本文为高光谱图像分类,参考链接https://github.com/KonstantinosF/Classification-of-Hyperspectral-Image
数据预处理
import numpy as np
from sklearn.decomposition import PCA
import scipy.io as sio
from sklearn.model_selection import train_test_split
from sklearn import preprocessing
import os
import random
from random import shuffle
from skimage.transform import rotate
import scipy.ndimage
def loadIndianPinesData():
data_path = os.path.join(os.getcwd(),'Data')
data = sio.loadmat(os.path.join(data_path, 'Indian_pines_corrected.mat'))['indian_pines_corrected']
labels = sio.loadmat(os.path.join(data_path, 'Indian_pines_gt.mat'))['indian_pines_gt']
return data, labels
def splitTrainTestSet(X, y, testRatio=0.10):
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=testRatio, random_state=345,
stratify=y)
return X_train, X_test, y_train, y_test
def oversampleWeakClasses(X, y):
uniqueLabels, labelCounts = np.unique(y, return_counts=True)
maxCount = np.max(labelCounts)
labelInverseRatios = maxCount / labelCounts
# repeat for every label and concat
newX = X[y == uniqueLabels[0], :, :, :].repeat(round(labelInverseRatios[0]), axis=0)
newY = y[y == uniqueLabels[0]].repeat(round(labelInverseRatios[0]), axis=0)
for label, labelInverseRatio in zip(uniqueLabels[1:], labelInverseRatios[1:]):
cX = X[y== label,:,:,:].repeat(round(labelInverseRatio), axis=0)
cY = y[y == label].repeat(round(labelInverseRatio), axis=0)
newX = np.concatenate((newX, cX))
newY = np.concatenate((newY, cY))
np.random.seed(seed=42)
rand_perm = np.random.permutation(newY.shape[0])
newX = newX[rand_perm, :, :, :]
newY = newY[rand_perm]
return newX, newY
def standartizeData(X):
newX = np.reshape(X, (-1, X.shape[2]))
scaler = preprocessing.StandardScaler().fit(newX)
newX = scaler.transform(newX)
newX = np.reshape(newX, (X.shape[0],X.shape[1],X.shape[2]))
return newX, scaler
def applyPCA(X, numComponents=75):
newX = np.reshape(X, (-1, X.shape[2]))
pca = PCA(n_components=numComponents, whiten=True)
newX = pca.fit_transform(newX)
newX = np.reshape(newX, (X.shape[0],X.shape[1], numComponents))
return newX, pca
def padWithZeros(X, margin=2):
newX = np.zeros((X.shape[0] + 2 * margin, X.shape[1] + 2* margin, X.shape[2]))
x_offset = margin
y_offset = margin
newX[x_offset:X.shape[0] + x_offset, y_offset:X.shape[1] + y_offset, :] = X
return newX
def createPatches(X, y, windowSize=5, removeZeroLabels = True):
margin = int((windowSize-1) / 2)
zeroPaddedX = padWithZeros(X, margin=margin)
# split patches
patchesData = np.zeros((X.shape[0] * X.shape[1], windowSize, windowSize, X.shape[2]))
patchesLabels = np.zeros((X.shape[0] * X.shape[1]))
patchIndex = 0
for r in range(margin, zeroPaddedX.shape[0] - margin):
for c in range(margin, zeroPaddedX.shape[1] - margin):
patch = zeroPaddedX[r - margin :r + margin + 1, c - margin :c + margin + 1]
patchesData[patchIndex, :, :, :] = patch
patchesLabels[patchIndex] = y[r-margin, c-margin]
patchIndex = patchIndex + 1
if removeZeroLabels:
patchesData = patchesData[patchesLabels>0,:,:,:]
patchesLabels = patchesLabels[patchesLabels>0]
patchesLabels -= 1
print('patchIndex',patchIndex)
return patchesData, patchesLabels
def AugmentData(X_train):
for i in range(int(X_train.shape[0]/2)):
patch = X_train[i,:,:,:]
num = random.randint(0,2)
if (num == 0):
flipped_patch = np.flipud(patch)
if (num == 1):
flipped_patch = np.fliplr(patch)
if (num == 2):
no = random.randrange(-180,180,30)
flipped_patch = scipy.ndimage.interpolation.rotate(patch, no,axes=(1, 0),
reshape=False, output=None, order=3, mode='constant', cval=0.0, prefilter=False)
patch2 = flipped_patch
X_train[i,:,:,:] = patch2
return X_train
def savePreprocessedData(X_trainPatches, X_testPatches, y_trainPatches, y_testPatches, windowSize, wasPCAapplied = False, numPCAComponents = 0, testRatio = 0.25):
if wasPCAapplied:
with open("./preprocessedData/XtrainWindowSize" + str(windowSize) + "PCA" + str(numPCAComponents) + "testRatio" + str(testRatio) + ".npy", 'bw') as outfile:
np.save(outfile, X_trainPatches)
with open("./preprocessedData/XtestWindowSize" + str(windowSize) + "PCA" + str(numPCAComponents) + "testRatio" + str(testRatio) + ".npy", 'bw') as outfile:
np.save(outfile, X_testPatches)
with open("./preprocessedData/ytrainWindowSize" + str(windowSize) + "PCA" + str(numPCAComponents) + "testRatio" + str(testRatio) + ".npy", 'bw') as outfile:
np.save(outfile, y_trainPatches)
with open("./preprocessedData/ytestWindowSize" + str(windowSize) + "PCA" + str(numPCAComponents) + "testRatio" + str(testRatio) + ".npy", 'bw') as outfile:
np.save(outfile, y_testPatches)
else:
with open("./preprocessedData/XtrainWindowSize" + str(windowSize) + ".npy", 'bw') as outfile:
np.save(outfile, X_trainPatches)
with open("./preprocessedData/XtestWindowSize" + str(windowSize) + ".npy", 'bw') as outfile:
np.save(outfile, X_testPatches)
with open("./preprocessedData/ytrainWindowSize" + str(windowSize) + ".npy", 'bw') as outfile:
np.save(outfile, y_trainPatches)
with open("./preprocessedData/ytestWindowSize" + str(windowSize) + ".npy", 'bw') as outfile:
np.save(outfile, y_testPatches)
if __name__ == "__main__":
# Global Variables
numComponents = 30
windowSize = 29
testRatio = 0.25
X, y = loadIndianPinesData()
print('X.shape',X.shape)
print('y.shape',y.shape)
X,pca = applyPCA(X,numComponents=numComponents)
print('X.shape',X.shape)
XPatches, yPatches = createPatches(X, y, windowSize=windowSize)
print('XPatches',XPatches.shape)
X_train, X_test, y_train, y_test = splitTrainTestSet(XPatches, yPatches, testRatio)
print('X_train.shape,y_train.shape',(X_train.shape,y_train.shape))
X_train, y_train = oversampleWeakClasses(X_train, y_train)
print('X_train.shape,y_train.shape',(X_train.shape,y_train.shape))
X_train = AugmentData(X_train)
print('X_train',X_train.shape)
savePreprocessedData(X_train, X_test, y_train, y_test, windowSize = windowSize,
wasPCAapplied=True, numPCAComponents = numComponents,testRatio = testRatio)
训练模型
import numpy as np
import scipy
import os
from keras import backend as K
from keras.models import Sequential
from keras.layers import Dense, Dropout, Flatten
from keras.layers import Conv2D, MaxPooling2D
from keras.optimizers import SGD
from keras import backend as K
K.clear_session()
K.set_image_dim_ordering('th')
from keras.utils import np_utils
#from sklearn.cross_validation import StratifiedKFold
PATH = os.getcwd()
print (PATH)
# Global Variables
windowSize = 29
numPCAcomponents = 30
testRatio = 0.25
X_train = np.load("/home/xm/桌面/sbc_project/data_analysis/preprocessedData/XtrainWindowSize"
+ str(windowSize) + "PCA" + str(numPCAcomponents) + "testRatio" + str(testRatio) + ".npy")
y_train = np.load("/home/xm/桌面/sbc_project/data_analysis/preprocessedData/ytrainWindowSize"
+ str(windowSize) + "PCA" + str(numPCAcomponents) + "testRatio" + str(testRatio) + ".npy")
# Reshape into (numberofsumples, channels, height, width)
X_train = np.reshape(X_train, (X_train.shape[0],X_train.shape[3], X_train.shape[1], X_train.shape[2]))
# convert class labels to on-hot encoding
y_train = np_utils.to_categorical(y_train)
# Define the input shape
input_shape= X_train[0].shape
print(input_shape)
# number of filters
C1 = 3*numPCAcomponents
# Define the model
model = Sequential()
model.add(Conv2D(C1, (3, 3), activation='relu', input_shape=input_shape))
model.add(Conv2D(3*C1, (3, 3), activation='relu'))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(6*numPCAcomponents, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(16, activation='softmax'))
sgd = SGD(lr=0.0001, decay=1e-6, momentum=0.9, nesterov=True)
model.compile(loss='categorical_crossentropy', optimizer=sgd, metrics=['accuracy'])
model.fit(X_train, y_train, batch_size=32, epochs=150)
import h5py
from keras.models import load_model
model.save('./model/my_model29.h5')
合成大图效果
# Import the necessary libraries
from sklearn.decomposition import PCA
import os
import scipy.io as sio
import numpy as np
from keras.models import load_model
from keras.utils import np_utils
from sklearn.metrics import classification_report, confusion_matrix
import itertools
import spectral
import matplotlib.pyplot as plt
import time
# Global Variables
windowSize = 29
numPCAcomponents = 30
testRatio = 0.25
def loadIndianPinesData():
data_path = os.path.join(os.getcwd(),'Data')
data = sio.loadmat(os.path.join(data_path, 'Indian_pines_corrected.mat'))['indian_pines_corrected']
labels = sio.loadmat(os.path.join(data_path, 'Indian_pines_gt.mat'))['indian_pines_gt']
return data, labels
def reports (X_test,y_test):
Y_pred = model.predict(X_test)
y_pred = np.argmax(Y_pred, axis=1)
target_names = ['Alfalfa', 'Corn-notill', 'Corn-mintill', 'Corn'
,'Grass-pasture', 'Grass-trees', 'Grass-pasture-mowed',
'Hay-windrowed', 'Oats', 'Soybean-notill', 'Soybean-mintill',
'Soybean-clean', 'Wheat', 'Woods', 'Buildings-Grass-Trees-Drives',
'Stone-Steel-Towers']
classification = classification_report(np.argmax(y_test, axis=1), y_pred, target_names=target_names)
confusion = confusion_matrix(np.argmax(y_test, axis=1), y_pred)
score = model.evaluate(X_test, y_test, batch_size=32)
Test_Loss = score[0]*100
Test_accuracy = score[1]*100
return classification, confusion, Test_Loss, Test_accuracy
def applyPCA(X, numComponents=75):
newX = np.reshape(X, (-1, X.shape[2]))
pca = PCA(n_components=numComponents, whiten=True)
newX = pca.fit_transform(newX)
newX = np.reshape(newX, (X.shape[0],X.shape[1], numComponents))
return newX, pca
def Patch(data,height_index,width_index):
#transpose_array = data.transpose((2,0,1))
#print transpose_array.shape
height_slice = slice(height_index, height_index+PATCH_SIZE)
width_slice = slice(width_index, width_index+PATCH_SIZE)
patch = data[height_slice, width_slice, :]
return patch
# X_test = np.load("/home/xm/桌面/sbc_project/data_analysis/preprocessedData/XtestWindowSize"
# + str(windowSize) + "PCA" + str(numPCAcomponents) + "testRAtio" + str(testRatio) + ".npy")
# y_test = np.load("/home/xm/桌面/sbc_project/data_analysis/preprocessedData/ytestWindowSize"
# + str(windowSize) + "PCA" + str(numPCAcomponents) + "testRatio" + str(testRatio) + ".npy")
X_test = np.load("/home/xm/桌面/sbc_project/data_analysis/preprocessedData/XtestWindowSize29PCA30testRatio0.25.npy")
y_test = np.load("/home/xm/桌面/sbc_project/data_analysis/preprocessedData/ytestWindowSize29PCA30testRatio0.25.npy")
X_test = np.reshape(X_test, (X_test.shape[0], X_test.shape[3], X_test.shape[1], X_test.shape[2]))
y_test = np_utils.to_categorical(y_test)
# load the model architecture and weights
model = load_model('./model/my_model29.h5')
classification, confusion, Test_loss, Test_accuracy = reports(X_test,y_test)
classification = str(classification)
confusion = str(confusion)
numComponents=30
file_name = 'report' + "WindowSize" + str(windowSize) + "PCA" + str(numComponents) + "testRatio" + str(testRatio) +".txt"
with open(file_name, 'w') as x_file:
x_file.write('{} Test loss (%)'.format(Test_loss))
x_file.write('\n')
x_file.write('{} Test accuracy (%)'.format(Test_accuracy))
x_file.write('\n')
x_file.write('\n')
x_file.write('{}'.format(classification))
x_file.write('\n')
x_file.write('{}'.format(confusion))
# load the original image
X, y = loadIndianPinesData()
X,pca = applyPCA(X,numComponents=numComponents)
height = y.shape[0]
width = y.shape[1]
PATCH_SIZE = 29
numComponents = 30
# calculate the predicted image
outputs = np.zeros((height,width))
for i in range(height-PATCH_SIZE+1):
for j in range(width-PATCH_SIZE+1):
target = int(y[int(i+PATCH_SIZE/2), int(j+PATCH_SIZE/2)])
if target == 0 :
continue
else :
image_patch=Patch(X,i,j)
#print (image_patch.shape)
X_test_image = image_patch.reshape(1,image_patch.shape[2],image_patch.shape[0],image_patch.shape[1]).astype('float32')
prediction = (model.predict_classes(X_test_image))
outputs[int(i+PATCH_SIZE/2)][int(j+PATCH_SIZE/2)] = prediction+1