机器学习笔记——基于奇异值分解(SVD)的图像压缩(PIL)

此脚本的作用是图片压缩(清晰度尚可的情况下,可达到8倍以上的压缩比),是SVD的一个应用实践,涉及PIL、numpy库。
(python中处理图片的库比较多,比如PIL、OpenCV、matplotlib等。)


主逻辑:读取一个PNG图片,
RGB三原色特征使用svd进行主特征提取
根据不同清晰度使用全部(部分奇异值)进行图像重组,生成相应的jpg文件

by jntcf, 201712


# -*- coding: utf-8 -*-
from PIL import Image
import numpy as np

'''
此脚本的作用是图片压缩,是SVD的一个应用实践,涉及PIL、numpy库
(python中处理图片的库比较多,比如PIL、OpenCV、matplotlib等。)
主逻辑:读取一个PNG图片,
	RGB三原色特征使用svd进行主特征提取
	然后输出不同清晰度的jpg文件
	
by jntcf, 201712
'''



def rebuild_img(u, sigma, v, percent): #p表示奇异值的百分比
    m = len(u)
    n = len(v)
    a = np.zeros((m, n))

    #根据指定的清晰度提取奇异值
    #(清晰度越高,压缩比越低,提取的奇异值的个数也就越多,图片也就越不会失真)
    count = (int)(sum(sigma))
    curSum = 0
    k = 0
    while curSum <= count * percent:
        uk = u[:, k].reshape(m, 1)
        vk = v[k].reshape(1, n)
        a += sigma[k] * np.dot(uk, vk)
        curSum += sigma[k]
        k += 1

    a[a < 0] = 0
    a[a > 255] = 255
    #按照最近距离取整数,并设置参数类型为uint8
    return np.rint(a).astype("uint8")
	
def svdimage(filename, percent, outFolder):
    img = Image.open(filename, 'r')
    a = np.array(img)
	
    #提取RGB的主特征(奇异值SVD),处理后根据指定清晰度(百分比)返回新的RGB数据
    u, sigma, v = np.linalg.svd(a[:, :, 0])
    R = rebuild_img(u, sigma, v, percent)
    u, sigma, v = np.linalg.svd(a[:, :, 1])
    G = rebuild_img(u, sigma, v, percent)
    u, sigma, v = np.linalg.svd(a[:, :, 2])
    B = rebuild_img(u, sigma, v, percent)	
	
    #新的RGB叠加,保存为JPG图片
    I = np.stack((R, G, B), 2)
    Image.fromarray(I).save(outFolder+"svd_" + str(p * 100) + ".jpg")
	
if __name__ == '__main__':
    filename='e:\\1.png'#原始图片
	outFolder='e:\\'#处理后的jpg图片输出目录

    #按指定压缩比进行图片处理(0.1 ~ 0.9)
    #压缩比越大(最大到0.1)处理后的图片越模糊	
    for p in np.arange(0.1, 1, 0.1):
        svdimage(filename, p, outFolder)


你可能感兴趣的:(随笔)