ok,既然秩可以度量相关性,而矩阵的相关性实际上就表示了矩阵的结构信息。如果矩阵之间各行的相关性很强,那么就表示这个矩阵实际可以投影到更低维的线性子空间,也就是用几个向量就可以完全表达了,它就是低秩的。所以总结的一点就是:如果矩阵表达的是结构性信息,例如图像、用户-商品推荐表等,那么这个矩阵各行之间存在一定的相关性,那这个矩阵一般是低秩的。
如果X是一个m行n列的数值矩阵,rank(x)是x的秩,假如rank (X)远小于m和n,则称x是低秩矩阵。低秩矩阵每行或每列都可以用其他的行或列线性表示,可见它包含大量的冗余信息。利用这种冗余信息,可以对数据进行恢复,也可以对数据进行特征提取。
总结一下:矩阵的秩的度量其实就是矩阵的行列之间的相关性。如果矩阵的各行或列是线性无关的,矩阵就是满秩的。非零元素的行数或列数决定了秩的多少。
图像处理中,rank可以理解为图像所包含的信息的丰富程度,在现实生活中,一张图片大部分是相似的。比如一张大草原的图片可以理解为,草原是由很多草组成的,而草是相似的,所以如果全是草,那么这张图所包含的信息量是很少的的,因为可以理解为草是草的复制品。而图中的蒙古包,人,马之类的则可以理解为图片所包含的信息,实际上,相对于只有草的草原图片和有草和蒙古包的草原图片,后者的秩是较高的。也就是说,图片中比较突兀的成分,比如蒙古包,比如人像照片中的红眼亮点,会增加图像矩阵的秩。而现实生活中一张不错的图片的秩其实是比较低的,如果图像的秩比较高,往往是因为图像中的噪声比较严重。比如拍照的时候ISO感光度设置过高造成噪点太过泛滥之类的。所以,图像处理的低秩性其实可以拿来去除照片中的噪点,电影中的雨丝也可以通过低秩表达的方式来去除。
低秩与稀疏。低秩是指矩阵的秩较小,稀疏是指矩阵中非零元素的个数少。如果对矩阵进行奇异值分解,并把其所有奇异值排列为一个向量,那么这个向量的稀疏性便对应于该矩阵的低秩性
图像中的雨滴可以看作是叠加在场景底层低频结构上的高频噪声。利用图像的低秩特征滤除雨滴的一种方法是使用一种称为矩阵分解的技术。
矩阵分解涉及将图像矩阵分解为其低秩和稀疏分量。低秩成分包含图像的底层结构,而稀疏成分包含高频噪声,包括雨滴。
一种流行的矩阵分解方法是奇异值分解 (SVD)。SVD将图像矩阵分解为三个矩阵:U、S和V,其中U和V是正交矩阵,S是包含图像矩阵奇异值的对角矩阵。
为了滤除雨滴,可以将奇异值矩阵S中的高频分量设置为零,并使用修改后的S矩阵和原始的U、V矩阵重建图像。这将从图像中去除高频噪声并留下场景的低频结构。
另一种方法是使用一种称为稳健主成分分析 (RPCA) 的技术。RPCA 是矩阵分解的一种变体,旨在在存在异常值的情况下将低秩成分与稀疏成分分开。在带有雨滴的图像的情况下,雨滴可以被认为是异常值。RPCA 可以用来提取图像的低秩分量,对应于场景的底层结构,同时抑制稀疏分量,对应于雨滴。
总之,利用图像的低秩特征可以帮助滤除图像中的雨滴。这可以使用矩阵分解等技术来实现,例如 SVD 和 RPCA,它们将图像的低频和高频分量分开。
import cvxpy as cp
import numpy as np
import matplotlib.pyplot as plt
from skimage import io, color# Load the image
img = io.imread('path/to/image.jpg')
# Convert the image to grayscale
gray_img = color.rgb2gray(img)# Define the optimization problem
X = cp.Variable((gray_img.shape[0], gray_img.shape[1]))
L = cp.Variable((gray_img.shape[0], gray_img.shape[1]))
S = cp.Variable((gray_img.shape[0], gray_img.shape[1]))
obj = cp.Minimize(cp.norm(L, 'nuc') + cp.norm(S, 1))
constraints = [X == L + S]
prob = cp.Problem(obj, constraints)# Solve the problem
prob.solve(solver=cp.SCS)# Get the low-rank and sparse components
L = L.value
S = S.value# Subtract the sparse component from the original image to obtain the filtered image
filtered_img = gray_img - S# Plot the original and filtered images side by side
fig, (ax1, ax2) = plt.subplots(ncols=2, figsize=(10, 5))
ax1.imshow(gray_img, cmap='gray')
ax1.set_title('Original Image')
ax2.imshow(filtered_img, cmap='gray')
ax2.set_title('Filtered Image')
plt.show()