大家都說gabor做人臉識別是傳統方法中效果最好的,這幾天就折騰實現了下,網上的python實現實在太少,github上的某個版本還誤導了我好幾天,后來采用將C++代碼封裝成dll供python調用的方式,成功解決。
圖像經多尺度多方向的gabor變換后,gabor系數的數目成倍上升,所以對gabor系數必須進行降維才能送至后續的SVM分類器。測試圖像使用att_faces數據集(40種類型,每種隨機選5張訓練,5張識別),降維方式我測試了DCT、PCA兩種變換方式,說實話,dct不怎么靠譜,居然准確率不到70%,所以我有點懷疑網頁http://blog.csdn.net/bxyill/article/details/7937850的實現效果,PCA方式也一般,平均識別率95%左右吧;同時測試了直接下采樣、均值濾波后采樣、最大值濾波后采樣三種方式,它們的平均識別率分別為98.6%、98.5%、99%左右。可見,最大值濾波后再下采樣的方式是最好的,其他的非線性降維方法沒試過,我也不太懂
下面是python實現代碼,不到50行哦
#coding:utf-8
import numpy as np
import cv2, os, math, os.path, glob, random
from ctypes import *
from sklearn.svm import LinearSVC
dll = np.ctypeslib.load_library('zmGabor', '.') #調用C++動態鏈接庫
print dll.gabor
dll.gabor.argtypes = [POINTER(c_uint8), POINTER(c_uint8), c_int32, c_int32, c_double, c_int32, c_double, c_double]
def loadImageSet(folder, sampleCount=5):
trainData = []; testData = []; yTrain=[]; yTest = [];
for k in range(1,41):
folder2 = os.path.join(folder, 's%d' %k)
data = [cv2.imread(d.encode('gbk'),0) for d in glob.glob(os.path.join(folder2, '*.pgm'))]
sample = random.sample(range(10), sampleCount)
trainData.extend([data[i] for i in range(10) if i in sample])
testData.extend([data[i] for i in range(10) if i not in sample])
yTest.extend([k]* (10-sampleCount))
yTrain.extend([k]* sampleCount)
return trainData, testData, np.array(yTrain), np.array(yTest)
def getGaborFeature(m):
res = []
for i in range(6):
for j in range(4):
g = np.zeros(m.shape, dtype = np.uint8)
dll.gabor(m.ctypes.data_as(POINTER(c_uint8)), g.ctypes.data_as(POINTER(c_uint8)),
m.shape[0], m.shape[1],
i*np.pi/6, j, 2*np.pi, np.sqrt(2))
#res.append(cv2.dct(g[:10,:10].astype(np.float))) #先DCT變換再取低頻系數
#res.append(g[::10,::10]) #直接子采樣
#res.append(cv2.blur(g, (10,10))[5::10, 5::10]) #先均值濾波再子采樣
res.append(255-cv2.erode(255-g, np.ones((10,10)))[5::10, 5::10]) #先最大值濾波再子采樣
return np.array(res)
def main(folder=u'D:/gabor/att_faces'):
trainImg, testImg, yTrain, yTest = loadImageSet(folder)
xTrain = np.array([getGaborFeature(d).ravel() for d in trainImg])
xTest = np.array([getGaborFeature(d).ravel() for d in testImg])
lsvc = LinearSVC() #支持向量機方法
lsvc.fit(xTrain, yTrain)
lsvc_y_predict = lsvc.predict(xTest)
print u'支持向量機識別率: %.2f%%' % (lsvc_y_predict == np.array(yTest)).mean()
if __name__ == '__main__':
main()
