奇异值分解SVD和图形处理
是一种重要的矩阵分解方法,在众多领域如信号处理、图像处理、机器学习等有着广泛应用。
A是一个m*n的一个矩阵,
那么A可以分解为-->U*S*V^T
这里的U是一个m*m的矩阵,S是奇异值矩阵,V^T是一个n*n的矩阵
奇异值只会分布在住对角线上,
奇异值分解的本质是为了进行降维,
比如:
上面的例子我们对A进行了降维,使得他的秩降低了1个
这样我们保留的特征比例是:
我们可以在matlab上运用SVD函数将我们的矩阵进行分解,并且将奇异值矩阵进行从大到小的排序。
SVD代码:
A = [4 0 1 6;0 0 5 1;2 1 3 2] % A : 3*4
[U,S,V] = svd(A)
这里就会自动压缩
这里的U*S*V’就会等于0
矩阵进行压缩和代码:
选择部分的特征值,使得我们保留的特征比例达到一定的比例,这样就可以得到一个达到保留了一定比例的,降低了秩的一个m*n的矩阵
function [compress_A] = mysvd(A, ratio)
% 函数作用:使用奇异值分解将矩阵A压缩到指定的特征比例
% 输入变量
% A:要压缩的m*n维的矩阵
% ratio:要保留原矩阵的特征比例(100%表示不压缩)
% 输出变量
% compress_A: 压缩后的矩阵
[U,S,V] = svd(A); % U:m*m S:m*n V : n*n
eigs = diag(S); % diag函数可以返回S的主对角线元素,即矩阵A的奇异值,并将其保存到列向量中
SUM = sum(eigs); % 计算所有奇异值的总和
temp = 0; % 新建临时变量,用于下面的循环,方便我们下面区计算特征比例
for i = 1: length(eigs) % 循环
temp =temp + eigs(i); % 每循环一次,就更新temp的值为原来的temp值+接下来的一个奇异值
if (temp/SUM) > ratio % 如果现在的比例超过了ratio,就退出循环
break
end
end
disp(['压缩后保留原矩阵的比例特征为:',num2str(roundn(100*temp/SUM,-2)),'%']) %roundn(x,-2)可将x四舍五入到小数点后两位
compress_A= U(:,1:i)*S(1:i,1:i)*V(:,1:i)';
end
注意:这里的降维本质只是降低了秩,而不是降低了矩阵的大小
下面利用上面的知识对我们的图片进行压缩
这里介绍下图片的一些知识:
RGB模式:RGB色彩就是常说的三原色,R代表Red(红色),G代表Green(绿色),B
代表Blue(蓝色)。自然界中肉眼所能看到的任何色彩都可以由这三种色彩混合叠加而成。
在一个像素点上是RGB三个颜色的叠加,
如果是黑白图片,那么RGB的值都是一样的
下面是对图片压缩的效果
对图片进行压缩处理
function []= photo_compress(photo_address, save_address, ratio, greycompress)
% 函数作用:利用SVD对图形进行压缩
% 输入变量
% photo_address:要压缩的图片存放的位置(建议输入完整的路径)
% save_address:将压缩后的图片保存的位置(建议输入完整的路径)
% ratio:要保留原矩阵的特征比例(100%表示不压缩)
% greycompress: 如果该值等于1,则会彩色的原图片转换为灰色图片后再压缩;默认值为0,表示不进行转换
% 输出变量
% 无(不需要输出,因为函数运行过程中已经将图片保存了~)
if nargin == 3 % 判断用户输入的参数,如果只输入了前三个参数,则默认最后的参数greycompress=0
greycompress = 0;
end
img = double(imread(photo_address));
% 图片保存的对象是 'uint8' 类型,需要将其转换为double类型才能进行奇异值分解的操作
% 注意: img是图形的像素矩阵,如果是彩色图片则是三维矩阵,如果是灰色图片(R=G=B)则是二维矩阵
% '赫本.jpg'是灰色的图片,得到的img类型是[914×1200]double
% '千与千寻.jpg'是彩色的图片,得到的img类型是[768×1024×3]double
% 因此我们可利用第三个维度的大小来判断图片是否为灰色的
% 灰色图片的只有两个维度,所以size(img ,3) == 1
if (greycompress == 1) && (size(img ,3) == 3) % 如果图片为彩色,且greycompress的值等于1,则会彩色的原图片转换为灰色图片后再压缩
img = double(rgb2gray(imread(photo_address))); % rgb2gray函数可以将彩色图片转换为灰色图片, 注意:输入的变量要为默认的'uint8' 类型的图片对象
end % 注意: grey(英)和gray(美)都表示灰色
if size(img ,3) == 3 % 判断图片是否为彩色的
R=img(:,:,1); % RGB色彩模式三要素:红色
G=img(:,:,2); % RGB色彩模式三要素:绿色
B=img(:,:,3); % RGB色彩模式三要素:蓝色
disp(['正在压缩: ',photo_address,'的红色要素'])
r = mysvd(R, ratio); % 调用自定义函数将R矩阵压缩成r
disp(['正在压缩: ',photo_address,'的绿色要素'])
g = mysvd(G, ratio); % 调用自定义函数将G矩阵压缩成g
disp(['正在压缩: ',photo_address,'的蓝色要素'])
b = mysvd(B, ratio); % 调用自定义函数将B矩阵压缩成b
compress_img=cat(3,r,g,b); % 根据三个RGB矩阵(压缩后的r、g、b)生成图片对象
else % 如果图片是灰色的要执行的步骤
disp(['正在压缩灰色图片: ',photo_address])
compress_img = mysvd(img, ratio); %如果是灰色图片的话,直接压缩img矩阵就好了
end
% 将压缩后的图片保存
imwrite(uint8(compress_img), save_address); % 如果你的矩阵是double格式的,导出时会自动将范围认为是[0 1],需要重新转换为uint8类型
end
我们只用按照格式传入我们的参数,就可以得到压缩过后的一个图片
一个文件夹内多个图片进行压缩处理
folder_name = ''; % 文件夹的绝对地址
dirOutput=dir(fullfile(folder_name, '*.jpg')); % 在名为folder_name的文件夹下找到所有以jpg结尾的文件
%fullfile函数可根据指定的文件夹和文件名构建完整的文件路径。
%dir函数的作用: 返回指定路径的结构体类型的数组。数组中每一个元素以结构体类型存储着每个子文件的信息(文件名,创建时间等)。
files={dirOutput.name}; % 将数组中的文件名保存到一个元胞数组中
n = length(files); % 图片的总数
ratio = 0.9; % 要保留的特征比例为90%
for i = 1:n
disp('-----------------')
photoname = files(i); % 注意此时的photoname是一个cell字符串对象,需要转换为字符串
% 如果我们直接把这个cell类型的变量,传递到其他函数中作为string类型使用,就会出现问题
name = photoname{1}; %直接这样取第一个元素就可以啦~cell数组中取元素使用大括号
photo_address = fullfile(folder_name, name); %图片的绝对地址
disp(photo_address)
save_address = fullfile(folder_name, strcat('compress_',name)); % 压缩后文件的保存地址
photo_compress(photo_address, save_address, ratio)
disp('------------------')
end
优缺点
优点:简化数据,去除噪声点,对数据降维(减少秩);
缺点:数据的转换可能难以理解;
应用场景
数据压缩:在图像等数据处理中,由于奇异值的重要性通常集中在前面少数几个较大的值上。通过保留较大的奇异值,忽略较小的奇异值,可以在损失较少信息的情况下对数据进行压缩。例如,对于一张图像,可以将其表示为矩阵形式,进行奇异值分解后,只保留前个较大的奇异值及其对应的左右奇异向量,然后重构图像,实现图像数据的压缩。
降维:在高维数据处理中,如机器学习的特征提取,利用奇异值分解可以将高维数据投影到低维空间,同时保留数据的主要特征。例如在主成分分析(PCA)中,本质上就是对数据矩阵进行奇异值分解,选取较大奇异值对应的成分作为主成分,实现数据的降维。
推荐系统:在基于用户 - 物品评分矩阵的推荐系统中,通过奇异值分解可以对评分矩阵进行分解和重构,填补缺失的评分数据,从而预测用户对物品的喜好程度,为用户提供个性化的推荐。