任务:将人脸图像分类为女性或男性。可以使用带有标签的训练图像,从网络摄像头获取测试图像。
使用: Python 2.7、OpenCV 2.4.4
我正在使用 ORB 从灰度图像中提取特征,我希望将其用于训练 K-Nearest Neighbor 分类器。每个训练图像都是不同的人,因此每个图像的关键点和描述符的数量明显不同。我的问题是我无法理解 KNN 和 ORB 的 OpenCV 文档。我见过其他关于 ORB、KNN 和 FLANN 的 SO 问题,但它们并没有太大帮助。
ORB 给出的描述符的本质是什么?它与通过 Brief、SURF、SIFT 等获得的描述符有何不同?
似乎 KNN 中每个训练样本的特征描述符应该具有相同的大小。如何确保每个图像的描述符大小相同?更一般地说,应该以什么格式将特征呈现给 KNN 以使用给定的数据和标签进行训练?数据应该是整数还是浮点数?可以是炭吗?
训练数据可以在这里找到。
我也在使用haarcascade_frontalface_alt.xml
来自 opencv 的示例
现在,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()
wheredescriptors
未检测为 numpy 数组的行处遇到错误。
另外,这种方法完全错误吗?我应该使用其他方式进行性别分类吗?我对 opencv facerec 演示中的 fisherface 和 eigenface 示例不满意,所以请不要将我引向那些。
非常感谢任何其他帮助。谢谢。
- - 编辑 - -
我已经尝试了一些事情并想出了一个答案。
我仍然希望 SO 社区中的某个人可以通过提出一个想法来帮助我,这样我就不必将事情硬编码到我的解决方案中。我还怀疑 knn.match_nearest() 没有做我需要做的事情。
正如预期的那样,识别器根本不准确,并且由于旋转、光照等原因很容易出现错误分类。任何关于改进这种方法的建议都将不胜感激。
我用于训练的数据库是:Karolinska Directed Emotional Faces