└── hogsvm.py /hogsvm.py: -------------------------------------------------------------------------------- 1 | import os 2 | import cv2 3 | import math 4 | import time 5 | import numpy as np 6 | import tqdm 7 | from skimage.feature import hog 8 | from sklearn.svm import LinearSVC 9 | 10 | 11 | class Classifier(object): 12 | def __init__(self, filePath): 13 | self.filePath = filePath 14 | 15 | def unpickle(self, file): 16 | import pickle 17 | with open(file, 'rb') as fo: 18 | dict = pickle.load(fo, encoding='bytes') 19 | return dict 20 | 21 | def get_data(self): 22 | TrainData = [] 23 | TestData = [] 24 | for childDir in os.listdir(self.filePath): 25 | if 'data_batch' in childDir: 26 | f = os.path.join(self.filePath, childDir) 27 | data = self.unpickle(f) 28 | # train = np.reshape(data[str.encode('data')], (10000, 3, 32 * 32)) 29 | # If your python version do not support to use this way to transport str to bytes. 30 | # Think another way and you can. 31 | train = np.reshape(data[b'data'], (10000, 3, 32 * 32)) 32 | labels = np.reshape(data[b'labels'], (10000, 1)) 33 | fileNames = np.reshape(data[b'filenames'], (10000, 1)) 34 | datalebels = zip(train, labels, fileNames) 35 | TrainData.extend(datalebels) 36 | if childDir == "test_batch": 37 | f = os.path.join(self.filePath, childDir) 38 | data = self.unpickle(f) 39 | test = np.reshape(data[b'data'], (10000, 3, 32 * 32)) 40 | labels = np.reshape(data[b'labels'], (10000, 1)) 41 | fileNames = np.reshape(data[b'filenames'], (10000, 1)) 42 | TestData.extend(zip(test, labels, fileNames)) 43 | print("data read finished!") 44 | return TrainData, TestData 45 | 46 | def get_hog_feat(self, image, stride=8, orientations=8, pixels_per_cell=(8, 8), cells_per_block=(2, 2)): 47 | cx, cy = pixels_per_cell 48 | bx, by = cells_per_block 49 | sx, sy = image.shape 50 | n_cellsx = int(np.floor(sx // cx)) # number of cells in x 51 | n_cellsy = int(np.floor(sy // cy)) # number of cells in y 52 | n_blocksx = (n_cellsx - bx) + 1 53 | n_blocksy = (n_cellsy - by) + 1 54 | gx = np.zeros((sx, sy), dtype=np.float32) 55 | gy = np.zeros((sx, sy), dtype=np.float32) 56 | eps = 1e-5 57 | grad = np.zeros((sx, sy, 2), dtype=np.float32) 58 | for i in range(1, sx-1): 59 | for j in range(1, sy-1): 60 | gx[i, j] = image[i, j-1] - image[i, j+1] 61 | gy[i, j] = image[i+1, j] - image[i-1, j] 62 | grad[i, j, 0] = np.arctan(gy[i, j] / (gx[i, j] + eps)) * 180 / math.pi 63 | if gx[i, j] < 0: 64 | grad[i, j, 0] += 180 65 | grad[i, j, 0] = (grad[i, j, 0] + 360) % 360 66 | grad[i, j, 1] = np.sqrt(gy[i, j] ** 2 + gx[i, j] ** 2) 67 | normalised_blocks = np.zeros((n_blocksy, n_blocksx, by * bx * orientations)) 68 | for y in range(n_blocksy): 69 | for x in range(n_blocksx): 70 | block = grad[y*stride:y*stride+16, x*stride:x*stride+16] 71 | hist_block = np.zeros(32, dtype=np.float32) 72 | eps = 1e-5 73 | for k in range(by): 74 | for m in range(bx): 75 | cell = block[k*8:(k+1)*8, m*8:(m+1)*8] 76 | hist_cell = np.zeros(8, dtype=np.float32) 77 | for i in range(cy): 78 | for j in range(cx): 79 | n = int(cell[i, j, 0] / 45) 80 | hist_cell[n] += cell[i, j, 1] 81 | hist_block[(k * bx + m) * orientations:(k * bx + m + 1) * orientations] = hist_cell[:] 82 | normalised_blocks[y, x, :] = hist_block / np.sqrt(hist_block.sum() ** 2 + eps) 83 | return normalised_blocks.ravel() 84 | 85 | def get_feat(self, TrainData, TestData): 86 | train_feat = [] 87 | test_feat = [] 88 | for data in tqdm.tqdm(TestData): 89 | image = np.reshape(data[0].T, (32, 32, 3)) 90 | gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)/255. 91 | fd = self.get_hog_feat(gray) #你可以用我写的hog提取函数,也可以用下面skimage提供的,我的速度会慢一些 92 | # fd = hog(gray, 9, [8, 8], [2, 2]) 93 | fd = np.concatenate((fd, data[1])) 94 | test_feat.append(fd) 95 | test_feat = np.array(test_feat) 96 | np.save("test_feat.npy", test_feat) 97 | print("Test features are extracted and saved.") 98 | for data in tqdm.tqdm(TrainData): 99 | image = np.reshape(data[0].T, (32, 32, 3)) 100 | gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) / 255. 101 | fd = self.get_hog_feat(gray) 102 | # fd = hog(gray, 9, [8, 8], [2, 2]) 103 | fd = np.concatenate((fd, data[1])) 104 | train_feat.append(fd) 105 | train_feat = np.array(train_feat) 106 | np.save("train_feat.npy", train_feat) 107 | print("Train features are extracted and saved.") 108 | return train_feat, test_feat 109 | 110 | def classification(self, train_feat, test_feat): 111 | t0 = time.time() 112 | clf = LinearSVC() 113 | print("Training a Linear SVM Classifier.") 114 | clf.fit(train_feat[:, :-1], train_feat[:, -1]) 115 | predict_result = clf.predict(test_feat[:, :-1]) 116 | num = 0 117 | for i in range(len(predict_result)): 118 | if int(predict_result[i]) == int(test_feat[i, -1]): 119 | num += 1 120 | rate = float(num) / len(predict_result) 121 | t1 = time.time() 122 | print('The classification accuracy is %f' % rate) 123 | print('The cast of time is :%f' % (t1 - t0)) 124 | 125 | def run(self): 126 | if os.path.exists("train_feat.npy") and os.path.exists("test_feat.npy"): 127 | train_feat = np.load("train_feat.npy") 128 | test_feat = np.load("test_feat.npy") 129 | else: 130 | TrainData, TestData = self.get_data() 131 | train_feat, test_feat = self.get_feat(TrainData, TestData) 132 | self.classification(train_feat, test_feat) 133 | 134 | 135 | if __name__ == '__main__': 136 | filePath = r'F:\DataSets\cifar-10-batches-py' 137 | cf = Classifier(filePath) 138 | cf.run() --------------------------------------------------------------------------------