任務:將人臉圖像分類爲女性或男性。使用標籤培訓圖像可用,從網絡攝像頭獲取測試圖像。Python,OpenCV:使用ORB特徵和KNN對性別進行分類
使用:的Python 2.7,OpenCV的2.4.4
我使用ORB來提取灰度圖像的特點,我希望用訓練的K近鄰分類。每個訓練圖像都是不同的人,因此每個圖像的關鍵點和描述符的數量明顯不同。我的問題是,我無法理解KNN和ORB的OpenCV文檔。我還看過關於ORB,KNN和FLANN的其他SO問題,但他們沒有太多幫助。
ORB給出的描述符的性質究竟是什麼?它與通過BRIEF,SURF,SIFT等獲得的描述符有什麼不同?
似乎KNN中每個訓練樣本的特徵描述符應該具有相同的大小。我如何確保每個圖像的描述符大小相同?更一般地說,應該以什麼樣的格式向KNN呈現特定的數據和標籤進行培訓?數據應該是int還是float?它可以是字符?
培訓數據可以找到here。
我也使用來自OpenCV的樣品
眼下KNN模型,給出了訓練僅有10圖像0,看看我的程序通過,沒有這些,它沒有錯誤。
這裏是我的代碼:
import cv2
from numpy import float32 as np.float32
def chooseCascade():
# TODO: Option for diferent cascades
# HAAR Classifier for frontal face
_cascade = cv2.CascadeClassifier('haarcascade_frontalface_alt.xml')
return _cascade
def cropToObj(cascade,imageFile):
# Load as 1-channel grayscale image
image = cv2.imread(imageFile,0)
# Crop to the object of interest in the image
objRegion = cascade.detectMultiScale(image) # TODO: What if multiple ojbects in image?
x1 = objRegion[0,0]
y1 = objRegion[0,1]
x1PlusWidth = objRegion[0,0]+objRegion[0,2]
y1PlusHeight = objRegion[0,1]+objRegion[0,3]
_objImage = image[y1:y1PlusHeight,x1:x1PlusWidth]
return _objImage
def recognizer(fileNames):
# ORB contructor
orb = cv2.ORB(nfeatures=100)
keyPoints = []
descriptors = []
# A cascade for face detection
haarFaceCascade = chooseCascade()
# Start processing images
for imageFile in fileNames:
# Find faces using the HAAR cascade
faceImage = cropToObj(haarFaceCascade,imageFile)
# Extract keypoints and description
faceKeyPoints, faceDescriptors = orb.detectAndCompute(faceImage, mask = None)
#print faceDescriptors.shape
descRow = faceDescriptors.shape[0]
descCol = faceDescriptors.shape[1]
flatFaceDescriptors = faceDescriptors.reshape(descRow*descCol).astype(np.float32)
keyPoints.append(faceKeyPoints)
descriptors.append(flatFaceDescriptors)
print descriptors
# KNN model and training on descriptors
responses = []
for name in fileNames:
if name.startswith('BF'):
responses.append(0) # Female
else:
responses.append(1) # Male
knn = cv2.KNearest()
knnTrainSuccess = knn.train(descriptors,
responses,
isRegression = False) # isRegression = false, implies classification
# Obtain test face image from cam
capture = cv2.VideoCapture(0)
closeCamera = -1
while(closeCamera < 0):
_retval, _camImage = capture.retrieve()
# Find face in camera image
testFaceImage = haarFaceCascade.detectMultiScale(_camImage) # TODO: What if multiple faces?
# Keyponts and descriptors of test face image
testFaceKP, testFaceDesc = orb.detectAndCompute(testFaceImage, mask = None)
testDescRow = testFaceDesc.shape[0]
flatTestFaceDesc = testFaceDesc.reshape(1,testDescRow*testDescCol).astype(np.float32)
# Args in knn.find_nearest: testData, neighborhood
returnedValue, result, neighborResponse, distance = knn.find_nearest(flatTestFaceDesc,3)
print returnedValue, result, neighborResponse, distance
# Display results
# TODO: Overlay classification text
cv2.imshow("testImage", _camImage)
closeCamera = cv2.waitKey(1)
cv2.destroyAllWindows()
if __name__ == '__main__':
fileNames = ['BF09NES_gray.jpg',
'BF11NES_gray.jpg',
'BF13NES_gray.jpg',
'BF14NES_gray.jpg',
'BF18NES_gray.jpg',
'BM25NES_gray.jpg',
'BM26NES_gray.jpg',
'BM29NES_gray.jpg',
'BM31NES_gray.jpg',
'BM34NES_gray.jpg']
recognizer(fileNames)
目前我得到在該行的錯誤與knn.train()
其中descriptors
沒有被檢測爲一個numpy的陣列。
另外,這種方法是完全錯誤的嗎?我是否應該使用其他方式進行性別分類?我對opencv facerec演示中的fisherface和eigenface示例不滿意,所以請不要直接告訴我這些。
任何其他幫助,非常感謝。謝謝。
---編輯---
我已經嘗試了一些東西,想出了一個答案。
我仍然希望SO社區中的某個人能夠通過提出一個想法來幫助我,這樣我就不必將事情硬編碼到我的解決方案中。我也懷疑knn.match_nearest()沒有做我所需要的。
正如預期的那樣,識別器並不完全準確,並且由於旋轉,照明等原因,很容易導致錯誤分類。有關改進此方法的任何建議都將得到真正的讚賞。
我使用培訓的數據庫是:Karolinska Directed Emotional Faces
一個快速評論。剛剛發現了關於弓。似乎相關。 SO回答(http://stackoverflow.com/questions/15611872/bow-in-opencv-using-precomputed-features)。並且在這裏(https://groups.google.com/forum/#!topic/accord-net/u5viBhgv0Fw)它說,視覺詞彙袋只有一個目的和一個目的:將可變長度的特徵表示轉化爲固定長度的特徵,長度特徵表示。' –