PCA的实现方法

一般来说有两种方法,一种用神经网络计算 ,能绕过求关联矩阵,速度快,适合在线提取;另一种是用线代传统方法计算,缺点是计算复杂性高,不适合在线提取。当然,python和matlab都有现成的接口可以调用,嫌麻烦的话可以直接调用,这篇博客采用神经网络的方法。

以lenna的照片为例 ,演示用pca压缩图片

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from scipy.io import loadmat
from skimage import io
from sklearn.decomposition import PCA

A=io.imread('lenna.jpg')
A=A/255 
io.imshow(A)
plt.show()
print(A.shape)

在这里插入图片描述

分通道展示

fig,ax_array=plt.subplots(nrows=1,ncols=4,figsize=(32,32))
cmap_list=['Reds','Greens','Blues']
ax_array[0].imshow(A[:,:,:])
ax_array[0].set_xticks([])
ax_array[0].set_yticks([])
ax_array[0].set_title("Combined", size = 30,color='w')
for i in range(3):
    ax_array[i+1].imshow(A[:,:,i],cmap=cmap_list[i])
    ax_array[i+1].set_xticks([])
    ax_array[i+1].set_yticks([])
    ax_array[i+1].set_title(cmap_list[i][:-1], size = 30,color='w')
plt.tight_layout()
fig.suptitle("IMAGES OF EACH COLOR CHANNEL", size = 30, y = 0.6, fontweight = "bold",color='w')
plt.show()

图片分通道处理与变形

#三通道分别处理
R,G,B=A[:,:,0],A[:,:,1],A[:,:,2]
R.shape,G.shape,B.shape
#图片变形
train_R=np.zeros((64,4096))
train_G=np.zeros((64,4096))
train_B=np.zeros((64,4096))

count2=0
for i in range(0,64):
    for j in range(0,64):
        count=0
        for k in range(0,8):
            for d in range(0,8):
                train_R[count][count2]=R[i*8+k][j*8+d]
                train_G[count][count2]=G[i*8+k][j*8+d]
                train_B[count][count2]=B[i*8+k][j*8+d]
                count=count+1
        count2=count2+1
print(train_R[:,0].shape)

核心点:神经网络迭代计算主成分

#Ojia's PCA 用神经网络提取主成分
def Pca(data,max_epochs=1000, lr_rate=1e-3, e=1e-5):
    w = np.random.randn(64)
    count=0
    for epoch in range(max_epochs):
        randnumber=random.randint(0,4096)
        x=data[:,randnumber]
        y=dot(w,x)
        
        change = lr_rate * (y*x - y*y*w)
        w = w + change
        y = np.matmul(x, w)
        
        ch=np.sqrt(np.sum(change**2))
        if ch<e:
            count=count+1 
        else:
            count=0
        
        if count > 10 :
            print('迭代停止,已经收敛')
            return w 
    print('迭代停止,未收敛')
    return w

迭代计算三个通道的主成分

w_R = Pca(train_R,max_epochs=100000,lr_rate=0.02,e=0.02)
w_G = Pca(train_G,max_epochs=100000,lr_rate=0.02,e=0.02)
w_B = Pca(train_B,max_epochs=100000,lr_rate=0.02,e=0.02)

图片的压缩和解压

#压缩
print(w_R.shape)
compress_R=np.matmul(w_R,train_R )
compress_G=np.matmul(w_G,train_G )
compress_B=np.matmul(w_B,train_B )
w_R_T=w_R.reshape((len(w_R),1))
w_G_T=w_G.reshape((len(w_G),1))
w_B_T=w_B.reshape((len(w_B),1))

compress_R1=compress_R.reshape((1,len(compress_R)))
compress_G1=compress_G.reshape((1,len(compress_G)))
compress_B1=compress_B.reshape((1,len(compress_B)))
#解压
decompression_R=dot(w_R_T,compress_R1)
decompression_G=dot(w_G_T,compress_G1)
decompression_B=dot(w_B_T,compress_B1)
print(decompression_R.shape)

形状复原

#复原形状
dec_R=np.zeros((512,512))
dec_G=np.zeros((512,512))
dec_B=np.zeros((512,512))

count2=0
for i in range(0,64):
    for j in range(0,64):
        count=0
        for k in range(0,8):
            for d in range(0,8):
                dec_R[i*8+k][j*8+d]=decompression_R[count][count2]
                dec_G[i*8+k][j*8+d]=decompression_G[count][count2]
                dec_B[i*8+k][j*8+d]=decompression_B[count][count2]
                count=count+1
        count2=count2+1

展示压缩后的图像(只提取了最大的特征向量方向上的信息,压缩比64:1)

#展示解压后的图像
A_new=np.zeros(A.shape)
A_new[:,:,0]=dec_R
A_new[:,:,1]=dec_G
A_new[:,:,2]=dec_B

fig,ax_array=plt.subplots(nrows=1,ncols=4,figsize=(32,32))
cmap_list=['Reds','Greens','Blues']
ax_array[0].imshow(A_new[:,:,:])
ax_array[0].set_xticks([])
ax_array[0].set_yticks([])
ax_array[0].set_title("Combined", size = 30,color='g')
for i in range(3):
    ax_array[i+1].imshow(A_new[:,:,i],cmap=cmap_list[i])
    ax_array[i+1].set_xticks([])
    ax_array[i+1].set_yticks([])
    ax_array[i+1].set_title(cmap_list[i][:-1], size = 30,color='g')
plt.tight_layout()
fig.suptitle("IMAGES OF EACH COLOR CHANNEL(K={})".format(1), size = 30, y = 0.6, fontweight = "bold",color='g')
plt.show()

在这里插入图片描述

总结:要提升复原后图像的清晰度的话,可以多提取几个特征向量,只要在PCA部分稍作改动即可,但相应的压缩比也会下降。

Logo

技术共进,成长同行——讯飞AI开发者社区

更多推荐