├── Bayes.py ├── Bayes.sh ├── README.md ├── RF_Adaboost-multi_classes.py ├── RF_Adaboost.py ├── SVM.py ├── SVM.sh ├── cnn ├── data_visualization.py ├── dataset.py ├── process_data.py ├── process_data.sh ├── run.sh └── train.py ├── data_visualization.py ├── example-data_visual_resimg ├── lda.png ├── pca.png └── t-sne.png ├── feature2.py ├── img_tools.py ├── knn.py ├── knn.sh ├── lib ├── __init__.py ├── __pycache__ │ ├── __init__.cpython-35.pyc │ ├── __init__.cpython-36.pyc │ ├── svm.cpython-35.pyc │ ├── svm.cpython-36.pyc │ ├── svmutil.cpython-35.pyc │ └── svmutil.cpython-36.pyc ├── svm.py └── svmutil.py ├── prapare_data.py └── prepare_data.sh /Bayes.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | ###### 5 | # 6 | # Mail npuxpli@mail.nwpu.edu.cn 7 | # Author LiXiping 8 | # Date 2019/09/20 16:19:34 9 | # 10 | ###### 11 | 12 | import os 13 | import time 14 | import argparse 15 | import csv 16 | import random 17 | import math 18 | from feature2 import * 19 | 20 | 21 | def maxmin_normalization(feature): 22 | return [(float(i) - float(min(feature)))/float(float(max(feature)) - float(min(feature))) for i in feature] 23 | 24 | def standard_normalization(feature): 25 | mean = sum([float(x) for x in feature]) / float(len(feature)) 26 | variance = sum([pow(float(x) - mean , 2) for x in feature]) / float(len(feature) -1) 27 | stdev = math.sqrt(variance) 28 | 29 | 30 | return [((float(i) - mean) / stdev) for i in feature] 31 | 32 | def log_normalization(feature): 33 | maxa = float(max(feature)) 34 | return [(np.log(float(i)) / np.log(maxa)) for i in feature] 35 | 36 | def get_feature(img_path): 37 | hu = get_hu(img_path) 38 | svd = get_svd(img_path) 39 | mr = get_mr(img_path) 40 | pzor = get_pzor(img_path) 41 | #sift = get_sift(img_path) 42 | minrectangle = get_minrectangle(img_path) 43 | #harris = get_harris(img_path) 44 | fourier = get_fourier(img_path) 45 | 46 | feature = np.concatenate(( mr, hu , pzor, minrectangle,svd,fourier)) 47 | 48 | #feature = np.concatenate(( mr, hu)) 49 | return feature 50 | 51 | # 52 | # def loadCsv(filename): 53 | # lines = csv.reader(open(filename, "r")) 54 | # dataset = list(lines) 55 | # for i in range(len(dataset)): 56 | # dataset[i] = [float(x) for x in dataset[i]] 57 | # return dataset 58 | # 59 | # 60 | # def splitDataset(dataset, splitRatio): 61 | # trainSize = int(len(dataset) * splitRatio) 62 | # trainSet = [] 63 | # copy = list(dataset) 64 | # while len(trainSet) < trainSize: 65 | # index = random.randrange(len(copy)) 66 | # trainSet.append(copy.pop(index)) 67 | # return [trainSet, copy] 68 | 69 | def prepare_data(dir): 70 | features = [] 71 | for i,img_dir in enumerate(sorted(os.listdir(dir))): 72 | img_folder = os.path.join(dir , img_dir) 73 | for item in os.listdir(img_folder): 74 | img_path = os.path.join(img_folder , item) 75 | feature = get_feature(img_path) 76 | feature = feature.tolist() 77 | feature.append(float(i+1)) 78 | features.append(feature) 79 | return features 80 | 81 | 82 | def separateByClass(dataset): 83 | separated = {} 84 | for i in range(len(dataset)): 85 | vector = dataset[i] 86 | if (vector[-1] not in separated): 87 | separated[vector[-1]] = [] 88 | separated[vector[-1]].append(vector) 89 | #print(separated) 90 | return separated 91 | 92 | 93 | def mean(numbers): 94 | return sum([float(x) for x in numbers]) / float(len(numbers)) 95 | 96 | 97 | def stdev(numbers): 98 | avg = mean(numbers) 99 | variance = sum([pow(float(x) - avg, 2) for x in numbers]) / float(len(numbers) - 1) 100 | return math.sqrt(variance) 101 | 102 | 103 | def summarize(dataset): 104 | summaries = [(mean(attribute), stdev(attribute)) for attribute in zip(*dataset)] 105 | del summaries[-1] 106 | return summaries 107 | 108 | 109 | def summarizeByClass(dataset): 110 | separated = separateByClass(dataset) 111 | summaries = {} 112 | for classValue, instances in separated.items(): 113 | summaries[classValue] = summarize(instances) 114 | print(summaries) 115 | return summaries 116 | 117 | 118 | def calculateProbability(x, mean, stdev): 119 | if stdev == 0: 120 | exponent = 1 121 | else: 122 | exponent = math.exp(-(math.pow(float(x) - mean, 2) / (2 * math.pow(stdev, 2)))) 123 | #print("stdev:",stdev) 124 | #print("exponent:",exponent) 125 | 126 | if stdev == 0: 127 | pro = 0.5 128 | else: 129 | pro = (1.0 / float((math.sqrt(2 * math.pi) * stdev))) * exponent 130 | #print("pro:", pro) 131 | return pro 132 | 133 | 134 | def calculateClassProbabilities(summaries, inputVector): 135 | probabilities = {} 136 | for classValue, classSummaries in summaries.items(): 137 | probabilities[classValue] = 1 138 | for i in range(len(classSummaries)): 139 | mean, stdev = classSummaries[i] 140 | x = inputVector[i] 141 | probabilities[classValue] *= calculateProbability(x, mean, stdev) 142 | return probabilities 143 | 144 | 145 | def predict(summaries, inputVector): 146 | probabilities = calculateClassProbabilities(summaries, inputVector) 147 | bestLabel, bestProb = None, -1 148 | for classValue, probability in probabilities.items(): 149 | if bestLabel is None or probability > bestProb: 150 | bestProb = probability 151 | bestLabel = classValue 152 | return bestLabel 153 | 154 | 155 | def getPredictions(summaries, testSet): 156 | predictions = [] 157 | for i in range(len(testSet)): 158 | result = predict(summaries, testSet[i]) 159 | predictions.append(result) 160 | return predictions 161 | 162 | 163 | def getAccuracy(testSet, predictions): 164 | correct = 0 165 | for i in range(len(testSet)): 166 | if testSet[i][-1] == predictions[i]: 167 | correct += 1 168 | print(correct) 169 | print(len(testSet)) 170 | return (correct / float(len(testSet))) * 100.0 171 | 172 | 173 | def main(): 174 | # filename = 'pima-indians-diabetes.csv' 175 | # splitRatio = 0.67 176 | # dataset = loadCsv(filename) 177 | # #print(dataset) 178 | # trainingSet, testSet = splitDataset(dataset, splitRatio) 179 | # print('Split {0} rows into train={1} and test={2} rows'.format(len(dataset), len(trainingSet), len(testSet))) 180 | # print(trainingSet) 181 | # print(testSet) 182 | parser = argparse.ArgumentParser() 183 | parser.add_argument("--train_dir") 184 | parser.add_argument("--test_dir") 185 | args = parser.parse_args() 186 | 187 | t11 = time.time() 188 | trainingSet = prepare_data(args.train_dir) 189 | data = np.array(trainingSet, dtype=np.float64) 190 | print(data.shape) 191 | # mean = np.mean(data, axis=0).astype(np.float64) 192 | # stdev = np.std(data, axis=0).astype(np.float64) 193 | # print(mean) 194 | # print(stdev) 195 | # data = (data - mean) / stdev 196 | train_data = data.tolist() 197 | testSet = prepare_data(args.test_dir) 198 | test_data = np.array(testSet, dtype=np.float64) 199 | # test_data = (test_data - mean) / stdev 200 | test_data = test_data.tolist() 201 | print("preparedata:",time.time()-t11) 202 | # prepare model 203 | t1 = time.time() 204 | summaries = summarizeByClass(train_data) 205 | print("t1:",time.time()-t1) 206 | # test model 207 | t2 = time.time() 208 | predictions = getPredictions(summaries, test_data) 209 | print("t2",time.time()-t2) 210 | print(predictions) 211 | accuracy = getAccuracy(test_data, predictions) 212 | print('Accuracy: {0}%'.format(accuracy)) 213 | 214 | if __name__ == '__main__': 215 | main() 216 | -------------------------------------------------------------------------------- /Bayes.sh: -------------------------------------------------------------------------------- 1 | python Bayes.py \ 2 | --train_dir=./4/train \ 3 | --test_dir=./4/test -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Machine-Learning 2 | Simple image classification using various machine learning methods, including image feature extraction steps and feature dimensionality reduction visualization method. 3 | > 用多种机器学习方法进行简单的图像分类(针对灰度图像,也可改为可见光图像),包括对图像的特征提取步骤及特征降维可视化方法。 4 | 5 | ## 1.Prepare Data 6 | _涉及到的文件包括:prapare_data.py, prepare_data.sh, feature2.py_ 7 | 8 | 1.1 数据采用如下格式存放 9 | 10 | * |-- data 11 | * |--train 12 | * |--1 13 | * |--2 14 | * |-... 15 | * |--test 16 | * |--1 17 | * |--2 18 | * |-... 19 | 20 | 1.2 运行说明 21 | 22 | **RF、Adaboost、SVM**方法的数据准备使用prapare_data.py与prepare_data.sh两个文件进行准备; 23 | 24 | **knn、Bayes**方法不需要数据准备,直接运行即可. 25 | 26 | 1.3 特征 27 | > 图像的特征包括 28 | >>SVD特征\ 29 | >>Hu不变矩特征\ 30 | >>均值对比度特征(MR)\ 31 | >>亮度比(Pzor):比目标最亮点亮度小10%以内的像素点个数与目标总像素个数之间的比值\ 32 | >>长宽比(minrectangle):目标最小外接矩形的长度与宽度之比值\ 33 | >>SIFT特征\ 34 | >>Harris特征\ 35 | >>Fourier傅立叶描述子 36 | 37 | 38 | 39 | ## 2.Methods 40 | _涉及到的文件包括:RF_Adaboost.py,RF_Adaboost-multi_classes.py, SVM.py, 41 | SVM.sh, knn.py, knn.sh, cnn/, lib/_ 42 | 43 | ### 2.1 AdaBoost 44 | RF_Adaboost.py和RF_Adaboost-multi_classes.py 分别针对步骤1提取到的特征,实现了图像的二分类与多分类。 45 | 46 | ### 2.2 Random Forest 47 | RF_Adaboost.py和RF_Adaboost-multi_classes.py 分别针对步骤1提取到的特征,实现了图像的二分类与多分类。 48 | 49 | ### 2.3 SVM 50 | - lib 直接从libSVM官网下载的py库文件 51 | 52 | SVM.py\ 53 | SVM.sh 54 | 55 | ### 2.4 KNN 56 | knn.py\ 57 | knn.sh 58 | 59 | ### 2.5 CNN 60 | 使用简单的神经网络进行图像分类 61 | 62 | cnn/* 63 | 64 | 65 | ## 3.feature dimensionality reduction &visualization 66 | 67 | 68 | data_visualization.py 69 | 70 | 实现了数据的三种降维方法 71 | 72 | 包括常见的LDA、PCA、T_SNE三种方法 73 | 74 | 并对结果进行可视化与保存,可以显示类别间的差异,验证特征的有效性与可分性 75 | 76 | 结果展示: 77 | ![lda](https://github.com/lesleyping/Machine-Learning/blob/master/example-data_visual_resimg/lda.png) 78 | 79 | ![pca](https://github.com/lesleyping/Machine-Learning/blob/master/example-data_visual_resimg/pca.png) 80 | 81 | ![t-sne](https://github.com/lesleyping/Machine-Learning/blob/master/example-data_visual_resimg/t-sne.png) 82 | -------------------------------------------------------------------------------- /RF_Adaboost-multi_classes.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | ###### 5 | # 6 | # Mail npuxpli@mail.nwpu.edu.cn 7 | # Author LiXiping 8 | # Date 2019/09/20 16:19:34 9 | # 10 | ###### 11 | 12 | import time 13 | import matplotlib.pyplot as plt 14 | import pylab 15 | import numpy as np 16 | import random 17 | from scipy import linalg as sp 18 | from mpl_toolkits.mplot3d import Axes3D 19 | from sklearn.metrics import confusion_matrix 20 | from sklearn.metrics import classification_report 21 | from sklearn import tree 22 | 23 | def RF_train(X_train, Y_train, d, n): 24 | clf=[] 25 | for i in range(n): 26 | idx=np.random.choice(len(Y_train),len(Y_train),replace=True) 27 | x=X_train[idx,:] 28 | y=Y_train[idx] 29 | temp=tree.DecisionTreeClassifier(max_depth=d) 30 | clf.append(temp.fit(x,y)) 31 | return clf 32 | 33 | def RF_test(clf, X_test, l, n): 34 | res=[] 35 | for j in range(l): 36 | r=[0,0,0,0,0,0] 37 | for i in range(n): 38 | temp=clf[i].predict(X_test[j,:]) 39 | r[int(temp[0])]+=1 40 | idx=r.index(max(r)) 41 | res.append(idx) 42 | return res 43 | 44 | def OOB_error(X_train, Y_train, d): 45 | clf=[] 46 | err=[] 47 | n=np.round(np.linspace(1,200,num=10)) 48 | for k in n: 49 | res=[] 50 | for i in range(int(k)): 51 | idx=np.random.choice(len(Y_train),len(Y_train),replace=True) 52 | x=X_train[idx,:] 53 | y=Y_train[idx] 54 | temp=tree.DecisionTreeClassifier(max_depth=d) 55 | clf.append(temp.fit(x,y)) 56 | idx=np.unique(idx) 57 | oob=[] 58 | for j in range(len(Y_train)): 59 | if j not in idx: 60 | oob.append(j) 61 | r=[0,0,0,0,0,0] 62 | for j in oob: 63 | temp=clf[i].predict(X_train[j,:]) 64 | r[int(temp[0])]+=1 65 | idx=r.index(max(r)) 66 | res.append(idx) 67 | temp=len([i for i, j in zip(res,Y_train[oob]) if i!=j]) 68 | k=int(k) 69 | err.append(temp/k) 70 | print(k) 71 | plt.figure(5, figsize=(8,6)) 72 | plt.plot(n,err) 73 | plt.ylabel('OOB Error') 74 | plt.xlabel('Number of Trees (Max Depth=full)') 75 | plt.show() 76 | 77 | def Train_Test_err(X_train,Y_train,X_test,Y_test): 78 | n=np.round(np.linspace(1,500,num=10)) 79 | err1=[] 80 | err2=[] 81 | err3=[] 82 | err4=[] 83 | for i in n: 84 | clf=RF_train(X_train, Y_train, len(Y_train), int(i)) 85 | res=RF_test(clf,X_train,len(Y_train), int(i)) 86 | temp=len([i for i, j in zip(res,Y_train) if i!=j]) 87 | err1.append(temp/len(Y_train)) 88 | res=RF_test(clf,X_test,len(Y_test), int(i)) 89 | temp=len([i for i, j in zip(res,Y_test) if i!=j]) 90 | err3.append(temp/len(Y_test)) 91 | 92 | clf=RF_train(X_train, Y_train, 5, int(i)) 93 | res=RF_test(clf,X_train,len(Y_train), int(i)) 94 | temp=len([i for i, j in zip(res,Y_train) if i!=j]) 95 | err2.append(temp/len(Y_train)) 96 | res=RF_test(clf,X_test,len(Y_test), int(i)) 97 | temp=len([i for i, j in zip(res,Y_test) if i!=j]) 98 | err4.append(temp/len(Y_test)) 99 | 100 | plt.figure(1, figsize=(8,6)) 101 | plt.plot(n,err1) 102 | plt.ylabel('Train Error') 103 | plt.xlabel('Number of Trees (Max Depth=full)') 104 | plt.figure(2, figsize=(8,6)) 105 | plt.plot(n,err2) 106 | plt.ylabel('Train Error') 107 | plt.xlabel('Number of Trees (Max Depth=5)') 108 | plt.figure(3, figsize=(8,6)) 109 | plt.plot(n,err3) 110 | plt.ylabel('Test Error') 111 | plt.xlabel('Number of Trees (Max Depth=full)') 112 | plt.figure(4, figsize=(8,6)) 113 | plt.plot(n,err4) 114 | plt.ylabel('Test Error') 115 | plt.xlabel('Number of Trees (Max Depth=5)') 116 | plt.show() 117 | 118 | def Adaboost_train(X_train, Y_train, d, num_classes): 119 | w=[] 120 | for i in range(len(Y_train)): 121 | w.append(1/len(Y_train)) 122 | alpha=[] 123 | for i in range(20): 124 | alpha.append(0) 125 | err=[] 126 | for i in range(20): 127 | err.append(0) 128 | clf=[] 129 | for i in range(20): 130 | x=X_train 131 | y=Y_train 132 | temp=tree.DecisionTreeClassifier(max_depth=d) 133 | clf.append(temp.fit(x,y,sample_weight=w)) 134 | t=0 135 | for j in range(len(Y_train)): 136 | pred=clf[i].predict(x[j,:]) 137 | if pred[0]!=y[j]: 138 | t=t+w[j] 139 | err[i]=t/np.sum(w) 140 | if err[i]==0: 141 | alpha[i]=np.log(num_classes-1) 142 | else: 143 | alpha[i]=np.log((1-err[i])/err[i]) + np.log(num_classes-1) 144 | for j in range(len(Y_train)): 145 | pred=clf[i].predict(x[j,:]) 146 | if pred[0]!=y[j]: 147 | w[j]=w[j]*np.exp(alpha[i]) 148 | w=w/np.sum(w) 149 | return alpha,clf 150 | 151 | def Adaboost_test(clf, alpha, X_test, l, n): 152 | Y=[] 153 | classes=[1,2,3,4] 154 | for i in range(l): 155 | Y.append(0) 156 | for i in range(l): 157 | c=[0,0,0,0] 158 | for j in range(n): 159 | for k in range(len(alpha)): 160 | pred=clf[k].predict(X_test[i,:]) 161 | if pred[0]==classes[j]: 162 | c[j]=c[j]+alpha[k] 163 | Y[i]=classes[int(c.index(max(c)))] 164 | return Y 165 | 166 | train_dataset = np.mat(np.loadtxt('4_train.txt', delimiter=",")) 167 | test_dataset = np.mat(np.loadtxt('4_test.txt',delimiter=",")) 168 | print(train_dataset[0]) 169 | x_train = train_dataset[:, 0:23] 170 | y_train = train_dataset[:, 23] 171 | x_test = test_dataset[:, 0:23] 172 | y_test = test_dataset[:, 23] 173 | 174 | print(len(x_train)) 175 | print(len(y_train)) 176 | 177 | #train 178 | # mnist = np.mat(np.loadtxt("train.csv", delimiter=",")) 179 | # mnist=mnist.T 180 | # print(mnist.shape) 181 | # X_train=mnist[:,0:784] 182 | # Y_train=mnist[:,784] 183 | num_trees=20 184 | t3 = time.time() 185 | clf=RF_train(x_train, y_train, 5, num_trees) 186 | print("t3:", time.time()-t3) 187 | OOB_error(x_train, y_train, len(y_train)) 188 | t4 = time.time() 189 | res=RF_test(clf,x_test,len(y_test), num_trees) 190 | print("t4:",time.time()-t4) 191 | target_names = ['1', '2', '3', '4'] 192 | print(classification_report(y_test, res, target_names=target_names)) 193 | cm=confusion_matrix(y_test, res) 194 | print(cm) 195 | 196 | Train_Test_err(x_train,y_train,x_test,y_test) 197 | t1 = time.time() 198 | alpha,clf=Adaboost_train(x_train, y_train, 10, 4) 199 | print("t1",time.time()-t1) 200 | print(alpha) 201 | t2 = time.time() 202 | Y_pred=Adaboost_test(clf,alpha,x_test,len(y_test),4) 203 | print("t2:",time.time()-t2) 204 | # target_names = ['1', '2', '3', '4', '5'] 205 | target_names = ['1', '2', '3', '4'] 206 | print(classification_report(y_test, Y_pred, target_names=target_names)) 207 | cm=confusion_matrix(y_test, Y_pred) 208 | print(cm) -------------------------------------------------------------------------------- /RF_Adaboost.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | ###### 5 | # 6 | # Mail npuxpli@mail.nwpu.edu.cn 7 | # Author LiXiping 8 | # Date 2019/09/20 16:14:26 9 | # 10 | ###### 11 | 12 | import torch 13 | import numpy as np 14 | from sklearn.model_selection import train_test_split 15 | from sklearn.metrics import accuracy_score 16 | 17 | # 单层决策树 18 | class DecisionStump: 19 | 20 | def __init__(self, X, y): 21 | self.X = X 22 | self.y = y 23 | self.N = self.X.size()[0] 24 | 25 | def train(self, W, steps=100): 26 | min_v = float("inf") 27 | threshold_value = 0 28 | threshold_pos = 0 29 | threshold_tag = 0 30 | self.W = torch.Tensor(W) 31 | for i in range(self.N): # value表示阈值,errcnt表示错误的数量 32 | value, errcnt = self.find_min(i, 1, steps) 33 | if (errcnt < min_v): 34 | min_v = errcnt 35 | threshold_value = value 36 | threshold_pos = i 37 | threshold_tag = 1 38 | 39 | for i in range(self.N): # -1 40 | value, errcnt = self.find_min(i, -1, steps) 41 | if (errcnt < min_v): 42 | min_v = errcnt 43 | threshold_value = value 44 | threshold_pos = i 45 | threshold_tag = -1 46 | self.threshold_value = threshold_value 47 | self.threshold_pos = threshold_pos 48 | self.threshold_res = threshold_tag 49 | print(self.threshold_value, self.threshold_pos, self.threshold_res) 50 | return min_v 51 | 52 | def find_min(self, i, tag, steps): 53 | t = 0 54 | tmp = self.predintrain(self.X, i, t, tag).transpose(0, 1) 55 | # print(type(tmp)) 56 | # print(type(self.y)) 57 | # ttt = tmp != self.y 58 | # print("====", (tmp.cpu() != self.y.cpu()).size()) 59 | # print(self.W.size()) 60 | # errcnt = torch.sum((tmp != self.y).float() * self.W) 61 | # print now 62 | buttom = torch.min(self.X[i, :]) # 该项属性的最小值,下界 63 | up = torch.max(self.X[i, :]) # 该项属性的最大值,上界 64 | minerr = float("inf") # 将minerr初始化为无穷大 65 | value = 0 # value表示阈值 66 | st = (up - buttom) / steps # 间隔 67 | if st!=0: 68 | for t in torch.arange(buttom, up, st): 69 | tmp = self.predintrain(self.X, i, t, tag).transpose(0, 1) 70 | tmp = tmp.float() 71 | errcnt = torch.sum((tmp != self.y).float() * self.W) 72 | if errcnt < minerr: 73 | minerr = errcnt 74 | value = t 75 | return value, minerr 76 | 77 | def predintrain(self, test_set, i, t, tag): # 训练时按照阈值为t时预测结果 78 | test_set = test_set.view(self.N, -1) 79 | pre_y = torch.ones((test_set.size()[1], 1)) 80 | 81 | pre_y[test_set[i, :] * tag < t * tag] = -1 82 | 83 | return pre_y 84 | 85 | def pred(self, test_X): # 弱分类器的预测 86 | test_X = torch.Tensor(test_X).view(self.N, -1) # 转换为N行X列,-1懒得算 87 | pre_y = torch.ones((torch.Tensor(test_X).size()[1], 1)) 88 | pre_y[test_X[self.threshold_pos, :] * self.threshold_res < self.threshold_value * self.threshold_res] = -1 89 | return pre_y 90 | 91 | 92 | class AdaBoost: 93 | def __init__(self, X, y, Weaker=DecisionStump): 94 | self.X = torch.Tensor(X) 95 | self.y = torch.Tensor(y).flatten() 96 | self.Weaker = Weaker 97 | 98 | self.sums = torch.zeros(self.y.shape) 99 | ''' 100 | W为权值,初试情况为均匀分布,即所有样本都为1/n 101 | ''' 102 | self.W = torch.ones((self.X.size()[1], 1)).flatten() / self.X.size()[1] 103 | 104 | self.Q = 0 # 弱分类器的实际个数 105 | 106 | # M 为弱分类器的最大数量,可以在main函数中修改 107 | def train(self, M=5): 108 | self.G = {} # 表示弱分类器的字典 109 | self.alpha = {} # 每个弱分类器的参数 110 | for i in range(M): 111 | self.G.setdefault(i) 112 | self.alpha.setdefault(i) 113 | for i in range(M): # self.G[i]为第i个弱分类器 114 | self.G[i] = self.Weaker(self.X, self.y) 115 | e = self.G[i].train(self.W) # 根据当前权值进行该个弱分类器训练 116 | self.alpha[i] = 1.0 / 2 * torch.log((1 - e) / e) # 计算该分类器的系数 117 | res = self.G[i].pred(self.X) # res表示该分类器得出的输出 118 | 119 | # 计算当前次数训练精确度 120 | print("weak classfier acc", accuracy_score(self.y, 121 | res), "\n======================================================") 122 | 123 | # Z表示规范化因子 124 | Z = self.W * torch.exp(-self.alpha[i] * self.y * res.transpose(1, 0)) 125 | self.W = (Z / Z.sum()).flatten() # 更新权值 126 | self.Q = i 127 | # errorcnt返回分错的点的数量,为0则表示perfect 128 | if (self.errorcnt(i) == 0): 129 | print("%d个弱分类器可以将错误率降到0" % (i + 1)) 130 | break 131 | 132 | def errorcnt(self, t): # 返回错误分类的点 133 | self.sums = self.sums + self.G[t].pred(self.X).flatten() * self.alpha[t] 134 | 135 | pre_y = torch.zeros_like(torch.Tensor(self.sums)) 136 | pre_y[self.sums >= 0] = 1 137 | pre_y[self.sums < 0] = -1 138 | 139 | t = (pre_y != self.y).sum() 140 | return t 141 | 142 | def pred(self, test_X): # 测试最终的分类器 143 | test_X = torch.Tensor(test_X) 144 | sums = torch.zeros(test_X.size()[1]) 145 | for i in range(self.Q + 1): 146 | sums = sums + self.G[i].pred(test_X).flatten() * self.alpha[i] 147 | pre_y = torch.zeros_like(torch.Tensor(sums)) 148 | pre_y[sums >= 0] = 1 149 | pre_y[sums < 0] = -1 150 | return pre_y 151 | 152 | 153 | def main(): 154 | # # load data 155 | # dataset = np.loadtxt('data.txt', delimiter=",") 156 | # x = dataset[:, 0:8] 157 | # y = dataset[:, 8] 158 | # 159 | # # prepare train data 160 | # x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=0) 161 | 162 | # load data 163 | train_dataset = np.loadtxt('p_c_train.txt', delimiter=",") 164 | test_dataset = np.loadtxt('p_c_test.txt', delimiter=",") 165 | print(len(train_dataset[0])) 166 | x_train = train_dataset[:, 0:261] 167 | y_train = train_dataset[:, 261] 168 | x_test = test_dataset[:, 0:261] 169 | y_test = test_dataset[:, 261] 170 | 171 | # prepare test and train data 172 | x_train = x_train.transpose() 173 | y_train[y_train == 1] = 1 174 | y_train[y_train == 2] = -1 175 | 176 | x_test = x_test.transpose() 177 | y_test[y_test == 1] = 1 178 | y_test[y_test == 2] = -1 179 | 180 | # train 181 | ada = AdaBoost(x_train, y_train) 182 | ada.train(50) 183 | 184 | # predict 185 | y_pred = ada.pred(x_test) 186 | y_pred = y_pred.numpy() 187 | print("total test", len(y_pred)) 188 | print("true pred", len(y_pred[y_pred == y_test])) 189 | print("acc", accuracy_score(y_test, y_pred)) 190 | 191 | 192 | if __name__ == '__main__': 193 | main() 194 | -------------------------------------------------------------------------------- /SVM.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | ###### 5 | # 6 | # Mail npuxpli@mail.nwpu.edu.cn 7 | # Author LiXiping 8 | # Date 2019/09/20 16:14:26 9 | # 10 | ###### 11 | import argparse 12 | import time 13 | from lib.svm import svm_problem, svm_parameter 14 | from lib.svmutil import * 15 | 16 | def train(args): 17 | """ 18 | 使用图像的特征文件 来训练生成model文件 19 | :return: 20 | """ 21 | y, x = svm_read_problem(args.train_file) 22 | param = svm_parameter('-s 0 -t 1 -c 5 -b 1') 23 | prob = svm_problem(y, x) 24 | model = svm_train(prob, param) 25 | svm_save_model(args.model_path, model) 26 | 27 | def decode(args): 28 | yt, xt = svm_read_problem(args.test_file) 29 | model = svm_load_model(args.model_path) 30 | p_label, p_acc, p_val = svm_predict(yt, xt, model) 31 | cnt = 0 32 | for item in p_label: 33 | print('%d' % item, end =',') 34 | cnt += 1 35 | if cnt % 8 == 0: 36 | print('') 37 | 38 | if __name__ == '__main__': 39 | parser = argparse.ArgumentParser() 40 | parser.add_argument("--train_file") 41 | parser.add_argument("--model_path") 42 | parser.add_argument("--test_file") 43 | parser.add_argument("--decode", default= True) 44 | #parser.add_argument("--decode", default=False) 45 | args = parser.parse_args() 46 | if args.decode: 47 | print("decoding...") 48 | t2 = time.time() 49 | decode(args) 50 | print("t2:",time.time()-t2) 51 | else: 52 | print("training...") 53 | t1 = time.time() 54 | train(args) 55 | print("t1:",time.time()-t1) 56 | -------------------------------------------------------------------------------- /SVM.sh: -------------------------------------------------------------------------------- 1 | python train.py \ 2 | --train_file=./txt/4_train.txt \ 3 | --model_path=./data/4_model \ 4 | --test_file=./txt/4_test.txt 5 | -------------------------------------------------------------------------------- /cnn/data_visualization.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | ###################################################################### 5 | # 6 | # Copyright 205@NPU. All Rights Reserved 7 | # 8 | # Licensed under the Apache License, Veresion 2.0(the "License"); 9 | # You may not use the file except in compliance with the Licese. 10 | # You may obtain a copy of the License at 11 | # 12 | # http://www.apache.org/license/LICENSE-2.0 13 | # 14 | # Unless required by applicable law or agreed to in writing,software 15 | # distributed under the License is distributed on an "AS IS" BASIS 16 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | # See the License for the specific language governing permissions and 18 | # limitations under the License. 19 | # 20 | # Author lixping 21 | # congjian 22 | # Date 2019/05/12 15:30:10 23 | # 24 | ###################################################################### 25 | 26 | 27 | import os 28 | 29 | import argparse 30 | import cv2 31 | import matplotlib.pyplot as plt 32 | import numpy as np 33 | from sklearn.manifold import TSNE 34 | from sklearn.decomposition import PCA 35 | from sklearn.discriminant_analysis import LinearDiscriminantAnalysis 36 | from tqdm import tqdm 37 | 38 | from feature import * 39 | 40 | def get_feature(work_dir): 41 | hu = get_hu(work_dir) 42 | svd = get_svd(work_dir) 43 | mr = get_mr(work_dir) 44 | pzor = get_pzor(work_dir) 45 | #sift = get_sift(work_dir) 46 | minrectangle = get_minrectangle(work_dir) 47 | #harris = get_harris(work_dir) 48 | #fourier = get_fourier(work_dir) 49 | feature = np.concatenate(( mr, pzor,minrectangle,svd,hu)) 50 | #feature1 = maxmin_normalization(feature) 51 | #feature2 = standard_normalization(feature) 52 | #feature3 = log_normalization(feature) 53 | #feature = np.concatenate(( mr, hu)) 54 | #return feature 55 | return feature 56 | 57 | def lda(x, y): 58 | lda = LinearDiscriminantAnalysis(n_components=2) 59 | lda.fit(x, y) 60 | res = lda.transform(x) 61 | return res 62 | 63 | def pca(x): 64 | pca = PCA(n_components=2) 65 | res = pca.fit_transform(x) 66 | return res 67 | 68 | def t_sne(x): 69 | tsne = TSNE(n_components=2, init='pca', random_state=0) 70 | tsne.fit_transform(x) 71 | res = tsne.embedding_ 72 | return res 73 | 74 | if __name__ == '__main__': 75 | parser = argparse.ArgumentParser() 76 | parser.add_argument("--work_dir", default="5f2d/train") 77 | parser.add_argument("--res_dir", default="data_visual_res_jcong") 78 | args = parser.parse_args() 79 | 80 | x = [] 81 | y = [] 82 | for label, class_dir in tqdm(enumerate(sorted(os.listdir(args.work_dir)))): 83 | for img in tqdm(sorted(os.listdir(os.path.join(args.work_dir, class_dir)))): 84 | work_dir = os.path.join(args.work_dir, class_dir, img) 85 | # feature = get_feature(work_dir) 86 | # x.append(feature) 87 | y.append(label) 88 | x = np.array(x).astype(np.float64) 89 | y = np.array(y).astype(np.int64).transpose() 90 | np.savetxt("y.txt",y) 91 | 92 | if not os.path.exists(args.res_dir): 93 | os.mkdir(args.res_dir) 94 | 95 | 96 | 97 | # plot pca 98 | # res = pca(x) 99 | # np.savetxt("1.txt",res) 100 | res = np.loadtxt("1.txt") 101 | plt.figure(figsize = (8, 5)) 102 | plt.scatter(res[:, 0], res[:, 1], c = y, marker='o') 103 | plt.title("PCA") 104 | plt.savefig(os.path.join(args.res_dir,"pca.png")) 105 | 106 | # plot t-sne 107 | # res = t_sne(x) 108 | # np.savetxt("2.txt", res) 109 | res = np.loadtxt("2.txt") 110 | plt.figure(figsize = (8, 5)) 111 | plt.scatter(res[:, 0], res[:, 1], c = y, marker = 'o') 112 | plt.title("T-SNE") 113 | plt.savefig(os.path.join(args.res_dir, "t-sne.png")) 114 | 115 | # plot lda 116 | # res = lda(x, y) 117 | # np.savetxt("3.txt", res) 118 | res = np.loadtxt("2.txt") 119 | plt.figure(figsize=(8, 5)) 120 | plt.scatter(res[:, 0], res[:, 1], c = y, marker = 'o') 121 | plt.title("LDA") 122 | plt.savefig(os.path.join(args.res_dir, "lda.png")) 123 | -------------------------------------------------------------------------------- /cnn/dataset.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | ###### 5 | # 6 | # Mail npuxpli@mail.nwpu.edu.cn 7 | # Author LiXiping 8 | # Date 2019/09/20 16:19:34 9 | # 10 | ###### 11 | import torch.utils.data as data 12 | import os 13 | import numpy as np 14 | import torch 15 | import cv2 16 | 17 | class Infrared_Dataloader(data.Dataset): 18 | def __init__(self, training_file, test_file, label_dim, train=True, transform=None, target_transform=None): 19 | self.transform = transform 20 | self.target_transform = target_transform 21 | self.training_file = training_file 22 | self.test_file = test_file 23 | self.train = train # training set or test set 24 | self.label_dim = 8 25 | if self.train: 26 | data_file = self.training_file 27 | else: 28 | data_file = self.test_file 29 | self.data = open(data_file).readlines() 30 | 31 | def __getitem__(self, index): 32 | img_path, target = self.data[index].split(" ") 33 | img = cv2.imread(img_path,0) 34 | img = cv2.resize(img, (350, 250)) 35 | img = np.array(img, dtype="float32") / 255 36 | #img = img[np.newaxis, :, :] 37 | if self.transform is not None: 38 | img = self.transform(img) 39 | # img = np.expand_dims(img, axis=2)# [338,328] [338,328,1] 40 | # return torch.from_numpy(img).long(), torch.tensor(int(target)) 41 | return img, torch.tensor(int(target)) 42 | 43 | def __len__(self): 44 | return len(self.data) 45 | #CUDA_VISIBLE_DEVICES=2 -------------------------------------------------------------------------------- /cnn/process_data.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | ###### 5 | # 6 | # Mail npuxpli@mail.nwpu.edu.cn 7 | # Author LiXiping 8 | # Date 2019/09/20 16:19:34 9 | # 10 | ###### 11 | import os 12 | import argparse 13 | import numpy as np 14 | import cv2 15 | 16 | def calculate_mean_stdev(train_dir): 17 | imgs = np.zeros([328,338,1]) 18 | for i, img_dir in enumerate(sorted(os.listdir(train_dir))): 19 | img_folder = os.path.join(train_dir,img_dir) 20 | for item in os.listdir(img_folder): 21 | img_path = os.path.join(img_folder, item) 22 | img = cv2.imread(img_path,0) 23 | img = img[:,:,np.newaxis] 24 | imgs = np.concatenate((imgs,img), axis=2) 25 | imgs = imgs.astype(np.float32) /255 26 | pixels = imgs.ravel() 27 | means = np.mean(pixels) 28 | stdev = np.std(pixels) 29 | print("means:{}".format(means)) 30 | print("stdev:{}".format(stdev)) 31 | 32 | 33 | 34 | 35 | def process_data(in_dir, out_file): 36 | out_file = open(out_file, 'w') 37 | for i, img_dir in enumerate(sorted(os.listdir(in_dir))): 38 | img_folder = os.path.join(in_dir,img_dir) 39 | for item in os.listdir(img_folder): 40 | line = os.path.abspath(os.path.join(img_folder, item)) + " " + str(i) + "\n" 41 | out_file.write(line) 42 | out_file.close() 43 | 44 | if __name__ == '__main__': 45 | parser = argparse.ArgumentParser() 46 | parser.add_argument("--train_dir") 47 | parser.add_argument("--test_dir") 48 | parser.add_argument("--train_file") 49 | parser.add_argument("--test_file") 50 | args = parser.parse_args() 51 | process_data(args.train_dir, args.train_file) 52 | process_data(args.test_dir, args.test_file) 53 | #calculate_mean_stdev(args.train_dir) 54 | -------------------------------------------------------------------------------- /cnn/process_data.sh: -------------------------------------------------------------------------------- 1 | python process_data.py \ 2 | --train_dir=./4/train \ 3 | --test_dir=./4/test \ 4 | --train_file=./4/train.lst \ 5 | --test_file=./4/test.lst 6 | -------------------------------------------------------------------------------- /cnn/run.sh: -------------------------------------------------------------------------------- 1 | python train.py \ 2 | --batch-size=1 \ 3 | --save-model \ 4 | --base_dir="./4" \ 5 | --epochs=100 6 | -------------------------------------------------------------------------------- /cnn/train.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | ###### 5 | # 6 | # Mail npuxpli@mail.nwpu.edu.cn 7 | # Author LiXiping 8 | # Date 2019/09/20 16:19:34 9 | # 10 | ###### 11 | from __future__ import print_function 12 | import argparse 13 | import time 14 | import torch 15 | import torch.nn as nn 16 | import torch.nn.functional as F 17 | import torch.optim as optim 18 | import os 19 | from torchvision import datasets, transforms 20 | from dataset import Infrared_Dataloader 21 | 22 | 23 | class Net(nn.Module): 24 | def __init__(self): 25 | super(Net, self).__init__() 26 | # self.conv1 = nn.Conv2d(1, 20, 5, 1) 27 | # self.conv2 = nn.Conv2d(20, 50, 5, 1) 28 | self.conv1 = nn.Conv2d(1, 20, 3, 2) 29 | self.conv2 = nn.Conv2d(20, 50, 3, 2) 30 | self.conv3 = nn.Conv2d(50, 80, 3, 2) 31 | self.conv4 = nn.Conv2d(80,30,3,2) 32 | # self.fc1 = nn.Linear(4*4*50, 500) 33 | self.fc1 = nn.Linear(30, 500) 34 | self.fc2 = nn.Linear(500, 7) 35 | 36 | def forward(self, x): 37 | # print(x.size(0)) 38 | # x = torch.reshape(x,[1,1,328,338]) 39 | x = F.relu(self.conv1(x)) 40 | x = F.max_pool2d(x, 2, 2) 41 | x = F.relu(self.conv2(x)) 42 | x = F.max_pool2d(x, 2, 2) 43 | x = F.relu(self.conv3(x)) 44 | x = F.max_pool2d(x, 2, 2) 45 | x = F.relu(self.conv4(x)) 46 | x = F.max_pool2d(x, 2, 2) 47 | x = x.view(-1, 30) 48 | x = F.relu(self.fc1(x)) 49 | x = self.fc2(x) 50 | return F.log_softmax(x, dim=1) 51 | 52 | def train(args, model, device, train_loader, optimizer, epoch): 53 | model.train() 54 | for batch_idx, (data, target) in enumerate(train_loader): 55 | data, target = data.to(device), target.to(device) 56 | optimizer.zero_grad() 57 | output = model(data) 58 | loss = F.nll_loss(output, target) 59 | loss.backward() 60 | optimizer.step() 61 | if batch_idx % args.log_interval == 0: 62 | print('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}'.format( 63 | epoch, batch_idx * len(data), len(train_loader), 64 | 100. * batch_idx / len(train_loader), loss.item())) 65 | 66 | def test(args, model, device, test_loader): 67 | model.eval() 68 | test_loss = 0 69 | correct = 0 70 | with torch.no_grad(): 71 | for data, target in test_loader: 72 | data, target = data.to(device), target.to(device) 73 | output = model(data) 74 | test_loss += F.nll_loss(output, target, reduction='sum').item() # sum up batch loss 75 | pred = output.argmax(dim=1, keepdim=True) # get the index of the max log-probability 76 | correct += pred.eq(target.view_as(pred)).sum().item() 77 | 78 | test_loss /= len(test_loader.dataset) 79 | 80 | print('\nTest set: Average loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)\n'.format( 81 | test_loss, correct, len(test_loader.dataset), 82 | 100. * correct / len(test_loader.dataset))) 83 | 84 | def main(): 85 | # Training settings 86 | parser = argparse.ArgumentParser(description='PyTorch MNIST Example') 87 | parser.add_argument('--batch-size', type=int, default=64, metavar='N', 88 | help='input batch size for training (default: 64)') 89 | parser.add_argument('--test-batch-size', type=int, default=1000, metavar='N', 90 | help='input batch size for testing (default: 1000)') 91 | parser.add_argument('--epochs', type=int, default=10, metavar='N', 92 | help='number of epochs to train (default: 10)') 93 | parser.add_argument('--lr', type=float, default=0.01, metavar='LR', 94 | help='learning rate (default: 0.01)') 95 | parser.add_argument('--momentum', type=float, default=0.5, metavar='M', 96 | help='SGD momentum (default: 0.5)') 97 | parser.add_argument('--no-cuda', action='store_true', default=False, 98 | help='disables CUDA training') 99 | parser.add_argument('--seed', type=int, default=1, metavar='S', 100 | help='random seed (default: 1)') 101 | parser.add_argument('--log-interval', type=int, default=10, metavar='N', 102 | help='how many batches to wait before logging training status') 103 | parser.add_argument('--save-model', action='store_true', default=False, 104 | help='For Saving the current Model') 105 | parser.add_argument('--base_dir') 106 | args = parser.parse_args() 107 | use_cuda = not args.no_cuda and torch.cuda.is_available() 108 | torch.manual_seed(args.seed) 109 | device = torch.device("cuda" if use_cuda else "cpu") 110 | kwargs = {'num_workers': 1, 'pin_memory': True} if use_cuda else {} 111 | 112 | #train_loader = torch.utils.data.DataLoader( 113 | # datasets.MNIST('../data', train=True, download=True, 114 | # transform=transforms.Compose([ 115 | # transforms.ToTensor(), 116 | # transforms.Normalize((0.1307,), (0.3081,)) 117 | # ])), 118 | # batch_size=args.batch_size, shuffle=True, **kwargs) 119 | #test_loader = torch.utils.data.DataLoader( 120 | # datasets.MNIST('../data', train=False, transform=transforms.Compose([ 121 | # transforms.ToTensor(), 122 | # transforms.Normalize((0.1307,), (0.3081,)) 123 | # ])), 124 | # batch_size=args.test_batch_size, shuffle=True, **kwargs) 125 | training_file = os.path.join(args.base_dir, "train.lst") 126 | test_file = os.path.join(args.base_dir, "test.lst") 127 | train_loader = torch.utils.data.DataLoader( 128 | Infrared_Dataloader(training_file, test_file, label_dim=8, 129 | train=True,transform=transforms.Compose([ 130 | transforms.ToTensor(), 131 | transforms.Normalize((0.12405,), (0.03575,)) 132 | ])), 133 | batch_size=args.batch_size, shuffle=True, **kwargs) 134 | test_loader = torch.utils.data.DataLoader( 135 | Infrared_Dataloader(training_file, test_file, label_dim=8, 136 | train=False, 137 | transform=transforms.Compose([ 138 | transforms.ToTensor(), 139 | transforms.Normalize((0.12405,), (0.03575,)) 140 | ])), 141 | batch_size=args.test_batch_size, shuffle=True, **kwargs) 142 | 143 | model = Net().to(device) 144 | optimizer = optim.SGD(model.parameters(), lr=args.lr, momentum=args.momentum) 145 | 146 | for epoch in range(1, args.epochs + 1): 147 | t1 = time.time() 148 | train(args, model, device, train_loader, optimizer, epoch) 149 | print("t1:",time.time()-t1) 150 | t2 = time.time() 151 | test(args, model, device, test_loader) 152 | print("t2:", time.time() - t2) 153 | if (args.save_model): 154 | torch.save(model.state_dict(),"5f2d.pt") 155 | 156 | if __name__ == '__main__': 157 | main() 158 | -------------------------------------------------------------------------------- /data_visualization.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | ###################################################################### 5 | # 6 | # Copyright 205@NPU. All Rights Reserved 7 | # 8 | # Licensed under the Apache License, Veresion 2.0(the "License"); 9 | # You may not use the file except in compliance with the Licese. 10 | # You may obtain a copy of the License at 11 | # 12 | # http://www.apache.org/license/LICENSE-2.0 13 | # 14 | # Unless required by applicable law or agreed to in writing,software 15 | # distributed under the License is distributed on an "AS IS" BASIS 16 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | # See the License for the specific language governing permissions and 18 | # limitations under the License. 19 | # 20 | # Author lixping 21 | # congjian 22 | # Date 2019/05/12 15:30:10 23 | # 24 | ###################################################################### 25 | 26 | 27 | import os 28 | 29 | import argparse 30 | import cv2 31 | import matplotlib.pyplot as plt 32 | import numpy as np 33 | from sklearn.manifold import TSNE 34 | from sklearn.decomposition import PCA 35 | from sklearn.discriminant_analysis import LinearDiscriminantAnalysis 36 | from tqdm import tqdm 37 | 38 | from feature import * 39 | 40 | def get_feature(work_dir): 41 | hu = get_hu(work_dir) 42 | svd = get_svd(work_dir) 43 | mr = get_mr(work_dir) 44 | pzor = get_pzor(work_dir) 45 | #sift = get_sift(work_dir) 46 | minrectangle = get_minrectangle(work_dir) 47 | #harris = get_harris(work_dir) 48 | #fourier = get_fourier(work_dir) 49 | feature = np.concatenate(( mr, pzor,minrectangle,svd,hu)) 50 | #feature1 = maxmin_normalization(feature) 51 | #feature2 = standard_normalization(feature) 52 | #feature3 = log_normalization(feature) 53 | #feature = np.concatenate(( mr, hu)) 54 | #return feature 55 | return feature 56 | 57 | def lda(x, y): 58 | lda = LinearDiscriminantAnalysis(n_components=2) 59 | lda.fit(x, y) 60 | res = lda.transform(x) 61 | return res 62 | 63 | def pca(x): 64 | pca = PCA(n_components=2) 65 | res = pca.fit_transform(x) 66 | return res 67 | 68 | def t_sne(x): 69 | tsne = TSNE(n_components=2, init='pca', random_state=0) 70 | tsne.fit_transform(x) 71 | res = tsne.embedding_ 72 | return res 73 | 74 | if __name__ == '__main__': 75 | parser = argparse.ArgumentParser() 76 | parser.add_argument("--work_dir", default="5f2d/train") 77 | parser.add_argument("--res_dir", default="data_visual_res_jcong") 78 | args = parser.parse_args() 79 | 80 | x = [] 81 | y = [] 82 | for label, class_dir in tqdm(enumerate(sorted(os.listdir(args.work_dir)))): 83 | for img in tqdm(sorted(os.listdir(os.path.join(args.work_dir, class_dir)))): 84 | work_dir = os.path.join(args.work_dir, class_dir, img) 85 | # feature = get_feature(work_dir) 86 | # x.append(feature) 87 | y.append(label) 88 | x = np.array(x).astype(np.float64) 89 | y = np.array(y).astype(np.int64).transpose() 90 | np.savetxt("y.txt",y) 91 | 92 | if not os.path.exists(args.res_dir): 93 | os.mkdir(args.res_dir) 94 | 95 | 96 | 97 | # plot pca 98 | # res = pca(x) 99 | # np.savetxt("1.txt",res) 100 | res = np.loadtxt("1.txt") 101 | plt.figure(figsize = (8, 5)) 102 | plt.scatter(res[:, 0], res[:, 1], c = y, marker='o') 103 | plt.title("PCA") 104 | plt.savefig(os.path.join(args.res_dir,"pca.png")) 105 | 106 | # plot t-sne 107 | # res = t_sne(x) 108 | # np.savetxt("2.txt", res) 109 | res = np.loadtxt("2.txt") 110 | plt.figure(figsize = (8, 5)) 111 | plt.scatter(res[:, 0], res[:, 1], c = y, marker = 'o') 112 | plt.title("T-SNE") 113 | plt.savefig(os.path.join(args.res_dir, "t-sne.png")) 114 | 115 | # plot lda 116 | # res = lda(x, y) 117 | # np.savetxt("3.txt", res) 118 | res = np.loadtxt("2.txt") 119 | plt.figure(figsize=(8, 5)) 120 | plt.scatter(res[:, 0], res[:, 1], c = y, marker = 'o') 121 | plt.title("LDA") 122 | plt.savefig(os.path.join(args.res_dir, "lda.png")) 123 | -------------------------------------------------------------------------------- /example-data_visual_resimg/lda.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lesleyping/Machine-Learning/3ab1d320106c2f10ea4e6947a2ddaa79712498ab/example-data_visual_resimg/lda.png -------------------------------------------------------------------------------- /example-data_visual_resimg/pca.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lesleyping/Machine-Learning/3ab1d320106c2f10ea4e6947a2ddaa79712498ab/example-data_visual_resimg/pca.png -------------------------------------------------------------------------------- /example-data_visual_resimg/t-sne.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lesleyping/Machine-Learning/3ab1d320106c2f10ea4e6947a2ddaa79712498ab/example-data_visual_resimg/t-sne.png -------------------------------------------------------------------------------- /feature2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | ###### 5 | # 6 | # Mail npuxpli@mail.nwpu.edu.cn 7 | # Author LiXiping 8 | # Date 2019/09/20 16:19:34 9 | # 10 | ###### 11 | 12 | import cv2 13 | import math 14 | import numpy as np 15 | from numpy import linalg as la 16 | from skimage import measure 17 | from PIL import Image 18 | 19 | def get_svd(img_path): 20 | img = cv2.imread(img_path, 0) 21 | U,sigma,VT=la.svd(img) 22 | # print(sigma) 23 | #print("svd sigma") 24 | #print(type(sigma)) 25 | # sigma[::-1].sort() 26 | sigma = sigma[:10] 27 | return sigma 28 | 29 | def get_hu(img_path): 30 | img = cv2.imread(img_path, 0) 31 | moments = cv2.moments(img) 32 | humoments = cv2.HuMoments(moments) 33 | # humoments = np.log(np.abs(humoments)) 34 | humoments = humoments.transpose()[0] 35 | hu1 = np.log(np.abs(humoments[0])) 36 | hu2 = np.log(np.abs(humoments[1])) 37 | hu = '{},{}'.format(hu1, hu2) 38 | hu = hu.strip(',').split(',') 39 | #print(hu) 40 | return hu 41 | 42 | 43 | def get_mr(img_path): 44 | def im2double(im): 45 | min_val = np.min(im) 46 | max_val = np.max(im) 47 | #out = (im.astype(np.float32) - min_val) / (max_val - min_val) 48 | out = im.astype(np.float32) 49 | return out 50 | 51 | image_in = cv2.imread(img_path, 0) 52 | # Otsu滤波 53 | threshold, image_BW = cv2.threshold(image_in ,0,255, 54 | cv2.THRESH_BINARY+cv2.THRESH_OTSU) 55 | 56 | orign_image=im2double(np.array(image_in)) 57 | binary_image=im2double(np.array(image_BW)) 58 | [m, n] = image_in.shape 59 | sum_foreground=0 60 | sum_background=0 61 | count_foreground=0 62 | count_background=0 63 | 64 | for row in range(m): 65 | for col in range(n): 66 | if binary_image[row,col] != 0: 67 | sum_foreground = sum_foreground + orign_image[row,col] 68 | count_foreground = count_foreground + 1 69 | else: 70 | sum_background = sum_background + orign_image[row,col] 71 | count_background = count_background + 1 72 | 73 | m1 = sum_foreground / count_foreground 74 | m2 = sum_background / count_background 75 | if m2 != 0: 76 | MR = m1 / m2 77 | else: 78 | MR = 0 79 | 80 | return np.array([MR]) 81 | 82 | def get_pzor(img_path): 83 | def im2double(im): 84 | min_val = np.min(im) 85 | max_val = np.max(im) 86 | out = (im.astype(np.float32) - min_val) / (max_val - min_val) 87 | return out 88 | 89 | image_in = cv2.imread(img_path, 0) 90 | threshold, image_BW = cv2.threshold(image_in ,0,255, 91 | cv2.THRESH_BINARY+cv2.THRESH_OTSU) 92 | 93 | orign_image=im2double(np.array(image_in)) 94 | binary_image=im2double(np.array(image_BW)) 95 | 96 | [m,n] = image_in.shape 97 | 98 | count = 0 99 | light = 0 100 | B = np.ones((m,n))*0 101 | 102 | for row in range(m): 103 | for col in range(n): 104 | if binary_image[row , col] != 0: 105 | B[row, col] = orign_image[row,col] 106 | count = count + 1 107 | thresh =(np.max(B))*0.9 108 | for row in range(m): 109 | for col in range(n): 110 | if orign_image[row , col] > thresh: 111 | light = light + 1 112 | light = float(light) 113 | count = float(count) 114 | # print(light) 115 | # print(count) 116 | Pzor = float(light/count) 117 | return np.array([Pzor]) 118 | 119 | def get_minrectangle(img_path): 120 | image_in = cv2.imread(img_path, 0) 121 | threshold, image_BW = cv2.threshold(image_in ,0,255, 122 | cv2.THRESH_BINARY+cv2.THRESH_OTSU) 123 | labels = measure.label(image_BW, connectivity=2) 124 | regions = measure.regionprops(labels) 125 | 126 | area_max = 0 127 | for r in regions: 128 | if r.area > area_max: 129 | area_max = r.area 130 | x = float(r.bbox[0]) 131 | y = float(r.bbox[1]) 132 | width = float(r.bbox[3] - r.bbox[1]) 133 | height = float(r.bbox[2] - r.bbox[0]) 134 | ration = float(height /width) 135 | extent = r.extent 136 | 137 | minrectangle = '{},{},{},{},{},{},{}'.format(x, y, width, height, area_max, ration, extent) 138 | minrectangle = minrectangle.strip(',').split(',') 139 | #print(minrectangle) 140 | return minrectangle 141 | 142 | def get_sift(img_path): 143 | img = cv2.imread(img_path , 0) 144 | sift = cv2.xfeatures2d.SIFT_create() 145 | kp = sift.detect(img , None) 146 | num = len(kp) 147 | 148 | return np.array([num]) 149 | 150 | def get_harris(img_path): 151 | img = cv2.imread(img_path , 0) 152 | img = np.float32(img) 153 | dst = cv2.cornerHarris(img ,2 ,3,0.04) 154 | dst = cv2.dilate(dst , None) 155 | num = len(dst) 156 | return np.array([num]) 157 | 158 | 159 | def truncate_descriptor(descriptors, degree): 160 | """this function truncates an unshifted fourier descriptor array 161 | and returns one also unshifted""" 162 | descriptors = np.fft.fftshift(descriptors) 163 | center_index = len(descriptors) / 2 164 | descriptors = descriptors[ 165 | center_index - degree / 2:center_index + degree / 2] 166 | descriptors = np.fft.ifftshift(descriptors) 167 | return descriptors 168 | 169 | def reconstruct(descriptors, degree): 170 | """ reconstruct(descriptors, degree) attempts to reconstruct the image 171 | using the first [degree] descriptors of descriptors""" 172 | # truncate the long list of descriptors to certain length 173 | descriptor_in_use = truncate_descriptor(descriptors, degree) 174 | contour_reconstruct = np.fft.ifft(descriptor_in_use) 175 | contour_reconstruct = np.array( 176 | [contour_reconstruct.real, contour_reconstruct.imag]) 177 | contour_reconstruct = np.transpose(contour_reconstruct) 178 | contour_reconstruct = np.expand_dims(contour_reconstruct, axis=1) 179 | # make positive 180 | if contour_reconstruct.min() < 0: 181 | contour_reconstruct -= contour_reconstruct.min() 182 | # normalization 183 | contour_reconstruct *= 800 / contour_reconstruct.max() 184 | # type cast to int32 185 | contour_reconstruct = contour_reconstruct.astype(np.int32, copy=False) 186 | black = np.zeros((800, 800), np.uint8) 187 | # draw and visualize 188 | # cv2.drawContours(black, contour_reconstruct, -1, 255, thickness=-1) 189 | # cv2.imshow("black", black) 190 | # cv2.waitKey(1000) 191 | # cv2.imwrite("reconstruct_result.jpg", black) 192 | # cv2.destroyAllWindows() 193 | return descriptor_in_use 194 | 195 | # def addNoise(descriptors): 196 | # """this function adds gaussian noise to descriptors 197 | # descriptors should be a [N,2] numpy array""" 198 | # scale = descriptors.max() / 10 199 | # noise = np.random.normal(0, scale, descriptors.shape[0]) 200 | # noise = noise + 1j * noise 201 | # descriptors += noise 202 | 203 | 204 | def get_fourier(img_path): 205 | img = cv2.imread(img_path , 0) 206 | retval, img = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY_INV) 207 | 208 | contour = [] 209 | _, contour, hierarchy = cv2.findContours( 210 | img, 211 | cv2.RETR_EXTERNAL, 212 | cv2.CHAIN_APPROX_NONE, 213 | contour 214 | ) 215 | contour_array = contour[0][:, 0, :] 216 | contour_complex = np.empty(contour_array.shape[:-1], dtype=complex) 217 | contour_complex.real = contour_array[: , 0] 218 | contour_complex.imag = contour_array[: , 1] 219 | fourier_result = np.fft.fft(contour_complex) 220 | 221 | contour = reconstruct(fourier_result, 2) 222 | #addNoise(contour) 223 | contour = np.absolute(contour) 224 | 225 | return contour 226 | 227 | 228 | 229 | 230 | # path = '063.bmp' 231 | # # a = Image.open(path) 232 | # # a = np.array(a) 233 | # s = get_svd(path) 234 | # print(s) 235 | 236 | 237 | # a,b,c = get_svd(path) 238 | # a.shape = (328,1) 239 | # # a = np.transpose(a) 240 | # print(a.shape) 241 | # d = b[:,:]*a[50:]*c[:50] 242 | 243 | # print(a) 244 | # print(type(contour)) 245 | # print(contour) 246 | 247 | 248 | -------------------------------------------------------------------------------- /img_tools.py: -------------------------------------------------------------------------------- 1 | """ 2 | 一些图像处理工具 3 | """ 4 | import os 5 | from PIL import Image 6 | from cfg import img_path, bin_clear_folder, origin_pic_folder, cut_pic_folder, data_root 7 | from os.path import join 8 | 9 | 10 | def get_bin_table(threshold=140): 11 | """ 12 | 获取灰度转二值的映射table 13 | :param threshold: 14 | :return: 15 | """ 16 | table = [] 17 | for i in range(256): 18 | if i < threshold: 19 | table.append(0) 20 | else: 21 | table.append(1) 22 | 23 | return table 24 | 25 | 26 | def sum_9_region(img, x, y): 27 | """ 28 | 9邻域框,以当前点为中心的田字框,黑点个数,作为移除一些孤立的点的判断依据 29 | :param img: Image 30 | :param x: 31 | :param y: 32 | :return: 33 | """ 34 | cur_pixel = img.getpixel((x, y)) # 当前像素点的值 35 | width = img.width 36 | height = img.height 37 | 38 | if cur_pixel == 1: # 如果当前点为白色区域,则不统计邻域值 39 | return 0 40 | 41 | if y == 0: # 第一行 42 | if x == 0: # 左上顶点,4邻域 43 | # 中心点旁边3个点 44 | sum = cur_pixel \ 45 | + img.getpixel((x, y + 1)) \ 46 | + img.getpixel((x + 1, y)) \ 47 | + img.getpixel((x + 1, y + 1)) 48 | return 4 - sum 49 | elif x == width - 1: # 右上顶点 50 | sum = cur_pixel \ 51 | + img.getpixel((x, y + 1)) \ 52 | + img.getpixel((x - 1, y)) \ 53 | + img.getpixel((x - 1, y + 1)) 54 | 55 | return 4 - sum 56 | else: # 最上非顶点,6邻域 57 | sum = img.getpixel((x - 1, y)) \ 58 | + img.getpixel((x - 1, y + 1)) \ 59 | + cur_pixel \ 60 | + img.getpixel((x, y + 1)) \ 61 | + img.getpixel((x + 1, y)) \ 62 | + img.getpixel((x + 1, y + 1)) 63 | return 6 - sum 64 | elif y == height - 1: # 最下面一行 65 | if x == 0: # 左下顶点 66 | # 中心点旁边3个点 67 | sum = cur_pixel \ 68 | + img.getpixel((x + 1, y)) \ 69 | + img.getpixel((x + 1, y - 1)) \ 70 | + img.getpixel((x, y - 1)) 71 | return 4 - sum 72 | elif x == width - 1: # 右下顶点 73 | sum = cur_pixel \ 74 | + img.getpixel((x, y - 1)) \ 75 | + img.getpixel((x - 1, y)) \ 76 | + img.getpixel((x - 1, y - 1)) 77 | 78 | return 4 - sum 79 | else: # 最下非顶点,6邻域 80 | sum = cur_pixel \ 81 | + img.getpixel((x - 1, y)) \ 82 | + img.getpixel((x + 1, y)) \ 83 | + img.getpixel((x, y - 1)) \ 84 | + img.getpixel((x - 1, y - 1)) \ 85 | + img.getpixel((x + 1, y - 1)) 86 | return 6 - sum 87 | else: # y不在边界 88 | if x == 0: # 左边非顶点 89 | sum = img.getpixel((x, y - 1)) \ 90 | + cur_pixel \ 91 | + img.getpixel((x, y + 1)) \ 92 | + img.getpixel((x + 1, y - 1)) \ 93 | + img.getpixel((x + 1, y)) \ 94 | + img.getpixel((x + 1, y + 1)) 95 | 96 | return 6 - sum 97 | elif x == width - 1: # 右边非顶点 98 | # print('%s,%s' % (x, y)) 99 | sum = img.getpixel((x, y - 1)) \ 100 | + cur_pixel \ 101 | + img.getpixel((x, y + 1)) \ 102 | + img.getpixel((x - 1, y - 1)) \ 103 | + img.getpixel((x - 1, y)) \ 104 | + img.getpixel((x - 1, y + 1)) 105 | 106 | return 6 - sum 107 | else: # 具备9领域条件的 108 | sum = img.getpixel((x - 1, y - 1)) \ 109 | + img.getpixel((x - 1, y)) \ 110 | + img.getpixel((x - 1, y + 1)) \ 111 | + img.getpixel((x, y - 1)) \ 112 | + cur_pixel \ 113 | + img.getpixel((x, y + 1)) \ 114 | + img.getpixel((x + 1, y - 1)) \ 115 | + img.getpixel((x + 1, y)) \ 116 | + img.getpixel((x + 1, y + 1)) 117 | return 9 - sum 118 | 119 | 120 | def remove_noise_pixel(img, noise_point_list): 121 | """ 122 | 根据噪点的位置信息,消除二值图片的黑点噪声 123 | :type img:Image 124 | :param img: 125 | :param noise_point_list: 126 | :return: 127 | """ 128 | for item in noise_point_list: 129 | img.putpixel((item[0], item[1]), 1) 130 | 131 | 132 | def get_clear_bin_image(image): 133 | """ 134 | 获取干净的二值化的图片。 135 | 图像的预处理: 136 | 1. 先转化为灰度 137 | 2. 再二值化 138 | 3. 然后清除噪点 139 | 参考:http://python.jobbole.com/84625/ 140 | :type img:Image 141 | :return: 142 | """ 143 | imgry = image.convert('L') # 转化为灰度图 144 | 145 | table = get_bin_table() 146 | out = imgry.point(table, '1') # 变成二值图片:0表示黑色,1表示白色 147 | 148 | noise_point_list = [] # 通过算法找出噪声点,第一步比较严格,可能会有些误删除的噪点 149 | for x in range(out.width): 150 | for y in range(out.height): 151 | res_9 = sum_9_region(out, x, y) 152 | if (0 < res_9 < 3) and out.getpixel((x, y)) == 0: # 找到孤立点 153 | pos = (x, y) # 154 | noise_point_list.append(pos) 155 | remove_noise_pixel(out, noise_point_list) 156 | return out 157 | 158 | 159 | def get_crop_imgs(img): 160 | """ 161 | 按照图片的特点,进行切割,这个要根据具体的验证码来进行工作. # 见本例验证图的结构原理图 162 | 分割图片是传统机器学习来识别验证码的重难点,如果这一步顺利的话,则多位验证码的问题可以转化为1位验证字符的识别问题 163 | :param img: 164 | :return: 165 | """ 166 | child_img_list = [] 167 | for i in range(4): 168 | x = 2 + i * (6 + 4) # 见原理图 169 | y = 0 170 | child_img = img.crop((x, y, x + 6, y + 10)) 171 | child_img_list.append(child_img) 172 | 173 | return child_img_list 174 | 175 | 176 | def print_line_x(img, x): 177 | """ 178 | 打印一个Image图像的第x行,方便调试 179 | :param img: 180 | :type img:Image 181 | :param x: 182 | :return: 183 | """ 184 | print("line:%s" % x) 185 | for w in range(img.width): 186 | print(img.getpixel((w, x)), end='') 187 | print('') 188 | 189 | 190 | def print_bin(img): 191 | """ 192 | 输出二值后的图片到控制台,方便调试的函数 193 | :param img: 194 | :type img: Image 195 | :return: 196 | """ 197 | print('current binary output,width:%s-height:%s\n') 198 | for h in range(img.height): 199 | for w in range(img.width): 200 | print(img.getpixel((w, h)), end='') 201 | print('') 202 | 203 | 204 | def save_crop_imgs(bin_clear_image_path, child_img_list): 205 | """ 206 | 输入:整个干净的二化图片 207 | 输出:每张切成4版后的图片集 208 | 保存切割的图片 209 | 210 | 例如: A.png ---> A-1.png,A-2.png,... A-4.png 并保存,这个保存后需要去做label标记的 211 | :param bin_clear_image_path: xxxx/xxxxx/xxxxx.png 主要是用来提取切割的子图保存的文件名称 212 | :param child_img_list: 213 | :return: 214 | """ 215 | full_file_name = os.path.basename(bin_clear_image_path) # 文件名称 216 | full_file_name_split = full_file_name.split('.') 217 | file_name = full_file_name_split[0] 218 | # file_ext = full_file_name_split[1] 219 | 220 | i = 0 221 | for child_img in child_img_list: 222 | cut_img_file_name = file_name + '-' + ("%s.png" % i) 223 | child_img.save(join(cut_pic_folder, cut_img_file_name)) 224 | i += 1 225 | 226 | 227 | # 训练素材准备:文件目录下面的图片的批量操作 228 | 229 | def batch_get_all_bin_clear(): 230 | """ 231 | 训练素材准备。 232 | 批量操作:获取所有去噪声的二值图片 233 | :return: 234 | """ 235 | 236 | file_list = os.listdir(origin_pic_folder) 237 | for file_name in file_list: 238 | file_full_path = os.path.join(origin_pic_folder, file_name) 239 | image = Image.open(file_full_path) 240 | get_clear_bin_image(image) 241 | 242 | 243 | def batch_cut_images(): 244 | """ 245 | 训练素材准备。 246 | 批量操作:分割切除所有 "二值 -> 除噪声" 之后的图片,变成所有的单字符的图片。然后保存到相应的目录,方便打标签 247 | """ 248 | 249 | file_list = os.listdir(bin_clear_folder) 250 | for file_name in file_list: 251 | bin_clear_img_path = os.path.join(bin_clear_folder, file_name) 252 | img = Image.open(bin_clear_img_path) 253 | 254 | child_img_list = get_crop_imgs(img) 255 | save_crop_imgs(bin_clear_img_path, child_img_list) # 将切割的图进行保存,后面打标签时要用 256 | 257 | 258 | # 中间的demo效果演示 259 | 260 | 261 | def demo_cut_pic(): 262 | """ 263 | 做实验研究时的演示代码 264 | :return: 265 | """ 266 | img_path = join(data_root, 'demo-6937/ocr-simple-char-captcha-bin-clear-6937.png') 267 | img = Image.open(img_path) 268 | cut_save = data_root + '/demo-6937' 269 | child_img_list = get_crop_imgs(img) 270 | 271 | index = 0 272 | for child_img in child_img_list: 273 | child_img.save(cut_save + '/cut-%d.png' % index) 274 | index += 1 275 | 276 | 277 | def get_bin_img_name(img_path): 278 | """ 279 | 根据原始origin 文件路径,获取二值而且去噪声的文件路径 280 | :param img_path: 281 | :type img_path:str 282 | :return: 283 | """ 284 | path_split = img_path.split('/') 285 | file_name_split = path_split[-1].split('.') 286 | file_name = file_name_split[0] # 文件名 287 | # file_ext = file_name_split[1] # 扩展名 288 | 289 | new_file = '/'.join(item for item in path_split[:-2]) + '/bin_clear/' + file_name + '.png' 290 | return new_file 291 | 292 | 293 | def demo_handle_save_bin_clear_pic(image): 294 | """ 295 | 图像处理函数的演示 296 | 在训练分析阶段的时候使用:保存二次的二值图, 297 | :type img:Image 298 | :return: 299 | """ 300 | out = get_clear_bin_image(image) 301 | new_file_path = get_bin_img_name(img_path) 302 | print(new_file_path) 303 | out.save(new_file_path) 304 | 305 | 306 | if __name__ == "__main__": 307 | print(get_bin_table()) 308 | # batch_get_all_bin_clear() # 获取所有的二值化的初步去噪的图片 309 | # cut_all_pic() # 切割图片成单个字 310 | # save_train_txt() 311 | # save_test_txt() 312 | # crack_captcha() 313 | # img = Image.open(img_path) 314 | # handle_save_bin_clear_pic(img) 315 | # demo_cut_pic() 316 | pass 317 | -------------------------------------------------------------------------------- /knn.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | ###### 5 | # 6 | # Mail npuxpli@mail.nwpu.edu.cn 7 | # Author LiXiping 8 | # Date 2019/09/20 16:19:34 9 | # 10 | ###### 11 | 12 | import os 13 | import time 14 | 15 | import argparse 16 | from feature2 import * 17 | from numpy import * 18 | import operator 19 | 20 | 21 | def get_feature(img_path): 22 | hu = get_hu(img_path) 23 | svd = get_svd(img_path) 24 | mr = get_mr(img_path) 25 | pzor = get_pzor(img_path) 26 | #sift = get_sift(img_path) 27 | minrectangle = get_minrectangle(img_path) 28 | #harris = get_harris(img_path) 29 | #fourier = get_fourier(img_path) 30 | 31 | feature = np.concatenate(( mr, pzor, minrectangle, hu, svd)) 32 | #feature = np.concatenate(( mr, hu)) 33 | return feature 34 | 35 | 36 | 37 | def classify(sample , features , labels , k): 38 | datasatSize = len(features) 39 | 40 | tempSet = tile(sample,(datasatSize,1)) 41 | tempSet = tempSet.astype('float64') 42 | features = np.array(features,dtype = np.float64) 43 | diffMat = tempSet -features 44 | sqDiffMat = diffMat**2 45 | sqDistances = sqDiffMat.sum(axis = 1) 46 | distances = sqDistances**0.5 47 | sortedDistIndicies = distances.argsort() 48 | 49 | 50 | classCount = {} 51 | for i in range(k): 52 | voteIlabel = labels[sortedDistIndicies[i]] 53 | classCount[voteIlabel]=classCount.get(voteIlabel,0)+1 54 | 55 | sortedClassCount = sorted(classCount.items(),key = operator.itemgetter(1) , reverse = True) 56 | return sortedClassCount[0][0] 57 | 58 | def decode(train_features,train_labels, test_file): 59 | k = 3 60 | right = 0 61 | sum = 0 62 | predict_labels = [] 63 | # model {"feature" [], labels: []} 64 | 65 | for i, img_dir in enumerate(sorted(os.listdir(test_file))): 66 | img_folder = os.path.join(test_file , img_dir) 67 | for item in os.listdir(img_folder): 68 | img_path = os.path.join(img_folder , item) 69 | sample = get_feature(img_path) 70 | label = classify(sample , train_features , train_labels , k) 71 | sum = sum+1 72 | if label == i+1 : 73 | right = right + 1 74 | predict_labels.append(label) 75 | print(right) 76 | print(sum) 77 | correct_rate = float(right)/float(sum) 78 | 79 | return correct_rate,predict_labels 80 | 81 | 82 | def train(train_dir): 83 | # 1 84 | # -- 001.bmp 85 | # -- 002.bmp 86 | # 2 87 | train_features = [] 88 | train_labels = [] 89 | 90 | for i, img_dir in enumerate(sorted(os.listdir(train_dir))): 91 | 92 | img_folder = os.path.join(train_dir, img_dir) 93 | for item in os.listdir(img_folder): 94 | img_path = os.path.join(img_folder, item) 95 | feature = get_feature(img_path) 96 | train_features.append(feature) 97 | train_labels.append(i+1) 98 | return train_features,train_labels 99 | 100 | if __name__=='__main__': 101 | parser = argparse.ArgumentParser() 102 | parser.add_argument("--train_dir") 103 | parser.add_argument("--test_dir") 104 | args = parser.parse_args() 105 | t1 = time.time() 106 | train_features, train_labels = train(args.train_dir) 107 | print("t1",time.time()-t1) 108 | t2 = time.time() 109 | c_r,predict = decode(train_features,train_labels, args.test_dir) 110 | print("t2", time.time() - t2) 111 | print(c_r) 112 | print(predict) 113 | -------------------------------------------------------------------------------- /knn.sh: -------------------------------------------------------------------------------- 1 | python knn.py \ 2 | --train_dir=./4/train \ 3 | --test_dir=./4/test -------------------------------------------------------------------------------- /lib/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lesleyping/Machine-Learning/3ab1d320106c2f10ea4e6947a2ddaa79712498ab/lib/__init__.py -------------------------------------------------------------------------------- /lib/__pycache__/__init__.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lesleyping/Machine-Learning/3ab1d320106c2f10ea4e6947a2ddaa79712498ab/lib/__pycache__/__init__.cpython-35.pyc -------------------------------------------------------------------------------- /lib/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lesleyping/Machine-Learning/3ab1d320106c2f10ea4e6947a2ddaa79712498ab/lib/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /lib/__pycache__/svm.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lesleyping/Machine-Learning/3ab1d320106c2f10ea4e6947a2ddaa79712498ab/lib/__pycache__/svm.cpython-35.pyc -------------------------------------------------------------------------------- /lib/__pycache__/svm.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lesleyping/Machine-Learning/3ab1d320106c2f10ea4e6947a2ddaa79712498ab/lib/__pycache__/svm.cpython-36.pyc -------------------------------------------------------------------------------- /lib/__pycache__/svmutil.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lesleyping/Machine-Learning/3ab1d320106c2f10ea4e6947a2ddaa79712498ab/lib/__pycache__/svmutil.cpython-35.pyc -------------------------------------------------------------------------------- /lib/__pycache__/svmutil.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lesleyping/Machine-Learning/3ab1d320106c2f10ea4e6947a2ddaa79712498ab/lib/__pycache__/svmutil.cpython-36.pyc -------------------------------------------------------------------------------- /lib/svm.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from ctypes import * 4 | from ctypes.util import find_library 5 | from os import path 6 | import sys 7 | 8 | if sys.version_info[0] >= 3: 9 | xrange = range 10 | 11 | __all__ = ['libsvm', 'svm_problem', 'svm_parameter', 12 | 'toPyModel', 'gen_svm_nodearray', 'print_null', 'svm_node', 'C_SVC', 13 | 'EPSILON_SVR', 'LINEAR', 'NU_SVC', 'NU_SVR', 'ONE_CLASS', 14 | 'POLY', 'PRECOMPUTED', 'PRINT_STRING_FUN', 'RBF', 15 | 'SIGMOID', 'c_double', 'svm_model'] 16 | 17 | try: 18 | dirname = path.dirname(path.abspath(__file__)) 19 | if sys.platform == 'win32': 20 | libsvm = CDLL(path.join(dirname, r'..\windows\libsvm.dll')) 21 | else: 22 | libsvm = CDLL(path.join(dirname, '../libsvm.so.2')) 23 | except: 24 | # For unix the prefix 'lib' is not considered. 25 | if find_library('svm'): 26 | libsvm = CDLL(find_library('svm')) 27 | elif find_library('libsvm'): 28 | libsvm = CDLL(find_library('libsvm')) 29 | else: 30 | raise Exception('LIBSVM library not found.') 31 | 32 | C_SVC = 0 33 | NU_SVC = 1 34 | ONE_CLASS = 2 35 | EPSILON_SVR = 3 36 | NU_SVR = 4 37 | 38 | LINEAR = 0 39 | POLY = 1 40 | RBF = 2 41 | SIGMOID = 3 42 | PRECOMPUTED = 4 43 | 44 | PRINT_STRING_FUN = CFUNCTYPE(None, c_char_p) 45 | def print_null(s): 46 | return 47 | 48 | def genFields(names, types): 49 | return list(zip(names, types)) 50 | 51 | def fillprototype(f, restype, argtypes): 52 | f.restype = restype 53 | f.argtypes = argtypes 54 | 55 | class svm_node(Structure): 56 | _names = ["index", "value"] 57 | _types = [c_int, c_double] 58 | _fields_ = genFields(_names, _types) 59 | 60 | def __str__(self): 61 | return '%d:%g' % (self.index, self.value) 62 | 63 | def gen_svm_nodearray(xi, feature_max=None, isKernel=None): 64 | if isinstance(xi, dict): 65 | index_range = xi.keys() 66 | elif isinstance(xi, (list, tuple)): 67 | if not isKernel: 68 | xi = [0] + xi # idx should start from 1 69 | index_range = range(len(xi)) 70 | else: 71 | raise TypeError('xi should be a dictionary, list or tuple') 72 | 73 | if feature_max: 74 | assert(isinstance(feature_max, int)) 75 | index_range = filter(lambda j: j <= feature_max, index_range) 76 | if not isKernel: 77 | index_range = filter(lambda j:xi[j] != 0, index_range) 78 | 79 | index_range = sorted(index_range) 80 | ret = (svm_node * (len(index_range)+1))() 81 | ret[-1].index = -1 82 | for idx, j in enumerate(index_range): 83 | ret[idx].index = j 84 | ret[idx].value = xi[j] 85 | max_idx = 0 86 | if index_range: 87 | max_idx = index_range[-1] 88 | return ret, max_idx 89 | 90 | class svm_problem(Structure): 91 | _names = ["l", "y", "x"] 92 | _types = [c_int, POINTER(c_double), POINTER(POINTER(svm_node))] 93 | _fields_ = genFields(_names, _types) 94 | 95 | def __init__(self, y, x, isKernel=None): 96 | if len(y) != len(x): 97 | raise ValueError("len(y) != len(x)") 98 | self.l = l = len(y) 99 | 100 | max_idx = 0 101 | x_space = self.x_space = [] 102 | for i, xi in enumerate(x): 103 | tmp_xi, tmp_idx = gen_svm_nodearray(xi,isKernel=isKernel) 104 | x_space += [tmp_xi] 105 | max_idx = max(max_idx, tmp_idx) 106 | self.n = max_idx 107 | 108 | self.y = (c_double * l)() 109 | for i, yi in enumerate(y): self.y[i] = yi 110 | 111 | self.x = (POINTER(svm_node) * l)() 112 | for i, xi in enumerate(self.x_space): self.x[i] = xi 113 | 114 | class svm_parameter(Structure): 115 | _names = ["svm_type", "kernel_type", "degree", "gamma", "coef0", 116 | "cache_size", "eps", "C", "nr_weight", "weight_label", "weight", 117 | "nu", "p", "shrinking", "probability"] 118 | _types = [c_int, c_int, c_int, c_double, c_double, 119 | c_double, c_double, c_double, c_int, POINTER(c_int), POINTER(c_double), 120 | c_double, c_double, c_int, c_int] 121 | _fields_ = genFields(_names, _types) 122 | 123 | def __init__(self, options = None): 124 | if options == None: 125 | options = '' 126 | self.parse_options(options) 127 | 128 | def __str__(self): 129 | s = '' 130 | attrs = svm_parameter._names + list(self.__dict__.keys()) 131 | values = map(lambda attr: getattr(self, attr), attrs) 132 | for attr, val in zip(attrs, values): 133 | s += (' %s: %s\n' % (attr, val)) 134 | s = s.strip() 135 | 136 | return s 137 | 138 | def set_to_default_values(self): 139 | self.svm_type = C_SVC; 140 | self.kernel_type = RBF 141 | self.degree = 3 142 | self.gamma = 0 143 | self.coef0 = 0 144 | self.nu = 0.5 145 | self.cache_size = 100 146 | self.C = 1 147 | self.eps = 0.001 148 | self.p = 0.1 149 | self.shrinking = 1 150 | self.probability = 0 151 | self.nr_weight = 0 152 | self.weight_label = None 153 | self.weight = None 154 | self.cross_validation = False 155 | self.nr_fold = 0 156 | self.print_func = cast(None, PRINT_STRING_FUN) 157 | 158 | def parse_options(self, options): 159 | if isinstance(options, list): 160 | argv = options 161 | elif isinstance(options, str): 162 | argv = options.split() 163 | else: 164 | raise TypeError("arg 1 should be a list or a str.") 165 | self.set_to_default_values() 166 | self.print_func = cast(None, PRINT_STRING_FUN) 167 | weight_label = [] 168 | weight = [] 169 | 170 | i = 0 171 | while i < len(argv): 172 | if argv[i] == "-s": 173 | i = i + 1 174 | self.svm_type = int(argv[i]) 175 | elif argv[i] == "-t": 176 | i = i + 1 177 | self.kernel_type = int(argv[i]) 178 | elif argv[i] == "-d": 179 | i = i + 1 180 | self.degree = int(argv[i]) 181 | elif argv[i] == "-g": 182 | i = i + 1 183 | self.gamma = float(argv[i]) 184 | elif argv[i] == "-r": 185 | i = i + 1 186 | self.coef0 = float(argv[i]) 187 | elif argv[i] == "-n": 188 | i = i + 1 189 | self.nu = float(argv[i]) 190 | elif argv[i] == "-m": 191 | i = i + 1 192 | self.cache_size = float(argv[i]) 193 | elif argv[i] == "-c": 194 | i = i + 1 195 | self.C = float(argv[i]) 196 | elif argv[i] == "-e": 197 | i = i + 1 198 | self.eps = float(argv[i]) 199 | elif argv[i] == "-p": 200 | i = i + 1 201 | self.p = float(argv[i]) 202 | elif argv[i] == "-h": 203 | i = i + 1 204 | self.shrinking = int(argv[i]) 205 | elif argv[i] == "-b": 206 | i = i + 1 207 | self.probability = int(argv[i]) 208 | elif argv[i] == "-q": 209 | self.print_func = PRINT_STRING_FUN(print_null) 210 | elif argv[i] == "-v": 211 | i = i + 1 212 | self.cross_validation = 1 213 | self.nr_fold = int(argv[i]) 214 | if self.nr_fold < 2: 215 | raise ValueError("n-fold cross validation: n must >= 2") 216 | elif argv[i].startswith("-w"): 217 | i = i + 1 218 | self.nr_weight += 1 219 | weight_label += [int(argv[i-1][2:])] 220 | weight += [float(argv[i])] 221 | else: 222 | raise ValueError("Wrong options") 223 | i += 1 224 | 225 | libsvm.svm_set_print_string_function(self.print_func) 226 | self.weight_label = (c_int*self.nr_weight)() 227 | self.weight = (c_double*self.nr_weight)() 228 | for i in range(self.nr_weight): 229 | self.weight[i] = weight[i] 230 | self.weight_label[i] = weight_label[i] 231 | 232 | class svm_model(Structure): 233 | _names = ['param', 'nr_class', 'l', 'SV', 'sv_coef', 'rho', 234 | 'probA', 'probB', 'sv_indices', 'label', 'nSV', 'free_sv'] 235 | _types = [svm_parameter, c_int, c_int, POINTER(POINTER(svm_node)), 236 | POINTER(POINTER(c_double)), POINTER(c_double), 237 | POINTER(c_double), POINTER(c_double), POINTER(c_int), 238 | POINTER(c_int), POINTER(c_int), c_int] 239 | _fields_ = genFields(_names, _types) 240 | 241 | def __init__(self): 242 | self.__createfrom__ = 'python' 243 | 244 | def __del__(self): 245 | # free memory created by C to avoid memory leak 246 | if hasattr(self, '__createfrom__') and self.__createfrom__ == 'C': 247 | libsvm.svm_free_and_destroy_model(pointer(self)) 248 | 249 | def get_svm_type(self): 250 | return libsvm.svm_get_svm_type(self) 251 | 252 | def get_nr_class(self): 253 | return libsvm.svm_get_nr_class(self) 254 | 255 | def get_svr_probability(self): 256 | return libsvm.svm_get_svr_probability(self) 257 | 258 | def get_labels(self): 259 | nr_class = self.get_nr_class() 260 | labels = (c_int * nr_class)() 261 | libsvm.svm_get_labels(self, labels) 262 | return labels[:nr_class] 263 | 264 | def get_sv_indices(self): 265 | total_sv = self.get_nr_sv() 266 | sv_indices = (c_int * total_sv)() 267 | libsvm.svm_get_sv_indices(self, sv_indices) 268 | return sv_indices[:total_sv] 269 | 270 | def get_nr_sv(self): 271 | return libsvm.svm_get_nr_sv(self) 272 | 273 | def is_probability_model(self): 274 | return (libsvm.svm_check_probability_model(self) == 1) 275 | 276 | def get_sv_coef(self): 277 | return [tuple(self.sv_coef[j][i] for j in xrange(self.nr_class - 1)) 278 | for i in xrange(self.l)] 279 | 280 | def get_SV(self): 281 | result = [] 282 | for sparse_sv in self.SV[:self.l]: 283 | row = dict() 284 | 285 | i = 0 286 | while True: 287 | row[sparse_sv[i].index] = sparse_sv[i].value 288 | if sparse_sv[i].index == -1: 289 | break 290 | i += 1 291 | 292 | result.append(row) 293 | return result 294 | 295 | def toPyModel(model_ptr): 296 | """ 297 | toPyModel(model_ptr) -> svm_model 298 | 299 | Convert a ctypes POINTER(svm_model) to a Python svm_model 300 | """ 301 | if bool(model_ptr) == False: 302 | raise ValueError("Null pointer") 303 | m = model_ptr.contents 304 | m.__createfrom__ = 'C' 305 | return m 306 | 307 | fillprototype(libsvm.svm_train, POINTER(svm_model), [POINTER(svm_problem), POINTER(svm_parameter)]) 308 | fillprototype(libsvm.svm_cross_validation, None, [POINTER(svm_problem), POINTER(svm_parameter), c_int, POINTER(c_double)]) 309 | 310 | fillprototype(libsvm.svm_save_model, c_int, [c_char_p, POINTER(svm_model)]) 311 | fillprototype(libsvm.svm_load_model, POINTER(svm_model), [c_char_p]) 312 | 313 | fillprototype(libsvm.svm_get_svm_type, c_int, [POINTER(svm_model)]) 314 | fillprototype(libsvm.svm_get_nr_class, c_int, [POINTER(svm_model)]) 315 | fillprototype(libsvm.svm_get_labels, None, [POINTER(svm_model), POINTER(c_int)]) 316 | fillprototype(libsvm.svm_get_sv_indices, None, [POINTER(svm_model), POINTER(c_int)]) 317 | fillprototype(libsvm.svm_get_nr_sv, c_int, [POINTER(svm_model)]) 318 | fillprototype(libsvm.svm_get_svr_probability, c_double, [POINTER(svm_model)]) 319 | 320 | fillprototype(libsvm.svm_predict_values, c_double, [POINTER(svm_model), POINTER(svm_node), POINTER(c_double)]) 321 | fillprototype(libsvm.svm_predict, c_double, [POINTER(svm_model), POINTER(svm_node)]) 322 | fillprototype(libsvm.svm_predict_probability, c_double, [POINTER(svm_model), POINTER(svm_node), POINTER(c_double)]) 323 | 324 | fillprototype(libsvm.svm_free_model_content, None, [POINTER(svm_model)]) 325 | fillprototype(libsvm.svm_free_and_destroy_model, None, [POINTER(POINTER(svm_model))]) 326 | fillprototype(libsvm.svm_destroy_param, None, [POINTER(svm_parameter)]) 327 | 328 | fillprototype(libsvm.svm_check_parameter, c_char_p, [POINTER(svm_problem), POINTER(svm_parameter)]) 329 | fillprototype(libsvm.svm_check_probability_model, c_int, [POINTER(svm_model)]) 330 | fillprototype(libsvm.svm_set_print_string_function, None, [PRINT_STRING_FUN]) 331 | -------------------------------------------------------------------------------- /lib/svmutil.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import os 4 | import sys 5 | 6 | from lib.svm import * 7 | from lib.svm import __all__ as svm_all 8 | 9 | __all__ = ['evaluations', 'svm_load_model', 'svm_predict', 'svm_read_problem', 10 | 'svm_save_model', 'svm_train'] + svm_all 11 | 12 | sys.path = [os.path.dirname(os.path.abspath(__file__))] + sys.path 13 | 14 | def svm_read_problem(data_file_name): 15 | """ 16 | svm_read_problem(data_file_name) -> [y, x] 17 | 18 | Read LIBSVM-format data from data_file_name and return labels y 19 | and data instances x. 20 | """ 21 | prob_y = [] 22 | prob_x = [] 23 | for line in open(data_file_name): 24 | line = line.split(None, 1) 25 | # In case an instance with all zero features 26 | if len(line) == 1: line += [''] 27 | label, features = line 28 | xi = {} 29 | for e in features.split(): 30 | ind, val = e.split(":") 31 | xi[int(ind)] = float(val) 32 | prob_y += [float(label)] 33 | prob_x += [xi] 34 | return (prob_y, prob_x) 35 | 36 | def svm_load_model(model_file_name): 37 | """ 38 | svm_load_model(model_file_name) -> model 39 | 40 | Load a LIBSVM model from model_file_name and return. 41 | """ 42 | model = libsvm.svm_load_model(model_file_name.encode()) 43 | if not model: 44 | print("can't open model file %s" % model_file_name) 45 | return None 46 | model = toPyModel(model) 47 | return model 48 | 49 | def svm_save_model(model_file_name, model): 50 | """ 51 | svm_save_model(model_file_name, model) -> None 52 | 53 | Save a LIBSVM model to the file model_file_name. 54 | """ 55 | libsvm.svm_save_model(model_file_name.encode(), model) 56 | 57 | def evaluations(ty, pv): 58 | """ 59 | evaluations(ty, pv) -> (ACC, MSE, SCC) 60 | 61 | Calculate accuracy, mean squared error and squared correlation coefficient 62 | using the true values (ty) and predicted values (pv). 63 | """ 64 | if len(ty) != len(pv): 65 | raise ValueError("len(ty) must equal to len(pv)") 66 | total_correct = total_error = 0 67 | sumv = sumy = sumvv = sumyy = sumvy = 0 68 | for v, y in zip(pv, ty): 69 | if y == v: 70 | total_correct += 1 71 | total_error += (v-y)*(v-y) 72 | sumv += v 73 | sumy += y 74 | sumvv += v*v 75 | sumyy += y*y 76 | sumvy += v*y 77 | l = len(ty) 78 | ACC = 100.0*total_correct/l 79 | MSE = total_error/l 80 | try: 81 | SCC = ((l*sumvy-sumv*sumy)*(l*sumvy-sumv*sumy))/((l*sumvv-sumv*sumv)*(l*sumyy-sumy*sumy)) 82 | except: 83 | SCC = float('nan') 84 | return (ACC, MSE, SCC) 85 | 86 | def svm_train(arg1, arg2=None, arg3=None): 87 | """ 88 | svm_train(y, x [, options]) -> model | ACC | MSE 89 | svm_train(prob [, options]) -> model | ACC | MSE 90 | svm_train(prob, param) -> model | ACC| MSE 91 | 92 | Train an SVM model from data (y, x) or an svm_problem prob using 93 | 'options' or an svm_parameter param. 94 | If '-v' is specified in 'options' (i.e., cross validation) 95 | either accuracy (ACC) or mean-squared error (MSE) is returned. 96 | options: 97 | -s svm_type : set type of SVM (default 0) 98 | 0 -- C-SVC (multi-class classification) 99 | 1 -- nu-SVC (multi-class classification) 100 | 2 -- one-class SVM 101 | 3 -- epsilon-SVR (regression) 102 | 4 -- nu-SVR (regression) 103 | -t kernel_type : set type of kernel function (default 2) 104 | 0 -- linear: u'*v 105 | 1 -- polynomial: (gamma*u'*v + coef0)^degree 106 | 2 -- radial basis function: exp(-gamma*|u-v|^2) 107 | 3 -- sigmoid: tanh(gamma*u'*v + coef0) 108 | 4 -- precomputed kernel (kernel values in training_set_file) 109 | -d degree : set degree in kernel function (default 3) 110 | -g gamma : set gamma in kernel function (default 1/num_features) 111 | -r coef0 : set coef0 in kernel function (default 0) 112 | -c cost : set the parameter C of C-SVC, epsilon-SVR, and nu-SVR (default 1) 113 | -n nu : set the parameter nu of nu-SVC, one-class SVM, and nu-SVR (default 0.5) 114 | -p epsilon : set the epsilon in loss function of epsilon-SVR (default 0.1) 115 | -m cachesize : set cache memory size in MB (default 100) 116 | -e epsilon : set tolerance of termination criterion (default 0.001) 117 | -h shrinking : whether to use the shrinking heuristics, 0 or 1 (default 1) 118 | -b probability_estimates : whether to train a SVC or SVR model for probability estimates, 0 or 1 (default 0) 119 | -wi weight : set the parameter C of class i to weight*C, for C-SVC (default 1) 120 | -v n: n-fold cross validation mode 121 | -q : quiet mode (no outputs) 122 | """ 123 | prob, param = None, None 124 | if isinstance(arg1, (list, tuple)): 125 | assert isinstance(arg2, (list, tuple)) 126 | y, x, options = arg1, arg2, arg3 127 | param = svm_parameter(options) 128 | prob = svm_problem(y, x, isKernel=(param.kernel_type == PRECOMPUTED)) 129 | elif isinstance(arg1, svm_problem): 130 | prob = arg1 131 | if isinstance(arg2, svm_parameter): 132 | param = arg2 133 | else: 134 | param = svm_parameter(arg2) 135 | if prob == None or param == None: 136 | raise TypeError("Wrong types for the arguments") 137 | 138 | if param.kernel_type == PRECOMPUTED: 139 | for xi in prob.x_space: 140 | idx, val = xi[0].index, xi[0].value 141 | if xi[0].index != 0: 142 | raise ValueError('Wrong input format: first column must be 0:sample_serial_number') 143 | if val <= 0 or val > prob.n: 144 | raise ValueError('Wrong input format: sample_serial_number out of range') 145 | 146 | if param.gamma == 0 and prob.n > 0: 147 | param.gamma = 1.0 / prob.n 148 | libsvm.svm_set_print_string_function(param.print_func) 149 | err_msg = libsvm.svm_check_parameter(prob, param) 150 | if err_msg: 151 | raise ValueError('Error: %s' % err_msg) 152 | 153 | if param.cross_validation: 154 | l, nr_fold = prob.l, param.nr_fold 155 | target = (c_double * l)() 156 | libsvm.svm_cross_validation(prob, param, nr_fold, target) 157 | ACC, MSE, SCC = evaluations(prob.y[:l], target[:l]) 158 | if param.svm_type in [EPSILON_SVR, NU_SVR]: 159 | print("Cross Validation Mean squared error = %g" % MSE) 160 | print("Cross Validation Squared correlation coefficient = %g" % SCC) 161 | return MSE 162 | else: 163 | print("Cross Validation Accuracy = %g%%" % ACC) 164 | return ACC 165 | else: 166 | m = libsvm.svm_train(prob, param) 167 | m = toPyModel(m) 168 | 169 | # If prob is destroyed, data including SVs pointed by m can remain. 170 | m.x_space = prob.x_space 171 | return m 172 | 173 | def svm_predict(y, x, m, options=""): 174 | """ 175 | svm_predict(y, x, m [, options]) -> (p_labels, p_acc, p_vals) 176 | 177 | Predict data (y, x) with the SVM model m. 178 | options: 179 | -b probability_estimates: whether to predict probability estimates, 180 | 0 or 1 (default 0); for one-class SVM only 0 is supported. 181 | -q : quiet mode (no outputs). 182 | 183 | The return tuple contains 184 | p_labels: a list of predicted labels 185 | p_acc: a tuple including accuracy (for classification), mean-squared 186 | error, and squared correlation coefficient (for regression). 187 | p_vals: a list of decision values or probability estimates (if '-b 1' 188 | is specified). If k is the number of classes, for decision values, 189 | each element includes results of predicting k(k-1)/2 binary-class 190 | SVMs. For probabilities, each element contains k values indicating 191 | the probability that the testing instance is in each class. 192 | Note that the order of classes here is the same as 'model.label' 193 | field in the model structure. 194 | """ 195 | 196 | def info(s): 197 | print(s) 198 | 199 | predict_probability = 0 200 | argv = options.split() 201 | i = 0 202 | while i < len(argv): 203 | if argv[i] == '-b': 204 | i += 1 205 | predict_probability = int(argv[i]) 206 | elif argv[i] == '-q': 207 | info = print_null 208 | else: 209 | raise ValueError("Wrong options") 210 | i+=1 211 | 212 | svm_type = m.get_svm_type() 213 | is_prob_model = m.is_probability_model() 214 | nr_class = m.get_nr_class() 215 | pred_labels = [] 216 | pred_values = [] 217 | 218 | if predict_probability: 219 | if not is_prob_model: 220 | raise ValueError("Model does not support probabiliy estimates") 221 | 222 | if svm_type in [NU_SVR, EPSILON_SVR]: 223 | info("Prob. model for test data: target value = predicted value + z,\n" 224 | "z: Laplace distribution e^(-|z|/sigma)/(2sigma),sigma=%g" % m.get_svr_probability()); 225 | nr_class = 0 226 | 227 | prob_estimates = (c_double * nr_class)() 228 | for xi in x: 229 | xi, idx = gen_svm_nodearray(xi, isKernel=(m.param.kernel_type == PRECOMPUTED)) 230 | label = libsvm.svm_predict_probability(m, xi, prob_estimates) 231 | values = prob_estimates[:nr_class] 232 | pred_labels += [label] 233 | pred_values += [values] 234 | else: 235 | if is_prob_model: 236 | info("Model supports probability estimates, but disabled in predicton.") 237 | if svm_type in (ONE_CLASS, EPSILON_SVR, NU_SVC): 238 | nr_classifier = 1 239 | else: 240 | nr_classifier = nr_class*(nr_class-1)//2 241 | dec_values = (c_double * nr_classifier)() 242 | for xi in x: 243 | xi, idx = gen_svm_nodearray(xi, isKernel=(m.param.kernel_type == PRECOMPUTED)) 244 | label = libsvm.svm_predict_values(m, xi, dec_values) 245 | if(nr_class == 1): 246 | values = [1] 247 | else: 248 | values = dec_values[:nr_classifier] 249 | pred_labels += [label] 250 | pred_values += [values] 251 | 252 | ACC, MSE, SCC = evaluations(y, pred_labels) 253 | l = len(y) 254 | if svm_type in [EPSILON_SVR, NU_SVR]: 255 | info("Mean squared error = %g (regression)" % MSE) 256 | info("Squared correlation coefficient = %g (regression)" % SCC) 257 | else: 258 | info("Accuracy = %g%% (%d/%d) (classification)" % (ACC, int(l*ACC/100), l)) 259 | 260 | return pred_labels, (ACC, MSE, SCC), pred_values 261 | 262 | 263 | -------------------------------------------------------------------------------- /prapare_data.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | ###### 5 | # 6 | # Mail npuxpli@mail.nwpu.edu.cn 7 | # Author LiXiping 8 | # Date 2019/09/20 16:19:34 9 | # 10 | ###### 11 | 12 | import os 13 | 14 | import argparse 15 | from feature2 import * 16 | from tqdm import tqdm 17 | import time 18 | def maxmin_normalization(feature): 19 | return [(float(i) - float(min(feature)))/float(float(max(feature)) - float(min(feature))) for i in feature] 20 | 21 | def standard_normalization(feature): 22 | mean = sum([float(x) for x in feature]) / float(len(feature)) 23 | variance = sum([pow(float(x) - mean , 2) for x in feature]) / float(len(feature) -1) 24 | stdev = math.sqrt(variance) 25 | 26 | 27 | return [((float(i) - mean) / stdev) for i in feature] 28 | 29 | def log_normalization(feature): 30 | maxa = float(max(feature)) 31 | return [(np.log(float(i)) / np.log(maxa)) for i in feature] 32 | 33 | 34 | def get_feature(img_path): 35 | hu = get_hu(img_path) 36 | svd = get_svd(img_path) 37 | mr = get_mr(img_path) 38 | pzor = get_pzor(img_path) 39 | #sift = get_sift(img_path) 40 | minrectangle = get_minrectangle(img_path) 41 | #harris = get_harris(img_path) 42 | fourier = get_fourier(img_path) 43 | 44 | feature = np.concatenate(( mr, pzor, minrectangle, hu, svd,fourier)) 45 | 46 | #feature1 = maxmin_normalization(feature) 47 | #feature2 = standard_normalization(feature) 48 | #feature3 = log_normalization(feature) 49 | #feature = np.concatenate(( mr, hu)) 50 | #return feature 51 | return feature 52 | 53 | def convert_value_to_str(label, feature): 54 | fmt = '' 55 | for item in feature: 56 | fmt = fmt + '{},'.format(item) 57 | line = fmt + '{}'.format(label) 58 | return line 59 | 60 | def imgs2feature(label, data_file, img_folder): 61 | for item in tqdm(os.listdir(img_folder)): 62 | img_path = os.path.join(img_folder , item) 63 | feature = get_feature(img_path) 64 | line = convert_value_to_str(label,feature) 65 | data_file.write(line + "\n") 66 | 67 | 68 | def get_txt(in_dir,out_file): 69 | data_file = open(out_file, 'w') 70 | for i,img_dir in tqdm(enumerate(sorted(os.listdir(in_dir)))): 71 | img_folder = os.path.join(in_dir,img_dir) 72 | imgs2feature(i+1 , data_file , img_folder) 73 | data_file.close() 74 | 75 | def svm_convert_value_to_str(label, feature): 76 | line = '{} '.format(label) 77 | for i, item in enumerate(feature): 78 | fmt = '{}:{} '.format(i + 1, item) 79 | line = line + fmt 80 | return line 81 | 82 | def svm_imgs2feature_file(label, svm_feature_file, img_folder): 83 | for item in os.listdir(img_folder): 84 | img_path = os.path.join(img_folder, item) 85 | feature = get_feature(img_path) 86 | line = wvm_convert_value_to_str(label, feature) 87 | svm_feature_file.write(line + "\n") 88 | 89 | def get_svm_txt(in_dir, out_file): 90 | svm_feature_file = open(out_file, 'w') 91 | for i, img_dir in enumerate(sorted(os.listdir(in_dir))): 92 | img_folder = os.path.join(in_dir,img_dir) 93 | svm_imgs2feature_file(i + 1, svm_feature_file, img_folder) 94 | svm_feature_file.close() 95 | 96 | if __name__ == '__main__': 97 | ''' 98 | process on RF_Adaboost 99 | ''' 100 | parser = argparse.ArgumentParser() 101 | parser.add_argument("--train_dir") 102 | parser.add_argument("--test_dir") 103 | parser.add_argument("--data_train") 104 | parser.add_argument("--data_test") 105 | args = parser.parse_args() 106 | t1 = time.time() 107 | get_txt(args.train_dir,args.data_train) 108 | get_txt(args.test_dir,args.data_test) 109 | print("t:",time.time()-t1) 110 | ''' 111 | Process on svm 112 | ''' 113 | get_svm_txt(args.train_dir, args.data_train) 114 | get_svm_txt(args.test_dir, args.data_test) 115 | 116 | -------------------------------------------------------------------------------- /prepare_data.sh: -------------------------------------------------------------------------------- 1 | python prepare_data.py \ 2 | --train_dir=./4/train \ 3 | --test_dir=./4/test \ 4 | --data_train=./4_train.txt \ 5 | --data_test=./4_test.txt --------------------------------------------------------------------------------