任务:将人脸图像分为女性或男性。带标签的培训图像可用,从网络摄像头获取测试图像。
使用:Python2.7,OpenCV 2.4.4
我使用ORB从灰度图像中提取特征,我希望用它来训练K近邻分类器。每个训练图像都是一个不同的人,因此每个图像的关键点和描述符的数量明显不同。我的问题是我无法理解KNN和ORB的OpenCV文档。我见过其他一些关于ORB,KNN和FLANN的问题,但是他们没有多大帮助。
ORB给出的描述符的性质究竟是什么?它与由简介、冲浪、筛选等获得的描述符有何不同?
对于KNN中的每个训练样本,特征描述子的大小应该是相同的。如何确保每个图像的描述符大小相同?更普遍地说,应该以何种格式向KNN展示功能,以便使用给定的数据和标签进行培训?数据是整数还是浮动?会是焦炭吗?
训练数据可以找到这里。
我还使用了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演示中的渔夫面和特征面示例不满意,所以请不要指导我这些。
任何其他帮助都是非常感谢的。谢谢。
--编辑--
我试了几件事,想出了一个答案。
我仍然希望在这样的社区中有人能帮助我,提出一个想法,这样我就不必把事情硬编码到我的解决方案中。我还怀疑knn.match_nearest()没有做我需要它做的事情。
正如预期的那样,识别器一点也不准确,而且由于旋转、照明等原因,很容易给出错误的分类。任何关于改进这种方法的建议都会受到欢迎。
我用于培训的数据库是:卡罗琳斯卡的情绪化面孔
发布于 2013-10-08 02:25:09
我对所述方法的有效性/可行性有一些怀疑。这是另一种可能需要考虑的方法。gen
文件夹的内容为@ http://www1.datafilehost.com/d/0f263abc。正如您将注意到的,当数据大小变得更大时(~10k训练样本),模型的大小可能变得不可接受(~100-200 as )。然后,你将需要调查pca/lda等。
import cv2
import numpy as np
import os
def feaCnt():
mat = np.zeros((400,400,3),dtype=np.uint8)
ret = extr(mat)
return len(ret)
def extr(img):
return sobel(img)
def sobel(img):
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
klr = [[-1,0,1],[-2,0,2],[-1,0,1]]
kbt = [[1,2,1],[0,0,0],[-1,-2,-1]]
ktb = [[-1,-2,-1],[0,0,0],[1,2,1]]
krl = [[1,0,-1],[2,0,-2],[1,0,-1]]
kd1 = [[0,1,2],[-1,0,1],[-2,-1,0]]
kd2 = [[-2,-1,0],[-1,0,1],[0,1,2]]
kd3 = [[0,-1,-2],[1,0,-1],[2,1,0]]
kd4 = [[2,1,0],[1,0,-1],[0,-1,-2]]
karr = np.asanyarray([
klr,
kbt,
ktb,
krl,
kd1,
kd2,
kd3,
kd4
])
gray=cv2.resize(gray,(40,40))
res = np.float32([cv2.resize(cv2.filter2D(gray, -1,k),(15,15)) for k in karr])
return res.flatten()
root = 'C:/data/gen'
model='c:/data/models/svm/gen.xml'
imgs = []
idx =0
for path, subdirs, files in os.walk(root):
for name in files:
p =path[len(root):].split('\\')
p.remove('')
lbl = p[0]
fpath = os.path.join(path, name)
imgs.append((fpath,int(lbl)))
idx+=1
samples = np.zeros((len(imgs),feaCnt()),dtype = np.float32)
labels = np.zeros(len(imgs),dtype = np.float32)
i=0.
for f,l in imgs:
print i
img = cv2.imread(f)
samples[i]=extr(img)
labels[i]=l
i+=1
svm = cv2.SVM()
svmparams = dict( kernel_type = cv2.SVM_POLY,
svm_type = cv2.SVM_C_SVC,
degree=3.43,
gamma=1.5e-4,
coef0=1e-1,
)
print 'svm train'
svm.train(samples,labels,params=svmparams)
svm.save(model)
print 'done'
result = np.float32( [(svm.predict(s)) for s in samples])
correct=0.
total=0.
for i,j in zip(result,labels):
total+=1
if i==j:
correct+=1
print '%f'%(correct/total)
https://stackoverflow.com/questions/19224300
复制相似问题