PCA与图像压缩

PCA与图像压缩

2015-8-10

奇异值分解在图像压缩处理中有着重要的应用。假定一副图像有 n×n 个像素,如果将这 n2 个数据一起传送,往往会显得数据量太大。因此,我们希望能够改为传送另外一些比较少的数据,并且在接收端还能够利用这些传送的数据重构原图像。

不妨用矩阵 A 表示要传送的原 n×n 个像素。假定对矩阵 A 进行奇异值分解,便得到 A=UΣVT ,其中,奇异值按照从大到小的顺序排列。如果从中选择 k 个大奇异值以及这些奇异值对应的左和右奇异向量逼近原图像,便可以共用 k(2n+1) 个数值代替原来的 n×n 个图像数据。这 k(2n+1) 个被选择的新数据是矩阵 A 的前 k 个奇异值、 n×n 左奇向量矩阵 U 的前 k 列和 n×n 右奇向量矩阵 V 的前 k 列的元素。

比率:

ρ=n2k(2n+1)

称为图像的压缩比。显然,被选择的大奇异值的个数 k 应该满足条件 k(2n+1)<n2

k<n22n+1

因此,我们在传送图像的过程中,就无须传送 n×n 个原始数据,而只需要传送 k(2n+1) 个有关奇异值和奇异值向量的数据即可。在接收端,接收到奇异值 σ1,σ2,...,σk 以及左奇异向量 u1,u2,...,uk 和右奇异向量 v1,v2,...,vk 后,即可通过截尾的奇异值分解公式

A^=i=1kσiuivTi
重构出原图像。

一个容易理解的事实是:若 k 值偏小,即压缩比 ρ 偏大,则重构的图像的质量有可能不能令人满意。反之,过大的 k <script type="math/tex" id="MathJax-Element-96">k</script> 值又会导致压缩比过小,从而降低图像压缩和传送的效率。因此,需要根据不同种类的图像,选择合适的压缩比,以兼顾图像传送效率和重构质量。

matlab 实现代码如下

% 利用奇异值分解进行图像压缩
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

clear;
clc;

img = imread('lena.jpg');
img_gray = rgb2gray(img);

img_gray = imresize(img_gray,0.5);
[m,n] = size(img_gray);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% 奇异值分解
[u s v] = svd(double(img_gray));
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% 重构压缩后的图像
r = 4;    % 压缩率
K =round(2 * m * n / ( r * (m + n + 1)));

if K > min(m,n)
    K = min(m,n);
end

img_c = zeros(size(img_gray));

for i = 1:K
    img_c = img_c + s(i,i) * u(:,i) * v(:,i)';    % 利用前K个特征值重构原图像
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
subplot(2,2,1); imshow(img,[]); title('原彩色图');
subplot(2,2,2); imshow(img_gray,[]); title('原灰度图');
subplot(2,2,3); imshow(img_c,[]); title(['压缩比 r = ',num2str(r), ' 的压缩图']);
subplot(2,2,4); imshow(uint8(double(img_gray) - img_c));  title('压缩前后图像的差值'); % colormap cool

实验结果:
压缩比 r = 4
压缩比 r = 8

  • 4
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是使用PCA实现图像压缩的Python代码: ```python import numpy as np from PIL import Image def pca(X, k): # 数据矩阵每一维的平均值 n_samples, n_features = X.shape mean = np.array([np.mean(X[:, i]) for i in range(n_features)]) # 去平均值化 norm_X = X - mean # 计算协方差矩阵 scatter_matrix = np.dot(np.transpose(norm_X), norm_X) # 计算特征值和特征向量 eig_val, eig_vec = np.linalg.eig(scatter_matrix) # 将特征向量按照对应的特征值从大到小排序 eig_pairs = [(np.abs(eig_val[i]), eig_vec[:, i]) for i in range(n_features)] eig_pairs.sort(reverse=True) # 选取前k个最大的特征值对应的特征向量 feature = np.array([ele[1] for ele in eig_pairs[:k]]) # 将数据转换到新的低维空间中 data = np.dot(norm_X, np.transpose(feature)) # 重构数据 data_reconstruct = np.dot(data, feature) + mean # 返回降维后的数据和重构的数据 return data, data_reconstruct # 加载图片 img = Image.open('img.jpg') # 转换为灰度图 gray_img = img.convert('L') # 将图像转换为numpy矩阵 img_matrix = np.array(gray_img) # 将矩阵转换为一维向量 img_vec = img_matrix.reshape((img_matrix.shape[0]*img_matrix.shape[1], 1)) # PCA降维 data, data_reconstruct = pca(img_vec, 50) # 将降维后的数据重构成图像矩阵 img_matrix_reconstruct = data_reconstruct.reshape((img_matrix.shape[0], img_matrix.shape[1])) # 将矩阵转换为图片对象 compress_img = Image.fromarray(np.uint8(img_matrix_reconstruct)) # 显示压缩后的图片 compress_img.show() ``` 在上面的代码中,我们首先使用`PIL`库中的`Image`类加载图片,然后将其转换为灰度图,并将图像矩阵转换为一维向量。接着,我们调用`pca`函数对向量进行降维操作,这里我们只保留了前50个最大的特征值对应的特征向量。最后,我们将降维后的数据重构成图像矩阵,并使用`Image`类将其转换为图片对象并显示出来。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值