├── HSI ├── 表格.pdf ├── 结果 │ ├── Pavia │ │ ├── 1D-Pavia.mat │ │ ├── 2D-Pavia.mat │ │ ├── RF-Pavia.mat │ │ ├── KNN-Pavia.mat │ │ ├── SVM-Pavia.mat │ │ ├── colormapPavia.mat │ │ └── HybridSN-Pavia.mat │ ├── 结果可视化 │ │ ├── 1D-Pavia.png │ │ ├── 2D-Pavia.png │ │ ├── HybridSN.png │ │ ├── RF-Pavia.png │ │ ├── 1D-Houston.png │ │ ├── 1D-Indian.png │ │ ├── 2D-Indian.png │ │ ├── KNN-Indian.png │ │ ├── KNN-Pavia.png │ │ ├── RF-Houston.png │ │ ├── RF-Indian.png │ │ ├── SVM-Pavia.png │ │ ├── SVM_Indian.png │ │ ├── KNN-Houston.png │ │ ├── SVM-Houston.png │ │ ├── HybridSN-Pavia.png │ │ └── HybridSN-Houston.png │ ├── Indian │ │ ├── 1D-Indian.mat │ │ ├── 2D-Indian.mat │ │ ├── RF-Indian.mat │ │ ├── colormap.mat │ │ ├── KNN-Indian.mat │ │ ├── SVM-Indian.mat │ │ └── HybridSN-Indian.mat │ └── Houston │ │ ├── 1D-Houston.mat │ │ ├── KNN-houston.mat │ │ ├── RF-Houston.mat │ │ ├── SVM-Houston.mat │ │ ├── HybridSN-Houston.mat │ │ └── colormapHuston.mat └── codes │ ├── colormaps │ ├── colormapPavia.mat │ ├── colormapHouston.mat │ └── colormapIndian.mat │ ├── __pycache__ │ └── utils.cpython-312.pyc │ ├── conventionalClassifiers.py │ ├── 1DimentioanlNN.py │ ├── 2DimentionalNN.py │ ├── HybridSN.py │ └── utils.py └── README.md /HSI/表格.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AStupidLight/Hyperspectral-Image-Classification/HEAD/HSI/表格.pdf -------------------------------------------------------------------------------- /HSI/结果/Pavia/1D-Pavia.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AStupidLight/Hyperspectral-Image-Classification/HEAD/HSI/结果/Pavia/1D-Pavia.mat -------------------------------------------------------------------------------- /HSI/结果/Pavia/2D-Pavia.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AStupidLight/Hyperspectral-Image-Classification/HEAD/HSI/结果/Pavia/2D-Pavia.mat -------------------------------------------------------------------------------- /HSI/结果/Pavia/RF-Pavia.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AStupidLight/Hyperspectral-Image-Classification/HEAD/HSI/结果/Pavia/RF-Pavia.mat -------------------------------------------------------------------------------- /HSI/结果/结果可视化/1D-Pavia.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AStupidLight/Hyperspectral-Image-Classification/HEAD/HSI/结果/结果可视化/1D-Pavia.png -------------------------------------------------------------------------------- /HSI/结果/结果可视化/2D-Pavia.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AStupidLight/Hyperspectral-Image-Classification/HEAD/HSI/结果/结果可视化/2D-Pavia.png -------------------------------------------------------------------------------- /HSI/结果/结果可视化/HybridSN.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AStupidLight/Hyperspectral-Image-Classification/HEAD/HSI/结果/结果可视化/HybridSN.png -------------------------------------------------------------------------------- /HSI/结果/结果可视化/RF-Pavia.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AStupidLight/Hyperspectral-Image-Classification/HEAD/HSI/结果/结果可视化/RF-Pavia.png -------------------------------------------------------------------------------- /HSI/结果/Indian/1D-Indian.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AStupidLight/Hyperspectral-Image-Classification/HEAD/HSI/结果/Indian/1D-Indian.mat -------------------------------------------------------------------------------- /HSI/结果/Indian/2D-Indian.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AStupidLight/Hyperspectral-Image-Classification/HEAD/HSI/结果/Indian/2D-Indian.mat -------------------------------------------------------------------------------- /HSI/结果/Indian/RF-Indian.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AStupidLight/Hyperspectral-Image-Classification/HEAD/HSI/结果/Indian/RF-Indian.mat -------------------------------------------------------------------------------- /HSI/结果/Indian/colormap.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AStupidLight/Hyperspectral-Image-Classification/HEAD/HSI/结果/Indian/colormap.mat -------------------------------------------------------------------------------- /HSI/结果/Pavia/KNN-Pavia.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AStupidLight/Hyperspectral-Image-Classification/HEAD/HSI/结果/Pavia/KNN-Pavia.mat -------------------------------------------------------------------------------- /HSI/结果/Pavia/SVM-Pavia.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AStupidLight/Hyperspectral-Image-Classification/HEAD/HSI/结果/Pavia/SVM-Pavia.mat -------------------------------------------------------------------------------- /HSI/结果/结果可视化/1D-Houston.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AStupidLight/Hyperspectral-Image-Classification/HEAD/HSI/结果/结果可视化/1D-Houston.png -------------------------------------------------------------------------------- /HSI/结果/结果可视化/1D-Indian.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AStupidLight/Hyperspectral-Image-Classification/HEAD/HSI/结果/结果可视化/1D-Indian.png -------------------------------------------------------------------------------- /HSI/结果/结果可视化/2D-Indian.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AStupidLight/Hyperspectral-Image-Classification/HEAD/HSI/结果/结果可视化/2D-Indian.png -------------------------------------------------------------------------------- /HSI/结果/结果可视化/KNN-Indian.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AStupidLight/Hyperspectral-Image-Classification/HEAD/HSI/结果/结果可视化/KNN-Indian.png -------------------------------------------------------------------------------- /HSI/结果/结果可视化/KNN-Pavia.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AStupidLight/Hyperspectral-Image-Classification/HEAD/HSI/结果/结果可视化/KNN-Pavia.png -------------------------------------------------------------------------------- /HSI/结果/结果可视化/RF-Houston.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AStupidLight/Hyperspectral-Image-Classification/HEAD/HSI/结果/结果可视化/RF-Houston.png -------------------------------------------------------------------------------- /HSI/结果/结果可视化/RF-Indian.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AStupidLight/Hyperspectral-Image-Classification/HEAD/HSI/结果/结果可视化/RF-Indian.png -------------------------------------------------------------------------------- /HSI/结果/结果可视化/SVM-Pavia.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AStupidLight/Hyperspectral-Image-Classification/HEAD/HSI/结果/结果可视化/SVM-Pavia.png -------------------------------------------------------------------------------- /HSI/结果/结果可视化/SVM_Indian.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AStupidLight/Hyperspectral-Image-Classification/HEAD/HSI/结果/结果可视化/SVM_Indian.png -------------------------------------------------------------------------------- /HSI/结果/Houston/1D-Houston.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AStupidLight/Hyperspectral-Image-Classification/HEAD/HSI/结果/Houston/1D-Houston.mat -------------------------------------------------------------------------------- /HSI/结果/Houston/KNN-houston.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AStupidLight/Hyperspectral-Image-Classification/HEAD/HSI/结果/Houston/KNN-houston.mat -------------------------------------------------------------------------------- /HSI/结果/Houston/RF-Houston.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AStupidLight/Hyperspectral-Image-Classification/HEAD/HSI/结果/Houston/RF-Houston.mat -------------------------------------------------------------------------------- /HSI/结果/Houston/SVM-Houston.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AStupidLight/Hyperspectral-Image-Classification/HEAD/HSI/结果/Houston/SVM-Houston.mat -------------------------------------------------------------------------------- /HSI/结果/Indian/KNN-Indian.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AStupidLight/Hyperspectral-Image-Classification/HEAD/HSI/结果/Indian/KNN-Indian.mat -------------------------------------------------------------------------------- /HSI/结果/Indian/SVM-Indian.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AStupidLight/Hyperspectral-Image-Classification/HEAD/HSI/结果/Indian/SVM-Indian.mat -------------------------------------------------------------------------------- /HSI/结果/Pavia/colormapPavia.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AStupidLight/Hyperspectral-Image-Classification/HEAD/HSI/结果/Pavia/colormapPavia.mat -------------------------------------------------------------------------------- /HSI/结果/结果可视化/KNN-Houston.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AStupidLight/Hyperspectral-Image-Classification/HEAD/HSI/结果/结果可视化/KNN-Houston.png -------------------------------------------------------------------------------- /HSI/结果/结果可视化/SVM-Houston.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AStupidLight/Hyperspectral-Image-Classification/HEAD/HSI/结果/结果可视化/SVM-Houston.png -------------------------------------------------------------------------------- /HSI/结果/Pavia/HybridSN-Pavia.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AStupidLight/Hyperspectral-Image-Classification/HEAD/HSI/结果/Pavia/HybridSN-Pavia.mat -------------------------------------------------------------------------------- /HSI/结果/结果可视化/HybridSN-Pavia.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AStupidLight/Hyperspectral-Image-Classification/HEAD/HSI/结果/结果可视化/HybridSN-Pavia.png -------------------------------------------------------------------------------- /HSI/结果/Houston/HybridSN-Houston.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AStupidLight/Hyperspectral-Image-Classification/HEAD/HSI/结果/Houston/HybridSN-Houston.mat -------------------------------------------------------------------------------- /HSI/结果/Houston/colormapHuston.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AStupidLight/Hyperspectral-Image-Classification/HEAD/HSI/结果/Houston/colormapHuston.mat -------------------------------------------------------------------------------- /HSI/结果/Indian/HybridSN-Indian.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AStupidLight/Hyperspectral-Image-Classification/HEAD/HSI/结果/Indian/HybridSN-Indian.mat -------------------------------------------------------------------------------- /HSI/结果/结果可视化/HybridSN-Houston.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AStupidLight/Hyperspectral-Image-Classification/HEAD/HSI/结果/结果可视化/HybridSN-Houston.png -------------------------------------------------------------------------------- /HSI/codes/colormaps/colormapPavia.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AStupidLight/Hyperspectral-Image-Classification/HEAD/HSI/codes/colormaps/colormapPavia.mat -------------------------------------------------------------------------------- /HSI/codes/colormaps/colormapHouston.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AStupidLight/Hyperspectral-Image-Classification/HEAD/HSI/codes/colormaps/colormapHouston.mat -------------------------------------------------------------------------------- /HSI/codes/colormaps/colormapIndian.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AStupidLight/Hyperspectral-Image-Classification/HEAD/HSI/codes/colormaps/colormapIndian.mat -------------------------------------------------------------------------------- /HSI/codes/__pycache__/utils.cpython-312.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AStupidLight/Hyperspectral-Image-Classification/HEAD/HSI/codes/__pycache__/utils.cpython-312.pyc -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Hyperspectral-Image-Classification 2 | 学校的大作业,大创打基础练手项目。最大的感想是从0开始完成一个项目还是非常困难的,故把我这个低水平代码放上来供大家参考。 3 | # 使用说明 4 | 1.数据集下载链接:https://pan.baidu.com/s/1nY0sP_MNp9qmtdlIyZevQw?pwd=z2qe 提取码: z2qe,包含IndianPines,Houston,Pavia 5 | 2.配置好项目所需要的python环境,将数据集下载好放置在根目录的datasets文件夹下。 6 | 3.使用python自带的可视化方法会存在精度的问题,对于Houston和Pavia这种比较大的数据集会边缘模糊,建议将最终的结果导出成mat文件,与所对应的colormap一并拿到matlab当中使用如下代码可视化: 7 | 8 | %% 结果展示 9 | result=uint8(result) 10 | colored_image=ind2rgb(result,colormap); 11 | imshow(colored_image); 12 | title('Result'); 13 | 14 | # 特别感谢 15 | 项目中的数据集和一些代码均来自于这个开源的代码https://github.com/danfenghong/IEEE_TGRS_SpectralFormer 16 | 初学者看这里的代码会有一些头大,但是还是为我提供了非常好的学习素材,特此鸣谢! 17 | 18 | # 联系 19 | 代码前后由于时间跨度比较长,并不能保证里面的注释完全正确。 20 | 如有任何问题,欢迎与我联系:xiaoyuchen@bjtu.edu.cn 21 | -------------------------------------------------------------------------------- /HSI/codes/conventionalClassifiers.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import utils 3 | import argparse 4 | from scipy.io import loadmat 5 | from scipy.io import savemat 6 | import matplotlib.pyplot as plt 7 | from matplotlib import colors 8 | 9 | #分类器 10 | from sklearn.neighbors import KNeighborsClassifier 11 | from sklearn.ensemble import RandomForestClassifier 12 | from sklearn.naive_bayes import CategoricalNB#categoricalNB离散化的朴素贝叶斯分类器 13 | from sklearn.svm import SVC 14 | #评价指标、准确率 15 | from sklearn.metrics import confusion_matrix 16 | 17 | #用程序的参数来确定目前使用的数据集和训练方法 18 | parser=argparse.ArgumentParser('Conventional Classifiers') 19 | 20 | parser.add_argument('dataset',choices=['Indian','Pavia','Houston'],default='Indian') 21 | parser.add_argument('mode',choices=['KNN','NB','SVM','RF'],default='KNN') 22 | 23 | args=parser.parse_args() 24 | 25 | data,data_TE,data_TR,data_label=utils.loaddata(args.dataset) 26 | 27 | # 标准化数据 28 | 29 | #创建一个同样大小的矩阵用于保存数据 30 | input_normalize = np.zeros(data.shape) 31 | #data。shape【2】指的是对于每一个波段来做标准化,对于每一个波段,找最大最小值,再归一化 32 | for i in range(data.shape[2]): 33 | input_max = np.max(data[:, :, i]) 34 | input_min = np.min(data[:, :, i]) 35 | input_normalize[:, :, i] = (data[:, :, i] - input_min) / (input_max - input_min) 36 | 37 | total_pos_train, total_pos_test, total_pos_true, number_train, number_test, number_true=utils.chooose_train_and_test_point(data_TR,data_TE,data_label,16) 38 | #number_train==[50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 15, 15, 15] 39 | #number_test==[1384, 784, 184, 447, 697, 439, 918, 2418, 564, 162, 1244, 330, 45, 39, 11, 5] 40 | #number_true==[10659, 1434, 834, 234, 497, 747, 489, 968, 2468, 614, 212, 1294, 380, 95, 54, 26, 20] 41 | #number_true多一个维数是背景像素,10659个 42 | 43 | #sum(number_train)==695,恰好等于total_pos_train里元素的数量 44 | 45 | width,height,band=input_normalize.shape 46 | 47 | #将pos和label转换为分类器所需要的形式 48 | #X_train x个像素*200个波段 49 | #y_train 1*一个label 50 | #一一对应 51 | 52 | #input_normalize 145*145*200,其中所有的数字都被限制在(0,1)之间 53 | x_train,x_test,x_true=utils.toStandardformX(input_normalize, band, total_pos_train, total_pos_test, total_pos_true,number_train, number_test, number_true) 54 | #x_train=659*200,659个坐标,200个波段 55 | 56 | y_train,y_test,y_true=utils.toStandardformY(data_label, band, total_pos_train, total_pos_test, total_pos_true,number_train, number_test, number_true) 57 | 58 | 59 | global pre,pree 60 | if args.mode=='KNN': 61 | #使用的是KNN 62 | #k值等于10 63 | knn=KNeighborsClassifier(n_neighbors=10) 64 | knn.fit(x_train,y_train) 65 | pre= knn.predict(x_test) 66 | pree=knn.predict(x_true) 67 | elif args.mode=='RF': 68 | #使用随机森林 69 | #n_estimate值设置为200,即代表着200棵决策树 70 | RF=RandomForestClassifier(n_estimators=200) 71 | RF.fit(x_train,y_train) 72 | pre=RF.predict(x_test) 73 | pree=RF.predict(x_true) 74 | elif args.mode=='NB': 75 | #使用朴素贝叶斯算法来预测 76 | #***************************有使用的bug,使用不了 77 | NB=CategoricalNB(min_categories=16) 78 | NB.fit(x_train, y_train) 79 | pre = NB.predict(x_test) 80 | pree=NB.predict(x_true) 81 | elif args.mode=='SVM': 82 | #最好使用五折交叉认证来确定最好的c和gamma 83 | #gamma的取值范围 84 | SVM=SVC(kernel='rbf',C=10000,gamma=0.01) 85 | SVM.fit(x_train, y_train) 86 | pre = SVM.predict(x_test) 87 | pree=SVM.predict(x_true) 88 | 89 | matrix = confusion_matrix(y_test, pre) 90 | #混淆矩阵的每一行表示某一类真实值,全部加起来等于某一类的总数 91 | utils.cal_class_results(matrix,y_train) 92 | 93 | classification_result=np.zeros(shape=(width,height),dtype=float) 94 | 95 | 96 | 97 | for i in range(sum(number_true)): 98 | classification_result[total_pos_true[i][0],total_pos_true[i][1]]+=pree[i] 99 | savemat('RF-Pavia.mat', mdict={"result":classification_result}) 100 | 101 | 102 | 103 | OA, AA_mean, Kappa, AA = utils.cal_results(matrix) 104 | print() 105 | print("Overall metrics:") 106 | print("OA: {:.4f} | AA: {:.4f} | Kappa: {:.4f}".format(OA, AA_mean, Kappa)) -------------------------------------------------------------------------------- /HSI/codes/1DimentioanlNN.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import utils 3 | import torch.utils.data as Data 4 | import torch.nn as nn 5 | import numpy as np 6 | import torch 7 | from sklearn.metrics import confusion_matrix 8 | 9 | import os 10 | os.environ['CUDA_LAUNCH_BLOCKING'] = '1' 11 | 12 | parser=argparse.ArgumentParser("1DNN") 13 | parser.add_argument('dataset',choices=['Indian','Houston','Pavia'],default='Indian') 14 | parser.add_argument('epoch', type=int, default=500, help='epoch number') 15 | args=parser.parse_args() 16 | 17 | data,data_TE,data_TR,data_label=utils.loaddata(args.dataset) 18 | 19 | input_normalize=utils.normalize(data) 20 | 21 | total_pos_train, total_pos_test, total_pos_true, number_train, number_test, number_true = utils.chooose_train_and_test_point( 22 | data_TR, data_TE, data_label, 16) 23 | width,height,band=input_normalize.shape 24 | 25 | # input_normalize 145*145*200,其中所有的数字都被限制在(0,1)之间 26 | x_train, x_test, x_true = utils.toStandardformX(input_normalize, band, total_pos_train, total_pos_test, 27 | total_pos_true, number_train, number_test, number_true) 28 | # x_train=659*200,659个坐标,200个波段 29 | 30 | y_train, y_test, y_true = utils.toStandardformY(data_label, band, total_pos_train, total_pos_test, total_pos_true, 31 | number_train, number_test, number_true) 32 | 33 | # 将numpy的ndarray类型转换为torch的tensor类型,再用tensordataset读取 34 | X_train = torch.from_numpy(x_train).type(torch.FloatTensor) 35 | Y_train = torch.from_numpy(y_train).type(torch.LongTensor) 36 | Label_train = Data.TensorDataset(X_train, Y_train) 37 | X_test = torch.from_numpy(x_test).type(torch.FloatTensor) 38 | Y_test = torch.from_numpy(y_test).type(torch.LongTensor) 39 | Label_test = Data.TensorDataset(X_test, Y_test) 40 | 41 | X_true = torch.from_numpy(x_true).type(torch.FloatTensor) 42 | Y_true = torch.from_numpy(y_true).type(torch.LongTensor) 43 | Label_true = Data.TensorDataset(X_true, Y_true) 44 | 45 | label_ture_loader = Data.DataLoader(Label_true, batch_size=64, shuffle=False) 46 | 47 | 48 | label_train_loader = Data.DataLoader(Label_train, batch_size=64, shuffle=True) 49 | label_test_loader = Data.DataLoader(Label_test, batch_size=64, shuffle=False) 50 | 51 | class OneDNN(nn.Module): 52 | def __init__(self,band): 53 | super().__init__() 54 | self.conv1=nn.Conv1d(in_channels=1,out_channels=8,stride=1,kernel_size=5) 55 | self.r=nn.ReLU() 56 | self.flat=nn.Flatten(1) 57 | #bn batch normalize 58 | self.pool=nn.MaxPool1d(2,stride=2) 59 | self.conv2=nn.Conv1d(in_channels=8,out_channels=16,kernel_size=5,stride=1) 60 | self.conv3=nn.Conv1d(in_channels=16,out_channels=32,kernel_size=5,stride=1) 61 | if args.dataset=='Indian': 62 | self.l=nn.Linear(1376,96) 63 | if args.dataset == 'Pavia': 64 | self.l = nn.Linear(576, 96) 65 | if args.dataset == 'Houston': 66 | self.l = nn.Linear(928, 96) 67 | self.ll=nn.Linear(96,16) 68 | 69 | def forward(self,input): 70 | output=self.conv1(input) 71 | output=self.r(output) 72 | output=self.pool(output) 73 | output=self.conv2(output) 74 | output=self.r(output) 75 | output=self.pool(output) 76 | output=self.conv3(output) 77 | output=self.r(output) 78 | output=self.flat(output) 79 | output=self.l(output) 80 | output=self.ll(output) 81 | return output 82 | 83 | NN=OneDNN(band) 84 | NN=NN.cuda() 85 | loss_fn=nn.CrossEntropyLoss() 86 | loss_fn=loss_fn.cuda() 87 | optimizer=torch.optim.Adam(NN.parameters(),lr=0.01) 88 | 89 | total_train_step=0 90 | 91 | 92 | for i in range(args.epoch): 93 | 94 | total_train_step=0 95 | # print("第{}轮开始".format(i+1)) 96 | for data in label_train_loader: 97 | # print("{}".format(total_train_step)) 98 | d,target=data 99 | #神经网络的输入是(batch,channel,height,width) 100 | #对于1d的卷积,则要求输入是(batch,1,channels) 101 | d = torch.unsqueeze(d, 1) 102 | d=d.cuda() 103 | target=target.cuda() 104 | outputs=NN(d) 105 | #outputs的格式应该为batch,类别,对象数(在此任务中为1) 106 | outputs=torch.unsqueeze(outputs,2) 107 | target=torch.unsqueeze(target,1) 108 | temp=torch.ones((target.shape[0],1)).type(torch.LongTensor).cuda() 109 | target=target.sub(temp) 110 | loss = loss_fn(outputs, target) 111 | 112 | optimizer.zero_grad() 113 | loss.backward() 114 | optimizer.step() 115 | #print("训练次数{}".format(total_train_step+1)) 116 | total_train_step+=1 117 | 118 | 119 | 120 | if (i + 1 == args.epoch): 121 | pree = torch.zeros(y_true.shape).type(torch.LongTensor) 122 | k = 0 123 | with torch.no_grad(): 124 | for data in label_ture_loader: 125 | d, targets = data 126 | d = torch.unsqueeze(d, 1) 127 | d = d.cuda() 128 | targets = targets.cuda() 129 | outputs = NN(d) 130 | outputs = torch.unsqueeze(outputs, 2) 131 | targets = torch.unsqueeze(targets, 1) 132 | temp = torch.ones((targets.shape[0], 1)).type(torch.LongTensor).cuda() 133 | targets = targets.sub(temp) 134 | # 构造pre矩阵 135 | outputs = outputs.squeeze() 136 | a = torch.argmax(outputs, dim=1) 137 | pree[k:k + a.shape[0]] = a 138 | k += a.shape[0] 139 | # 将格式转换为ndarry 140 | pree = pree.type(torch.LongTensor).numpy() 141 | t = np.ones(pree.shape) 142 | pree = np.add(pree, t) 143 | 144 | utils.save_result(pree, width, height, total_pos_true, number_true, "1D-Houston") 145 | # 跑完一轮之后,要用测试数据集评估一下训练之后的结果 146 | # with表示不会对源模型的参数做任何的修改 147 | elif (i+1)%100==0: 148 | print("Epoch:{}".format(i+1)) 149 | total_test_loss = 0 150 | pre = torch.zeros(size=y_test.shape) 151 | k = 0 152 | with torch.no_grad(): 153 | for data in label_test_loader: 154 | 155 | d, targets = data 156 | d = torch.unsqueeze(d, 1) 157 | d = d.cuda() 158 | targets = targets.cuda() 159 | outputs = NN(d) 160 | outputs = torch.unsqueeze(outputs, 2) 161 | targets = torch.unsqueeze(targets, 1) 162 | temp = torch.ones((targets.shape[0], 1)).type(torch.LongTensor).cuda() 163 | targets = targets.sub(temp) 164 | loss = loss_fn(outputs, targets) 165 | # item函数把tensor变成数字 166 | total_test_loss += loss.item() 167 | 168 | #构造pre矩阵 169 | outputs=outputs.squeeze() 170 | a=torch.argmax(outputs,dim=1) 171 | pre[k:k+a.shape[0]]=a 172 | k+=a.shape[0] 173 | #将格式转换为ndarry 174 | pre=pre.type(torch.LongTensor).numpy() 175 | t=np.ones(pre.shape) 176 | pre=np.add(pre,t) 177 | matrix = confusion_matrix(y_test, pre) 178 | 179 | OA, AA_mean, Kappa, AA = utils.cal_results(matrix) 180 | print() 181 | print("Overall metrics:") 182 | print("OA: {:.4f} | AA: {:.4f} | Kappa: {:.4f}".format(OA, AA_mean, Kappa)) 183 | print("total_loss:{:.4f}".format(total_test_loss)) 184 | utils.cal_class_results(matrix,y_test) 185 | 186 | -------------------------------------------------------------------------------- /HSI/codes/2DimentionalNN.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import utils 3 | import torch.utils.data as Data 4 | import torch.nn as nn 5 | import numpy as np 6 | import torch 7 | from sklearn.metrics import confusion_matrix 8 | 9 | from sklearn.decomposition import PCA 10 | 11 | parser=argparse.ArgumentParser("2DNN") 12 | parser.add_argument('dataset',choices=['Indian','Houston','Pavia'],default='Indian') 13 | parser.add_argument('epoch', type=int, default=500, help='epoch number') 14 | parser.add_argument('patch',type=int,help='size of input',default=7) 15 | parser.add_argument('usePCA',type=bool,default=False) 16 | args=parser.parse_args() 17 | 18 | data,data_TE,data_TR,data_label=utils.loaddata(args.dataset) 19 | 20 | input_normalize=utils.normalize(data) 21 | 22 | total_pos_train, total_pos_test, total_pos_true, number_train, number_test, number_true = utils.chooose_train_and_test_point( 23 | data_TR, data_TE, data_label, 16) 24 | height,width,band=input_normalize.shape 25 | #对于2D的CNN,我们需要对于获取其周边的像素 26 | #在1DCNN当中,我们传入的数据的形状是【x,200】,其中x为全部打散的波段 27 | #我们现在希望传入输入的大小是【x,width,height,band】 28 | #再对于每一张小图匹配一个标签 29 | 30 | if args.usePCA==True: 31 | #n_components表示的是期待将为之后的维度,band从200将为30 32 | pca=PCA(n_components=30) 33 | input_normalize=input_normalize.reshape(-1,band) 34 | input_normalize=pca.fit_transform(input_normalize) 35 | input_normalize=input_normalize.reshape(height,width,-1) 36 | band = 30 37 | #在测试当中我们向网络输入7*7的小patch,这意味着我们需要对于原图像的边界进行3的像素的padding 38 | #我们在这里不使用0来填充,我们使用了镜像的填充方法 39 | 40 | #调用utils里面的mirror方法来实现这个功能 41 | #对于Indian,原输入是145*145*200,左边增加三个像素右边增加三个像素,最终的结果就是151*151*200 42 | input_mirror=utils.mirror(height, width, band, input_normalize, patch=args.patch) 43 | 44 | 45 | #获取每一个周围的像素,大小为【x,7,7,200】 46 | x_train,x_test,x_true=utils.train_and_test_data(input_mirror,band,total_pos_train,total_pos_test,total_pos_true,patch=args.patch) 47 | 48 | y_train, y_test, y_true = utils.toStandardformY(data_label, band, total_pos_train, total_pos_test, total_pos_true, 49 | number_train, number_test, number_true) 50 | 51 | # 将numpy的ndarray类型转换为torch的tensor类型,再用tensordataset读取 52 | X_train = torch.from_numpy(x_train).type(torch.FloatTensor) 53 | Y_train = torch.from_numpy(y_train).type(torch.LongTensor) 54 | Label_train = Data.TensorDataset(X_train, Y_train) 55 | X_test = torch.from_numpy(x_test).type(torch.FloatTensor) 56 | Y_test = torch.from_numpy(y_test).type(torch.LongTensor) 57 | Label_test = Data.TensorDataset(X_test, Y_test) 58 | 59 | X_true = torch.from_numpy(x_true).type(torch.FloatTensor) 60 | Y_true = torch.from_numpy(y_true).type(torch.LongTensor) 61 | Label_true = Data.TensorDataset(X_true, Y_true) 62 | 63 | label_ture_loader = Data.DataLoader(Label_true, batch_size=64, shuffle=False) 64 | 65 | label_train_loader = Data.DataLoader(Label_train, batch_size=64, shuffle=True) 66 | label_test_loader = Data.DataLoader(Label_test, batch_size=64, shuffle=False) 67 | 68 | 69 | class TwoDNN(nn.Module): 70 | def __init__(self,band): 71 | super().__init__() 72 | self.conv1 = nn.Sequential( 73 | nn.Conv2d(in_channels=band, out_channels=6, kernel_size=4, stride=1), 74 | nn.MaxPool2d(kernel_size=2) 75 | ) 76 | 77 | self.conv2 = nn.Sequential( 78 | nn.Conv2d(in_channels=6, out_channels=16, kernel_size=5, stride=1), 79 | nn.MaxPool2d(kernel_size=2) 80 | ) 81 | self.f=nn.Flatten() 82 | self.fc1 = nn.Sequential( 83 | nn.Linear(in_features=400, out_features=120) 84 | ) 85 | self.fc2 = nn.Sequential( 86 | nn.Linear(in_features=120, out_features=84) 87 | ) 88 | self.fc3 = nn.Sequential( 89 | nn.Linear(in_features=84, out_features=16) 90 | ) 91 | 92 | def forward(self, input): 93 | conv1_output = self.conv1(input) # [28,28,1]-->[24,24,6]-->[12,12,6] 94 | conv2_output = self.conv2(conv1_output) # [12,12,6]-->[8,8,16]-->[4,4,16] 95 | conv2_output = self.f(conv2_output) # [n,4,4,16]-->[n,4*4*16],其中n代表个数 96 | fc1_output = self.fc1(conv2_output) # [n,256]-->[n,120] 97 | fc2_output = self.fc2(fc1_output) # [n,120]-->[n,84] 98 | fc3_output = self.fc3(fc2_output) # [n,84]-->[n,10] 99 | return fc3_output 100 | 101 | 102 | 103 | NN=TwoDNN(band) 104 | NN=NN.cuda() 105 | loss_fn=nn.CrossEntropyLoss() 106 | loss_fn=loss_fn.cuda() 107 | optimizer=torch.optim.Adam(NN.parameters(),lr=0.01) 108 | 109 | total_train_step=0 110 | 111 | 112 | for i in range(args.epoch): 113 | 114 | total_train_step=0 115 | # print("第{}轮开始".format(i+1)) 116 | for data in label_train_loader: 117 | #print("{}".format(total_train_step)) 118 | d,target=data 119 | #神经网络的输入是(batch,channel,height,width) 120 | #permute 按序号交换维度 121 | d=d.permute(0,3,1,2) 122 | d=d.cuda() 123 | target=target.cuda() 124 | outputs=NN(d) 125 | #outputs的格式应该为batch,类别,对象数(在此任务中为1) 126 | outputs=torch.unsqueeze(outputs,2) 127 | target=torch.unsqueeze(target,1) 128 | temp=torch.ones((target.shape[0],1)).type(torch.LongTensor).cuda() 129 | target=target.sub(temp) 130 | loss = loss_fn(outputs, target) 131 | 132 | optimizer.zero_grad() 133 | loss.backward() 134 | optimizer.step() 135 | #print("训练次数{}".format(total_train_step+1)) 136 | total_train_step+=1 137 | 138 | if (i + 1 == args.epoch): 139 | pree = torch.zeros(y_true.shape).type(torch.LongTensor) 140 | k = 0 141 | with torch.no_grad(): 142 | for data in label_ture_loader: 143 | d, targets = data 144 | d = d.permute(0, 3, 1, 2) 145 | d = d.cuda() 146 | targets = targets.cuda() 147 | outputs = NN(d) 148 | outputs = torch.unsqueeze(outputs, 2) 149 | targets = torch.unsqueeze(targets, 1) 150 | temp = torch.ones((targets.shape[0], 1)).type(torch.LongTensor).cuda() 151 | targets = targets.sub(temp) 152 | # 构造pre矩阵 153 | outputs = outputs.squeeze() 154 | a = torch.argmax(outputs, dim=1) 155 | pree[k:k + a.shape[0]] = a 156 | k += a.shape[0] 157 | # 将格式转换为ndarry 158 | pree = pree.type(torch.LongTensor).numpy() 159 | t = np.ones(pree.shape) 160 | pree = np.add(pree, t) 161 | 162 | utils.save_result(pree, height,width, total_pos_true, number_true, "2D-Pavia") 163 | # 跑完一轮之后,要用测试数据集评估一下训练之后的结果 164 | 165 | # 跑完一轮之后,要用测试数据集评估一下训练之后的结果 166 | # with表示不会对源模型的参数做任何的修改 167 | if (i+1)%10==0: 168 | print("Epoch:{}".format(i+1)) 169 | total_test_loss = 0 170 | pre = torch.zeros(size=y_test.shape) 171 | k = 0 172 | with torch.no_grad(): 173 | for data in label_test_loader: 174 | 175 | d, targets = data 176 | d = d.permute(0, 3, 1, 2) 177 | d = d.cuda() 178 | targets = targets.cuda() 179 | outputs = NN(d) 180 | outputs = torch.unsqueeze(outputs, 2) 181 | targets = torch.unsqueeze(targets, 1) 182 | temp = torch.ones((targets.shape[0], 1)).type(torch.LongTensor).cuda() 183 | targets = targets.sub(temp) 184 | loss = loss_fn(outputs, targets) 185 | # item函数把tensor变成数字 186 | total_test_loss += loss.item() 187 | 188 | #构造pre矩阵 189 | outputs=outputs.squeeze() 190 | a=torch.argmax(outputs,dim=1) 191 | pre[k:k+a.shape[0]]=a 192 | k+=a.shape[0] 193 | #将格式转换为ndarry 194 | pre=pre.type(torch.LongTensor).numpy() 195 | t=np.ones(pre.shape) 196 | pre=np.add(pre,t) 197 | matrix = confusion_matrix(y_test, pre) 198 | 199 | OA, AA_mean, Kappa, AA = utils.cal_results(matrix) 200 | print() 201 | print("Overall metrics:") 202 | print("OA: {:.4f} | AA: {:.4f} | Kappa: {:.4f}".format(OA, AA_mean, Kappa)) 203 | print("total_loss:{:.4f}".format(total_test_loss)) 204 | utils.cal_class_results(matrix,y_test) 205 | -------------------------------------------------------------------------------- /HSI/codes/HybridSN.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import utils 3 | import torch.utils.data as Data 4 | import torch.nn as nn 5 | import numpy as np 6 | import torch 7 | from sklearn.metrics import confusion_matrix 8 | 9 | from sklearn.decomposition import PCA 10 | 11 | parser=argparse.ArgumentParser("2DNN") 12 | parser.add_argument('dataset',choices=['Indian','Houston','Pavia'],default='Indian') 13 | parser.add_argument('epoch', type=int, default=500, help='epoch number') 14 | parser.add_argument('patch',type=int,help='size of input',default=7) 15 | parser.add_argument('usePCA',type=bool,default=False) 16 | args=parser.parse_args() 17 | 18 | data,data_TE,data_TR,data_label=utils.loaddata(args.dataset) 19 | 20 | input_normalize=utils.normalize(data) 21 | 22 | total_pos_train, total_pos_test, total_pos_true, number_train, number_test, number_true = utils.chooose_train_and_test_point( 23 | data_TR, data_TE, data_label, 16) 24 | height,width,band=input_normalize.shape 25 | #对于2D的CNN,我们需要对于获取其周边的像素 26 | #在1DCNN当中,我们传入的数据的形状是【x,200】,其中x为全部打散的波段 27 | #我们现在希望传入输入的大小是【x,width,height,band】 28 | #再对于每一张小图匹配一个标签 29 | 30 | if args.usePCA==True: 31 | #n_components表示的是期待将为之后的维度,band从200将为30 32 | pca=PCA(n_components=30) 33 | input_normalize=input_normalize.reshape(-1,band) 34 | input_normalize=pca.fit_transform(input_normalize) 35 | input_normalize=input_normalize.reshape(height,width,-1) 36 | band = 30 37 | #在测试当中我们向网络输入7*7的小patch,这意味着我们需要对于原图像的边界进行3的像素的padding 38 | #我们在这里不使用0来填充,我们使用了镜像的填充方法 39 | 40 | #调用utils里面的mirror方法来实现这个功能 41 | #对于Indian,原输入是145*145*200,左边增加三个像素右边增加三个像素,最终的结果就是151*151*200 42 | #input_mirror=utils.padWithZeros(height, width, band, input_normalize,(int)(args.patch/2)) 43 | input_mirror=utils.mirror(height, width, band, input_normalize, patch=args.patch) 44 | 45 | #获取每一个周围的像素,大小为【x,7,7,200】 46 | print("开始读取数据") 47 | x_train,x_test,x_true=utils.train_and_test_data(input_mirror,band,total_pos_train,total_pos_test,total_pos_true,patch=args.patch) 48 | 49 | y_train, y_test, y_true = utils.toStandardformY(data_label, band, total_pos_train, total_pos_test, total_pos_true, 50 | number_train, number_test, number_true) 51 | 52 | # 将numpy的ndarray类型转换为torch的tensor类型,再用tensordataset读取 53 | #torch.set_default_dtype(torch.float16) 54 | X_train = torch.from_numpy(x_train).type(torch.FloatTensor) 55 | Y_train = torch.from_numpy(y_train).type(torch.LongTensor) 56 | Label_train = Data.TensorDataset(X_train, Y_train) 57 | X_test = torch.from_numpy(x_test).type(torch.FloatTensor) 58 | Y_test = torch.from_numpy(y_test).type(torch.LongTensor) 59 | Label_test = Data.TensorDataset(X_test, Y_test) 60 | 61 | X_true = torch.from_numpy(x_true).type(torch.FloatTensor) 62 | Y_true = torch.from_numpy(y_true).type(torch.LongTensor) 63 | Label_true = Data.TensorDataset(X_true, Y_true) 64 | 65 | label_ture_loader = Data.DataLoader(Label_true, batch_size=64, shuffle=False) 66 | 67 | 68 | label_train_loader = Data.DataLoader(Label_train, batch_size=64, shuffle=True) 69 | label_test_loader = Data.DataLoader(Label_test, batch_size=64, shuffle=False) 70 | 71 | class OneDNN(nn.Module): 72 | def __init__(self,band): 73 | super().__init__() 74 | 75 | #三层三维卷积 76 | self.conv1=nn.Sequential( 77 | nn.Conv3d(in_channels=1,out_channels=8,kernel_size=(7,3,3),stride=1,padding=0), 78 | nn.BatchNorm3d(8), 79 | nn.ReLU(inplace=True), 80 | ) 81 | self.conv2=nn.Sequential( 82 | nn.Conv3d(in_channels=8, out_channels=16, kernel_size=(5, 3, 3), stride=1, padding=0), 83 | nn.BatchNorm3d(16), 84 | nn.ReLU(inplace=True), 85 | ) 86 | self.conv3=nn.Sequential( 87 | nn.Conv3d(in_channels=16,out_channels=32,kernel_size=(3,3,3),stride=1,padding=0), 88 | nn.BatchNorm3d(32), 89 | nn.ReLU(inplace=True), 90 | ) 91 | 92 | #一层二维卷积 93 | self.conv4=nn.Sequential( 94 | nn.Conv2d(in_channels=576,out_channels=64,kernel_size=(3,3),stride=1,padding=0), 95 | nn.BatchNorm2d(64), 96 | nn.ReLU(inplace=True), 97 | ) 98 | self.flat=nn.Flatten(1) 99 | 100 | 101 | if args.patch == 15: 102 | self.l = nn.Linear(3136,256) 103 | if args.patch == 17: 104 | self.l = nn.Linear(5184, 256) 105 | if args.patch == 19: 106 | self.l = nn.Linear(7744, 256) 107 | if args.patch == 21: 108 | self.l = nn.Linear(10816, 256) 109 | if args.patch == 23: 110 | self.l = nn.Linear(14400, 256) 111 | if args.patch == 25: 112 | self.l=nn.Linear(18496,256) 113 | 114 | self.ll = nn.Linear(256, 128) 115 | self.lll = nn.Linear(128, 16) 116 | 117 | self.r = nn.ReLU() 118 | self.drop = nn.Dropout(0.4) 119 | 120 | def forward(self,input): 121 | output=self.conv1(input) 122 | output=self.conv2(output) 123 | output=self.conv3(output) 124 | 125 | #reshape 126 | 127 | output = output.reshape(output.shape[0], -1,output.shape[3], output.shape[3]) 128 | output=self.conv4(output) 129 | 130 | output=self.flat(output) 131 | 132 | output=self.l(output) 133 | output=self.r(output) 134 | output=self.drop(output) 135 | 136 | output=self.ll(output) 137 | output = self.r(output) 138 | output = self.drop(output) 139 | 140 | output=self.lll(output) 141 | return output 142 | 143 | NN=OneDNN(band) 144 | NN=NN.cuda() 145 | NN=NN 146 | loss_fn=nn.CrossEntropyLoss() 147 | loss_fn=loss_fn.cuda() 148 | optimizer=torch.optim.Adam(NN.parameters(), lr=0.001) 149 | 150 | total_train_step=0 151 | 152 | print("Start train") 153 | for i in range(args.epoch): 154 | 155 | total_train_step=0 156 | NN.train() 157 | # print("第{}轮开始".format(i+1)) 158 | for data in label_train_loader: 159 | #print("{}".format(total_train_step)) 160 | d,target=data 161 | #神经网络的输入是(batch,channel,band,height,width) 162 | #permute 按序号交换维度 163 | d=d.permute(0,3,1,2) 164 | d=d.unsqueeze(1) 165 | d=d.cuda() 166 | target=target.cuda() 167 | outputs=NN(d) 168 | #outputs的格式应该为batch,类别,对象数(在此任务中为1) 169 | outputs=torch.unsqueeze(outputs,2) 170 | target=torch.unsqueeze(target,1) 171 | temp=torch.ones((target.shape[0],1)).type(torch.LongTensor).cuda() 172 | target=target.sub(temp) 173 | loss = loss_fn(outputs, target) 174 | 175 | optimizer.zero_grad() 176 | loss.backward() 177 | optimizer.step() 178 | #print("训练次数{}".format(total_train_step+1)) 179 | total_train_step+=1 180 | if (i + 1 == args.epoch): 181 | pree = torch.zeros(y_true.shape).type(torch.LongTensor) 182 | k = 0 183 | NN.eval() 184 | with torch.no_grad(): 185 | for data in label_ture_loader: 186 | d, targets = data 187 | d = d.permute(0, 3, 1, 2) 188 | d = d.unsqueeze(1) 189 | d = d.cuda() 190 | targets = targets.cuda() 191 | outputs = NN(d) 192 | outputs = torch.unsqueeze(outputs, 2) 193 | targets = torch.unsqueeze(targets, 1) 194 | temp = torch.ones((targets.shape[0], 1)).type(torch.LongTensor).cuda() 195 | targets = targets.sub(temp) 196 | # 构造pre矩阵 197 | outputs = outputs.squeeze() 198 | a = torch.argmax(outputs, dim=1) 199 | pree[k:k + a.shape[0]] = a 200 | k += a.shape[0] 201 | # 将格式转换为ndarry 202 | pree = pree.type(torch.LongTensor).numpy() 203 | t = np.ones(pree.shape) 204 | pree = np.add(pree, t) 205 | 206 | utils.save_result(pree, height, width, total_pos_true, number_true, "HybridSN-Houston") 207 | # 跑完一轮之后,要用测试数据集评估一下训练之后的结果 208 | # with表示不会对源模型的参数做任何的修改 209 | if (i+1)%10==0: 210 | print("Epoch:{}".format(i+1)) 211 | total_test_loss = 0 212 | pre = torch.zeros(size=y_test.shape) 213 | k = 0 214 | NN.eval() 215 | with torch.no_grad(): 216 | for data in label_test_loader: 217 | 218 | d, targets = data 219 | d = d.permute(0, 3, 1, 2) 220 | d = d.unsqueeze(1) 221 | d = d.cuda() 222 | targets = targets.cuda() 223 | outputs = NN(d) 224 | outputs = torch.unsqueeze(outputs, 2) 225 | targets = torch.unsqueeze(targets, 1) 226 | temp = torch.ones((targets.shape[0], 1)).type(torch.LongTensor).cuda() 227 | targets = targets.sub(temp) 228 | loss = loss_fn(outputs, targets) 229 | # item函数把tensor变成数字 230 | total_test_loss += loss.item() 231 | 232 | #构造pre矩阵 233 | outputs=outputs.squeeze() 234 | a=torch.argmax(outputs,dim=1) 235 | pre[k:k+a.shape[0]]=a 236 | k+=a.shape[0] 237 | #将格式转换为ndarry 238 | pre=pre.type(torch.LongTensor).numpy() 239 | t=np.ones(pre.shape) 240 | pre=np.add(pre,t) 241 | matrix = confusion_matrix(y_test, pre) 242 | 243 | OA, AA_mean, Kappa, AA = utils.cal_results(matrix) 244 | print() 245 | print("Overall metrics:") 246 | print("OA: {:.4f} | AA: {:.4f} | Kappa: {:.4f}".format(OA, AA_mean, Kappa)) 247 | print("total_loss:{:.4f}".format(total_test_loss)) 248 | utils.cal_class_results(matrix,y_test) 249 | -------------------------------------------------------------------------------- /HSI/codes/utils.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from scipy.io import loadmat 3 | import torch 4 | import torch.utils.data as Data 5 | from scipy.io import savemat 6 | 7 | # 移动文件的库 8 | import shutil 9 | 10 | 11 | # 计算OA,AA和Kappa 12 | def cal_results(matrix): 13 | shape = np.shape(matrix) 14 | number = 0 15 | sum = 0 16 | AA = np.zeros([shape[0]], dtype=np.float64) 17 | for i in range(shape[0]): 18 | number += matrix[i, i] 19 | AA[i] = matrix[i, i] / np.sum(matrix[i, :]) 20 | sum += np.sum(matrix[i, :]) * np.sum(matrix[:, i]) 21 | OA = number / np.sum(matrix) 22 | AA_mean = np.mean(AA) 23 | pe = sum / (np.sum(matrix) ** 2) 24 | Kappa = (OA - pe) / (1 - pe) 25 | return OA, AA_mean, Kappa, AA 26 | 27 | 28 | def cal_class_results(matrix, y): 29 | x = np.sum(matrix, axis=1) 30 | for i in range(max(y)): 31 | accuracy = matrix[i][i] / x[i] 32 | print("Class:{}".format(i + 1)) 33 | print("Accuracy:{:.2f}".format(accuracy * 100)) 34 | 35 | 36 | def save_result(pre, width, height, total_pos_test, number_test, name): 37 | classification_result = np.zeros(shape=(width, height), dtype=int) 38 | for i in range(sum(number_test)): 39 | classification_result[total_pos_test[i][0], total_pos_test[i][1]] += pre[i] 40 | savemat(name + '.mat', mdict={"result": classification_result}) 41 | shutil.move(name + '.mat', './results') 42 | 43 | 44 | def chooose_train_and_test_point(train_data, test_data, true_data, num_classes): 45 | # TR, TE, label, num_classes 46 | # train_data和true_data都是只保存标签信息 47 | 48 | # number_train 每个类别的总数,类别代表数量 49 | number_train = [] 50 | # pos_train用一个字典表示每一个类别对应的坐标,key是类别序号,键值是一个{x,2}的矩阵,每一行代表一个坐标 51 | pos_train = {} 52 | number_test = [] 53 | pos_test = {} 54 | number_true = [] 55 | pos_true = {} 56 | # -------------------------for train data------------------------------------ 57 | # 统计每种种类的数量 58 | for i in range(num_classes): 59 | each_class = [] 60 | # 标签等于每种种类,不吃背景label=0,只吃实际转换的大小 61 | each_class = np.argwhere(train_data == (i + 1)) 62 | # 在number_train后面加上这个类别的数量,shape【0】代表着数量 63 | number_train.append(each_class.shape[0]) 64 | # 用字典保存所有的坐标 65 | pos_train[i] = each_class 66 | # 要构造一个最终的全部的坐标点,初始化为标签为0的一些点 67 | total_pos_train = pos_train[0] 68 | for i in range(1, num_classes): 69 | # 把别的点都接在后面 70 | total_pos_train = np.r_[total_pos_train, pos_train[i]] # (695,2) 71 | # 把类型改变为int 72 | total_pos_train = total_pos_train.astype(int) 73 | # --------------------------for test data------------------------------------ 74 | for i in range(num_classes): 75 | each_class = [] 76 | each_class = np.argwhere(test_data == (i + 1)) 77 | number_test.append(each_class.shape[0]) 78 | pos_test[i] = each_class 79 | 80 | total_pos_test = pos_test[0] 81 | for i in range(1, num_classes): 82 | total_pos_test = np.r_[total_pos_test, pos_test[i]] # (9671,2) 83 | total_pos_test = total_pos_test.astype(int) 84 | # --------------------------for true data------------------------------------ 85 | for i in range(num_classes + 1): 86 | each_class = [] 87 | each_class = np.argwhere(true_data == i) 88 | number_true.append(each_class.shape[0]) 89 | pos_true[i] = each_class 90 | 91 | total_pos_true = pos_true[0] 92 | for i in range(1, num_classes + 1): 93 | total_pos_true = np.r_[total_pos_true, pos_true[i]] 94 | total_pos_true = total_pos_true.astype(int) 95 | 96 | return total_pos_train, total_pos_test, total_pos_true, number_train, number_test, number_true 97 | 98 | 99 | def toStandardformX(input_normalize, band, total_pos_train, total_pos_test, total_pos_true, number_train, number_test, 100 | number_true): 101 | X_train = np.zeros(shape=(sum(number_train), band), dtype=float) 102 | X_test = np.zeros(shape=(sum(number_test), band), dtype=float) 103 | X_true = np.zeros(shape=(sum(number_true), band), dtype=float) 104 | for i in range(sum(number_train)): 105 | X_train[i, :] = input_normalize[total_pos_train[i][0]][total_pos_train[i][1]] 106 | for i in range(sum(number_test)): 107 | X_test[i, :] = input_normalize[total_pos_test[i][0]][total_pos_test[i][1]] 108 | for i in range(sum(number_true)): 109 | X_true[i,:]=input_normalize[total_pos_true[i][0]][total_pos_true[i][1]] 110 | return X_train, X_test, X_true 111 | 112 | 113 | def toStandardformY(data_label, band, total_pos_train, total_pos_test, total_pos_true, number_train, number_test, 114 | number_true): 115 | Y_test = np.zeros(shape=(sum(number_test)), dtype=int) 116 | Y_train = np.zeros(shape=(sum(number_train)), dtype=int) 117 | Y_true = np.zeros(shape=(sum(number_true)), dtype=int) 118 | for i in range(sum(number_train)): 119 | Y_train[i] = data_label[total_pos_train[i][0]][total_pos_train[i][1]] 120 | for i in range(sum(number_test)): 121 | Y_test[i] = data_label[total_pos_test[i][0]][total_pos_test[i][1]] 122 | for i in range(sum(number_train)): 123 | Y_true[i] = data_label[total_pos_test[i][0]][total_pos_test[i][1]] 124 | return Y_train, Y_test, Y_true 125 | 126 | 127 | def loadColormap(dataset): 128 | global temp 129 | if dataset == 'Indian': 130 | temp = loadmat('./colormaps/colormapIndian.mat') 131 | elif dataset == 'Houston': 132 | temp = loadmat('colormaps/colormapHouston.mat') 133 | elif dataset == 'Pavia': 134 | temp = loadmat('./colormaps/colormapPavia.mat') 135 | return temp 136 | 137 | 138 | def loaddata(dataset): 139 | global da 140 | if dataset == 'Indian': 141 | # loadmat以字典的形式保存数据 142 | da = loadmat('./datasets/IndianPine.mat') 143 | elif dataset == 'Houston': 144 | da = loadmat('./datasets/Houston.mat') 145 | elif dataset == 'Pavia': 146 | da = loadmat("./datasets/Pavia.mat") 147 | data = da['input'] # 取出实际使用的数据 148 | data_TE = da['TE'] 149 | data_TR = da['TR'] 150 | data_label = data_TE + data_TR 151 | return data, data_TE, data_TR, data_label 152 | 153 | 154 | def normalize(data): 155 | # 创建一个同样大小的矩阵用于保存数据 156 | input_normalize = np.zeros(data.shape) 157 | # data。shape【2】指的是对于每一个波段来做标准化,对于每一个波段,找最大最小值,再归一化 158 | for i in range(data.shape[2]): 159 | input_max = np.max(data[:, :, i]) 160 | input_min = np.min(data[:, :, i]) 161 | input_normalize[:, :, i] = (data[:, :, i] - input_min) / (input_max - input_min) 162 | 163 | # number_train==[50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 15, 15, 15] 164 | # number_test==[1384, 784, 184, 447, 697, 439, 918, 2418, 564, 162, 1244, 330, 45, 39, 11, 5] 165 | # number_true==[10659, 1434, 834, 234, 497, 747, 489, 968, 2468, 614, 212, 1294, 380, 95, 54, 26, 20] 166 | # number_true多一个维数是背景像素,10659个 167 | 168 | # sum(number_train)==695,恰好等于total_pos_train里元素的数量 169 | 170 | return input_normalize 171 | 172 | 173 | def mirror(height, width, band, input_normalize, patch=5): 174 | # 截断除法,除完之后向下取整,并且返回的是一个int值 175 | padding = patch // 2 176 | # 对图片进行一个扩大化,在边界上扩增一个padding的长度,左边和右边各一个padding,最终总长增加了两个padding 177 | # padding上的值相当于将中间的部分折到边上 178 | mirror_hsi = np.zeros((height + 2 * padding, width + 2 * padding, band), dtype=float) 179 | # 中心区域 180 | # 中心区域的值直接等于原来的部分 181 | mirror_hsi[padding:(padding + height), padding:(padding + width), :] = input_normalize 182 | # 左边镜像 183 | for i in range(padding): 184 | mirror_hsi[padding:(height + padding), i, :] = input_normalize[:, padding - i - 1, :] 185 | # 右边镜像 186 | for i in range(padding): 187 | mirror_hsi[padding:(height + padding), width + padding + i, :] = input_normalize[:, width - 1 - i, :] 188 | # 上边镜像 189 | for i in range(padding): 190 | mirror_hsi[i, :, :] = mirror_hsi[padding * 2 - i - 1, :, :] 191 | # 下边镜像 192 | for i in range(padding): 193 | mirror_hsi[height + padding + i, :, :] = mirror_hsi[height + padding - 1 - i, :, :] 194 | 195 | print("**************************************************") 196 | print("patch is : {}".format(patch)) 197 | print("mirror_image shape : [{0},{1},{2}]".format(mirror_hsi.shape[0], mirror_hsi.shape[1], mirror_hsi.shape[2])) 198 | print("**************************************************") 199 | return mirror_hsi 200 | 201 | 202 | def padWithZeros(height, width, band, input_normalize, patch=5): 203 | newX = np.zeros((height + 2 * patch, width + 2 * patch, band)) 204 | x_offset = patch 205 | y_offset = patch 206 | newX[x_offset:height + x_offset, y_offset:width + y_offset, :] = input_normalize 207 | return newX 208 | 209 | 210 | def gain_neighborhood_pixel(mirror_image, point, i, patch=5): 211 | x = point[i, 0] 212 | y = point[i, 1] 213 | # 在这个点的右下角取一个立方体 214 | temp_image = mirror_image[x:(x + patch), y:(y + patch), :] 215 | return temp_image 216 | 217 | 218 | # ------------------------------------------------------------------------------- 219 | # 汇总训练数据和测试数据mirror_image, band, total_pos_train, total_pos_test total_pos_true, patch=args.patches, band_patch=args.band_patches 220 | def train_and_test_data(mirror_image, band, train_point, test_point,true_point, patch=5): 221 | x_train = np.zeros((train_point.shape[0], patch, patch, band), dtype=float) 222 | x_test = np.zeros((test_point.shape[0], patch, patch, band), dtype=float) 223 | x_true = np.zeros((true_point.shape[0], patch, patch, band), dtype='float16') 224 | # 获取右下角的patch*patch个像素以及200波段 225 | for i in range(train_point.shape[0]): 226 | x_train[i, :, :, :] = gain_neighborhood_pixel(mirror_image, train_point, i, patch) 227 | for j in range(test_point.shape[0]): 228 | x_test[j, :, :, :] = gain_neighborhood_pixel(mirror_image, test_point, j, patch) 229 | for j in range(true_point.shape[0]): 230 | x_true[j, :, :, :] = gain_neighborhood_pixel(mirror_image, true_point, j, patch) 231 | print("x_train shape = {}, type = {}".format(x_train.shape, x_train.dtype)) 232 | print("x_test shape = {}, type = {}".format(x_test.shape, x_test.dtype)) 233 | 234 | return x_train, x_test,x_true 235 | 236 | # def make_results(NN,label_ture_loader,pree): 237 | --------------------------------------------------------------------------------