PCA-图像降维重构
1)去平均值:(即去中心化)。
2) 计算协方差矩阵。
3) 计算协方差矩阵的特征值与特征向量。
4) 对特征值从大到小排序,选择其中最大的K个。然后将其对应的k个特征向量分别作为行向量组成新的特征向量矩阵。
5) 利用新的特征向量矩阵重构原始图像。
import numpy as np
import cv2 as cv
from sklearn import decomposition
# 数据中心化
def centere_data(dataMat):
rows, cols = dataMat.shape
meanVal = np.mean(dataMat, axis=0) # 按列求均值,即求各个特征的均值
meanVal = np.tile(meanVal, (rows, 1))
newdata = dataMat - meanVal
return newdata, meanVal
'''
# 协方差矩阵
def Cov(dataMat):
meanVal = np.mean(dataMat, 0) # 压缩行,返回1*cols矩阵,对各列求均值
meanVal = np.tile(meanVal, (rows, 1)) # 返回rows行的均值矩阵
Z = dataMat - meanVal
Zcov = (1 / (rows - 1)) * Z.T * Z
return Zcov
'''
# 最小化降维造成的损失,确定k
def Percentage2n(eigVals, percentage):
sortArray = np.sort(eigVals) # 升序
sortArray = sortArray[-1::-1] # 逆转,即降序
arraySum = sum(sortArray)
temp_Sum = 0
num = 0
for i in sortArray:
temp_Sum += i
num += 1
if temp_Sum >= arraySum * percentage:
return num
# 得到最大的k个特征值和特征向量
def EigDV(covMat, p):
D, V = np.linalg.eig(covMat) # 得到特征值和特征向量
k = Percentage2n(D, p) # 确定k值
print("保留99%信息,降维后的特征个数:" + str(k) + "\n")
eigenvalue = np.argsort(D)
K_eigenValue = eigenvalue[-1:-(k + 1):-1]
K_eigenVector = V[:, K_eigenValue]
return K_eigenValue, K_eigenVector
# PCA算法
def PCA(data, p):
dataMat = np.float32(np.mat(data))
# 数据中心化
dataMat, meanVal = centere_data(dataMat)
# 计算协方差矩阵
covMat = np.cov(dataMat, rowvar=0)
# 选取最大的k个特征值和特征向量
D, V = EigDV(covMat, p)
# 得到降维后的数据
lowDataMat = dataMat * V
# 重构数据
reconDataMat = lowDataMat *V.T+ meanVal
return reconDataMat
if __name__ == '__main__':
img = cv.imread('D:/testimage/dog.jpg',0)
rows, cols = img.shape
#pca = decomposition.PCA()
print("降维前的特征个数:" + str(cols) + "\n")
print(img)
print('----------------------------------------')
PCA_img = PCA(img, 0.99)
PCA_img = PCA_img.astype(np.uint8)
print(PCA_img)
cv.imshow('test', PCA_img)
cv.imwrite('D:/testimage/dog-pca.jpg',PCA_img)
cv.waitKey(0)
cv.destroyAllWindows()
原图:
PCA:
降维前的特征个数:605;
降维后的特征个数:116。