本博客只用於學習,如果有錯誤的地方,懇請指正,如需轉載請注明出處。
看機器學習也是有一段時間了,這兩天終於勇敢地踏出了第一步,實現了HOG+SVM對圖片分類,具體代碼可以在github上下載,https://github.com/subicWang/HOG-SVM-classifer。大家都說HOG+SVM是在行人檢測中很合拍的一對。至於為啥,我也講不清楚。我猜想這么合拍的一對應用在圖片分類上效果應該也不錯吧,事實證明確實還行,速度挺快,分類正確率還行。我用的數據集是http://www.cs.toronto.edu/~kriz/cifar.html。圖片特征HOG的提取過程,本文不做講解,很多博客也肯定比我講得清楚。那我就直接粘出我的代碼吧,方便需要的人參考。
def getHOGfeat( image,stride = 8, orientations=8, pixels_per_cell=(8, 8),cells_per_block=(2, 2)): cx, cy = pixels_per_cell bx, by = cells_per_block sx, sy = image.shape n_cellsx = int(np.floor(sx // cx)) # number of cells in x n_cellsy = int(np.floor(sy // cy)) # number of cells in y n_blocksx = (n_cellsx - bx) + 1 n_blocksy = (n_cellsy - by) + 1 gx = zeros((sx, sy), dtype=np.double) gy = zeros((sx, sy), dtype=np.double) eps = 1e-5 grad = zeros((sx, sy, 2), dtype=np.double) for i in xrange(1, sx-1): for j in xrange(1, sy-1): gx[i, j] = image[i, j-1] - image[i, j+1] gy[i, j] = image[i+1, j] - image[i-1, j] grad[i, j, 0] = arctan(gy[i, j] / (gx[i, j] + eps)) * 180 / math.pi if gx[i, j] < 0: grad[i, j, 0] += 180 grad[i, j, 0] = (grad[i, j, 0] + 360) % 360 grad[i, j, 1] = sqrt(gy[i, j] ** 2 + gx[i, j] ** 2) normalised_blocks = np.zeros((n_blocksy, n_blocksx, by * bx * orientations)) for y in xrange(n_blocksy): for x in xrange(n_blocksx): block = grad[y*stride:y*stride+16, x*stride:x*stride+16] hist_block = zeros(32, dtype=double) eps = 1e-5 for k in xrange(by): for m in xrange(bx): cell = block[k*8:(k+1)*8, m*8:(m+1)*8] hist_cell = zeros(8, dtype=double) for i in xrange(cy): for j in xrange(cx): n = int(cell[i, j, 0] / 45) hist_cell[n] += cell[i, j, 1] hist_block[(k * bx + m) * orientations:(k * bx + m + 1) * orientations] = hist_cell[:] normalised_blocks[y, x, :] = hist_block / np.sqrt(hist_block.sum() ** 2 + eps) return normalised_blocks.ravel()
熟悉HOG特征提取過程的應該都能看懂,我就不注釋了。簡單的這樣實現當然不能滿足我的要求,我一直不能理解為啥這些特征提取算法中像素點的梯度只由水平和垂直的像素決定,周圍的其他點就對該點沒有作用嗎?對此我做了一些實驗,在下一篇分享。
2020.4.5 更新:上面是三年前的代碼了,當時寫的有點不好導致好多人運行報錯。今天重新改了一下,現在代碼簡介了很多,應該沒啥問題。https://github.com/SubicLovePython/hog-svm