任务: 将人脸图像分类为男性或女性。有带标签的训练图像,从网络摄像头获取测试图像。
使用: Python 2.7, OpenCV 2.4.4
我正在使用ORB从灰度图像提取特征,希望用于训练K-最近邻分类器。每个训练图像都是不同的人,因此每个图像的关键点和描述符数量显然不同。我的问题是,我无法理解OpenCV文档中关于KNN和ORB的内容。我看过其他关于ORB、KNN和FLANN的SO问题,但它们没有什么帮助。
ORB给出的描述符的本质是什么?它与由BRIEF、SURF、SIFT等获得的描述符有何不同?
对于KNN,特征描述符似乎应该对每个训练样本具有相同的大小。如何确保每个图像的描述符大小相同?更一般地说,特征应该以什么格式呈现给具有给定数据和标签的KNN进行训练?数据应该是整型还是浮点型?可以是char吗?
训练数据可以在此处找到。
我还使用了来自OpenCV样本的haarcascade_frontalface_alt.xml
现在,KNN模型只给出10张训练图像以查看我的程序是否能通过没有错误的测试,但它没有通过。
这是我的代码:
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