基于matlab实现PCA图像压缩

数据在大数据时代成为一笔宝贵的财富,随之而来的是海量的数据的传输和存储问题。大量数据的重复和冗余让我们不得不对数据进行压缩处理。对于图像压缩的问题,目标是最小化压缩数据和最大化保留原样本数据,方法可以分为有损压缩和无损压缩。本文就是基于PCA实现的一种图像的有损压缩方法,项目基于matlab实现。

PCA相信大家都不陌生,就是用样本的协方差矩阵进行特征分解,求出协方差矩阵的特征值和特征向量,找出其中较大的几个特征值对应的特征向量作为主成分,并将样本向量向主成分上做投影,利用投影后的数据表示原数据,从而降维和去除冗余。这里不对PCA的具体原理说明。

PCA算法的步骤

先举个例子说明PCA算法的主要步骤,这样就可以直接写算法了,很简单。

  • 数据去中心化 $ (X_i-E(X)) $

    $$
    X = \left( {\begin{array}{{20}{c}}
    {100} & {200} & {300} & {400} & {500} \
    {150} & {450} & {560} & {750} & {1100} \
    \end{array}} \right) - \left( {\begin{array}{
    {20}{c}}
    {300} \
    {602} \
    \end{array}} \right) = \left( {\begin{array}{*{20}{c}}
    { - 200} & { - 100} & 0 & {100} & {200} \
    { - 452} & { - 152} & { - 42} & {148} & {498} \
    \end{array}} \right)
    $$

  • 计算协方差矩阵 $ C_x = XX’ $

$$
{C_x} = X{X^T} = \left( {\begin{array}{*{20}{c}}
{25000} & {55000} \
{55000} & {124770} \
\end{array}} \right)
$$

  • 对协方差矩阵进行奇异值分解$(SVD)$

$$
{C_x} = \left( {\begin{array}{{20}{c}}
{ - 0.9143} & {0.4051} \
{0.4051} & {0.9143} \
\end{array}} \right) \times \left( {\begin{array}{
{20}{c}}
{149140} & 0 \
0 & {630} \
\end{array}} \right) \times \left( {\begin{array}{*{20}{c}}
{ - 0.9143} & {0.4051} \
{0.4051} & {0.9143} \
\end{array}} \right)
$$

  • 取$K$个特征值和特征向量构成一个变幻矩阵(这里是1)

    $$
    {P_k} = \left( {\begin{array}{{20}{c}}
    {0.4051} \
    {0.9143} \
    \end{array}} \right) \times 149140 = \left( {\begin{array}{
    {20}{c}}
    {60410} \
    {136350} \
    \end{array}} \right)
    $$

  • 将原始投影映射到K维空间

$$
Y = P_K^TX
$$

设计实现PCA算法

其实不管是matlab还是python的sklearn包里面都包含了PCA算法,这里既然知道了算法的原理和具体步骤,完全可以自己设计实现。先贴出完整的matlab代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
%% 利用PCA对图像压缩
close all
clear
clc
%% 输入参数
num_val = 4; %取前num_val个特征值
size_block = 4; %取size_block*size_block块
%% 批量处理图片
img_path = 'D:\development\MATLAB\About_image\PCA\Origin_Data\NWPU VHR-10 dataset\negative image set\';
path_list = dir(strcat(img_path,'*.jpg'));
img_num = length(path_list);
if img_num>0
for pn = 1:10
img_name = path_list(pn).name;
origin_img = imread(strcat(img_path,img_name));
%fprintf("%d %s\n",pn,strcat(img_path,img_name));
%图像处理的具体方法
In = imresize(origin_img,[256,256]);
% 测试的图像灰度化
%In = rgb2gray(In);
% 将原图像矩阵分割成n*n的块,再转化为列矩阵,构成最终矩阵reIn
In = im2double(In);
[row ,rol] = size(In);
m = 0;
Data = zeros(size_block*size_block,(row/size_block)*(rol/size_block));
for i = 1:size_block:row
for j = 1:size_block:rol
m = m+1;
block = In(i:i+size_block-1,j:j+size_block-1);
Data(:,m) = block(:);
end
end
%PCA处理
Data1 = Data - ones(size(Data,1),1)*mean(Data); % 标准化处理
c = cov(Data1'); % 求矩阵协方差矩阵
[vec,val] = eig(c); % 求特征值和特征向量
% 按特征值降序排列
val = diag(val); % 从对角线拿出特征值
[val ,t] = sort(val,'descend'); % 特征值降序排列
vec = vec(:,t);
%重构图像
vec_new = vec(:,1:num_val);
rata = val./sum(val);
rata_sum = sum(rata(1:num_val));
fprintf("当前图片处理的进度是%g----",pn/img_num);
fprintf('当前图片选取%g个特征值的贡献率为:%g\n',num_val,rata_sum);
y = vec_new'* Data; % 映射 由公式:y=w'*x
Data2 = vec_new * y; % 重构图像
Data2 = Data2 + ones(size(vec_new, 1), 1) * mean(Data); % 加均值
m = 0;
for i = 1:size_block:row
for j = 1:size_block:rol
m = m + 1;
block1 = reshape(Data2(:, m), size_block, size_block); % 列向量块转化为方块
Out(i:i+size_block-1, j:j+size_block-1) = block1;
end
end
Out1 = Out(:,1:256);
Out2 = Out(:,257:2*256);
Out3 = Out(:,2*256+1:768);
RGB = cat(3,Out1,Out2,Out3);
imwrite(RGB,strcat('D:\development\MATLAB\About_image\PCA\After_PCA_Data\negative image set\',img_name));
%imwrite(RGB,strcat(img_name,'.jpg'));
end
end

这里说明一下,如果我们一开始输入时RGB图像,那么图像有三个通道,直接绘制的话,会是三个通道的图片。所以如果我们只需要灰度图片,在代码的一开始,先用rgb2gray函数把RGB图像转换为灰度图像。如果需要保存彩色图像,则需要在代码的最后,则需要用cat函数把三个通道组合在一起,输出为一张RGB图片。代码关键的地方都有注释。

运行结果

我们选的数据集一共只有150张图片,当我选择不同数量的主成分的时候,会得到不同的结果,主成分的选取越大,图像越接近原图像,压缩比例也就不好。

image-20200624164431654

然后看一下具体的压缩效果:

对于原始的图片:image-20200624164831044

对于压缩后图片:image-20200624164924880

啊哈还行哈,单个图片的对比就不放上来了,emmm影响排版。

  • Copyright: Copyright is owned by the author. For commercial reprints, please contact the author for authorization. For non-commercial reprints, please indicate the source.

扫一扫,分享到微信

微信分享二维码

请我喝杯咖啡吧~

支付宝
微信