Python+gdal實現遙感影像的PCA(主成分分析)

PCA基本步驟:
對數據進行歸一化處理(直接減去均值)
計算歸一化後的數據集的協方差矩陣
計算協方差矩陣的特徵值和特徵向量
保留最重要的k個特徵(通常k要小於n),也可以自己制定,也可以選擇一個閾值,然後通過前k個特徵值之和減去後面n-k個特徵值之和大於這個閾值,則選擇這個k
找出k個特徵值對應的特徵向量
將m * n的數據集乘以k個n維的特徵向量的特徵向量(n * k),得到最後降維的數據。

1、進行歸一化處理、計算協方差等
def meanX(dataX):
return np.mean(dataX, axis=0) # axis=0表示按照列來求均值,如果輸入list,則axis=1
def variance(X):
m, n = np.shape(X)
mu = meanX(X)
muAll = np.tile(mu, (m, 1))
X1 = X - muAll
variance = 1. / m * np.diag(X1.T * X1)
return variance
def normalize(X):
m, n = np.shape(X)
mu = meanX(X)
muAll = np.tile(mu, (m, 1))
X1 = X - muAll
X2 = np.tile(np.diag(X.T * X), (m, 1))
XNorm = X1 / X2
return XNorm
2、定義PCA函數,實現主成分分析
def pca(XMat, k):
average = meanX(XMat) #計算均值,爲進行歸一化做準備
m, n = np.shape(XMat) #行,列(7)
data_adjust = []
avgs = np.tile(average, (m, 1))
covX = np.cov(data_adjust.T) # 計算協方差矩陣
featValue, featVec = np.linalg.eig(covX) # 求解協方差矩陣的特徵值和特徵向量
index = np.argsort(-featValue) # 按照featValue進行從大到小排序
#確定主成分的個數
sum=0
max=0
for i in range(len(index)):
sum=sum+featValue[index[i]]
if max/sum<0.99:
max=max+featValue[index[i]]
k=k+1
finalData = []
print ("k = ",k)
if k > n:
print (“k must lower than feature number”)
return
else:
# 注意特徵向量是列向量,而numpy的二維矩陣(數組)a[m][n]中,a[1]表示第1行值
selectVec = np.matrix(featVec[index[:k]]) # 找出k個特徵值對應的特徵向量
reconData = (data_adjust * selectVec.T) + average[:,6]
#將m * n的數據集乘以k個n維的特徵向量的特徵向量(m * k),得到最後降維的數據。
print( np.shape(reconData))
array = []
array = np.array(array) # 列表轉數組
for j in range(k):
array = np.append(array, reconData[:,j]) #將reconData從二維(3列)數組轉化從一維數組(1維)
print (np.shape(array))
array1 = array.reshape(k, im_height, im_width) #將 一維數組 轉成 3維矩陣(k,高(行),寬(列))
out = ga.SaveArray(array1, os.path.join(path, “after.img”), format=“GTiff”, prototype=img)
return reconData

3、打開img或者tif格式的圖像進行PCA
path = “… 主成分分析”
input = os.listdir(path)
data = []
for i in input:
if i == ‘before.img’:
img = gdal.Open(os.path.join(path, i))
im_width = img.RasterXSize # 柵格矩陣的列數
im_height = img.RasterYSize # 柵格矩陣的行數
im_bands = img.RasterCount # 波段數
im_data = img.ReadAsArray(0, 0, im_width, im_height) # 獲取數據 將數據寫成數組,對應柵格矩陣
#im_data:(波段數,行,列)
for j in range(im_bands):
picture = im_data[j,:,:].flatten() # 變成一維數組
data.append(picture) #將各個波段合併在一個數組裏,一行爲一個波段(n個波段n行)
print (“data維數”, np.shape(data))
data = np.mat(data) #數組轉換爲矩陣
data1 = data.T #進行轉置
print (“data1維數”, np.shape(data1))
XMat = data1

-得到XMat:是一個numpy的矩陣格式,行表示樣本數,列表示特徵(每一列表示一個波段的信息,共n個波段)

k = 0 # k:表示取前k個特徵值對應的特徵向量
pca(XMat,k)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章