为什么PCA图像与原始图像完全不相似?

问题描述 投票:0回答:2

我正在尝试在没有任何图像降维库的情况下实现 PCA。我尝试了 O'Reilly 计算机视觉书中的代码,并在示例 lenna 图片上实现了它:

    from PIL import Image
    from numpy import *

    def pca(X):
        num_data, dim = X.shape

        mean_X = X.mean(axis=0)
        X = X - mean_X

        if dim > num_data:
            # PCA compact trick
            M = np.dot(X, X.T) # covariance matrix
            e, U = np.linalg.eigh(M) # calculate eigenvalues an deigenvectors
            tmp = np.dot(X.T, U).T
            V = tmp[::-1] # reverse since the last eigenvectors are the ones we want
            S = np.sqrt(e)[::-1] #reverse since the last eigenvalues are in increasing order
            for i in range(V.shape[1]):
                V[:,i] /= S
        else:
            # normal PCA, SVD method
            U,S,V = np.linalg.svd(X)
            V = V[:num_data] # only makes sense to return the first num_data
        return V, S, mean_X
img=color.rgb2gray(io.imread('D:\lenna.png'))
x,y,z=pca(img)
plt.imshow(x)

但是 PCA 的图像图看起来根本不像原始图像。 据我所知,PCA 有点减少图像尺寸,但它仍然会在某种程度上类似于原始图像,但细节较低。代码有什么问题吗?

python image machine-learning pca
2个回答
1
投票

嗯,你的代码本身没有任何问题,但是如果我确实理解你真正想要做什么,你就不会显示right的东西!

我会为您的问题写下以下内容:

def pca(X, number_of_pcs):
    num_data, dim = X.shape

    mean_X = X.mean(axis=0)
    X = X - mean_X

    if dim > num_data:
        # PCA compact trick
        M = np.dot(X, X.T) # covariance matrix
        e, U = np.linalg.eigh(M) # calculate eigenvalues an deigenvectors
        tmp = np.dot(X.T, U).T
        V = tmp[::-1] # reverse since the last eigenvectors are the ones we want
        S = np.sqrt(e)[::-1] #reverse since the last eigenvalues are in increasing order
        for i in range(V.shape[1]):
            V[:,i] /= S

        return V, S, mean_X

    else:
        # normal PCA, SVD method
        U, S, V = np.linalg.svd(X, full_matrices=False)

        # reconstruct the image using U, S and V
        # otherwise you're just outputting the eigenvectors of X*X^T
        V = V.T
        S = np.diag(S)
        X_hat = np.dot(U[:, :number_of_pcs], np.dot(S[:number_of_pcs, :number_of_pcs], V[:,:number_of_pcs].T))      

        return X_hat, S, mean_X

这里的变化在于我们想要使用给定数量的特征向量(由

number_of_pcs
决定)来重建图像。

要记住的是,在

np.linalg.svd
中,U 的列是 X.X^T 的特征向量。

这样做时,我们获得以下结果(此处使用 1 和 10 主成分显示):


X_hat, S, mean_X = pca(img, 1)
plt.imshow(X_hat)


X_hat, S, mean_X = pca(img, 10)
plt.imshow(X_hat)

PS:请注意,由于 matplotlib.pyplot,图片不会以灰度显示,但这是一个非常小的问题。


0
投票

锋利的边缘。这就是为什么。如果图像具有锐利边缘或高对比度,则 PCA 无法很好地进行图像压缩。尝试一下咖啡图像,您会看到类似的东西。 将 numpy 导入为 np 将 matplotlib.pyplot 导入为 plt 从skimage导入数据 从 sklearn.decomposition 导入 PCA

加载咖啡图片

灰度图像 = data.coffee()

© www.soinside.com 2019 - 2024. All rights reserved.