调整基于HAAR特征的AdaBoost级联分类器的物体识别的参数
1. 基于HAAR特征的AdaBoost级联分类器的物体识别问题
Paul A. Viola和Michael J. Jones在2001年发表文章“使用简单特征的提高级联检测器的快速物体检测”。同时CSDN上很多博主在07年到13年也纷纷对该方法的原理,库函数内容,XML文件的训练以及OpenCV的实现做出很多工作。同时,调用OpenCV的库函数很方便,能够用很短的代码即可实现人脸的检测。但是,在实际使用中发现,很多训练好的XML文件不好用。
2. 调整参数的意义
既然训练好的XML文件不好用,是不是意味着要重新训练分类器?如果需要检测的物体在OpenCV中有,那么尽量用OpenCV中自带的分类器。因为自带的分类器包含了很多工作人员的心血,绝对不会那么轻易不好用的。所以根据需要根据实际情况查找问题。主要问题包括:图像分辨率,参数设置和物体摆放的位姿。
(1)图像分辨率
如果图像分辨率过低导致图像中的物体不清晰,甚至连人眼都看不清楚,当然检测不出来物体;如果图像分辨率过高,导致物体的大小超出分类器的尺寸,即分类器最多只能检测到物体的一部分,但检测不到整体,这样也不会检测出物体。
(2)参数设置
参数设置的内容会在调整参数的步骤中详细说明。
(3)物体摆放的位姿
举个极端的例子:分类器训练的样本都是物体的正面,而实际检测的为物体的反面,物体正面和反面又是截然不同的,所以也有可能检测不出物体。简单地说,训练的样本和测试的样本虽然是同一类物体,但在图像中表现得差异过大。有两种解决办法:数据库不完备,增加数据库样本重新训练;摆正样本。
3. 代码实现
import cv2
import numpy as np
from matplotlib import pyplot as plt
################################################################################
print 'Load Object Cascade Classifier'
faceCascade = cv2.CascadeClassifier('D:/OpenCV 2.4.9/opencv/sources/data/haarcascades/haarcascade_frontalface_default.xml')
lefteyeCascade = cv2.CascadeClassifier('D:/OpenCV 2.4.9/opencv/sources/data/haarcascades/haarcascade_mcs_lefteye.xml')
righteyeCascade = cv2.CascadeClassifier('D:/OpenCV 2.4.9/opencv/sources/data/haarcascades/haarcascade_mcs_righteye.xml')
noseCascade = cv2.CascadeClassifier('D:/OpenCV 2.4.9/opencv/sources/data/haarcascades/haarcascade_mcs_nose.xml')
mouthCascade = cv2.CascadeClassifier('D:/OpenCV 2.4.9/opencv/sources/data/haarcascades/haarcascade_mcs_mouth.xml')
################################################################################
print 'Load Image'
imgFile = 'images/face.jpg'
# load an original image
img = cv2.imread(imgFile)
# convert color space from bgr to gray
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
imgGray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
faces = faceCascade.detectMultiScale(imgGray, scaleFactor = 1.3, minNeighbors = 4, minSize = (60,60), maxSize = (300,300), flags = cv2.cv.CV_HAAR_SCALE_IMAGE)
for (x,y,w,h) in faces:
cv2.rectangle(img, (x,y), (x+w,y+h), (255,0,0), 2)
faceGray = imgGray[y:y+h, x:x+w]
faceColor = img[y:y+h, x:x+w]
'''
# for small Alice
lefteye = lefteyeCascade.detectMultiScale(faceGray, scaleFactor = 1.3, minNeighbors = 5, minSize = (20,20), maxSize = (80,80), flags = cv2.cv.CV_HAAR_SCALE_IMAGE)
righteye = righteyeCascade.detectMultiScale(faceGray, scaleFactor = 1.3, minNeighbors = 5, minSize = (20,20), maxSize = (80,80), flags = cv2.cv.CV_HAAR_SCALE_IMAGE)
# cannot search nose successfully!
nose = noseCascade.detectMultiScale(faceGray, scaleFactor = 1.1, minNeighbors = 0, minSize = (5,5), maxSize = (80,80), flags = cv2.cv.CV_HAAR_SCALE_IMAGE)
# mistaken eye for mouth!
mouth = mouthCascade.detectMultiScale(faceGray, scaleFactor = 1.05, minNeighbors = 10, minSize = (5,5), maxSize = (80,80), flags = cv2.cv.CV_HAAR_SCALE_IMAGE)
'''
'''
# for big Alice
lefteye = lefteyeCascade.detectMultiScale(faceGray, scaleFactor = 1.3, minNeighbors = 18, minSize = (40,40), maxSize = (80,80), flags = cv2.cv.CV_HAAR_SCALE_IMAGE)
righteye = righteyeCascade.detectMultiScale(faceGray, scaleFactor = 1.3, minNeighbors = 16, minSize = (40,40), maxSize = (80,80), flags = cv2.cv.CV_HAAR_SCALE_IMAGE)
nose = noseCascade.detectMultiScale(faceGray, scaleFactor = 1.3, minNeighbors = 10, minSize = (40,40), maxSize = (80,80), flags = cv2.cv.CV_HAAR_SCALE_IMAGE)
mouth = mouthCascade.detectMultiScale(faceGray, scaleFactor = 1.3, minNeighbors = 10, minSize = (40,40), maxSize = (80,80), flags = cv2.cv.CV_HAAR_SCALE_IMAGE)
'''
# for face
lefteye = lefteyeCascade.detectMultiScale(faceGray, scaleFactor = 1.3, minNeighbors = 18, minSize = (40,40), maxSize = (80,80), flags = cv2.cv.CV_HAAR_SCALE_IMAGE)
righteye = righteyeCascade.detectMultiScale(faceGray, scaleFactor = 1.3, minNeighbors = 16, minSize = (40,40), maxSize = (80,80), flags = cv2.cv.CV_HAAR_SCALE_IMAGE)
nose = noseCascade.detectMultiScale(faceGray, scaleFactor = 1.3, minNeighbors = 16, minSize = (40,40), maxSize = (80,80), flags = cv2.cv.CV_HAAR_SCALE_IMAGE)
mouth = mouthCascade.detectMultiScale(faceGray, scaleFactor = 1.3, minNeighbors = 10, minSize = (40,40), maxSize = (80,80), flags = cv2.cv.CV_HAAR_SCALE_IMAGE)
############################################################################
print 'Add Objects on Face'
for (ex,ey,ew,eh) in lefteye:
cv2.rectangle(faceColor, (ex,ey), (ex+ew,ey+eh), (0,255,0), 2)
for (ex,ey,ew,eh) in righteye:
cv2.rectangle(faceColor, (ex,ey), (ex+ew,ey+eh), (255,255,0), 2)
for (ex,ey,ew,eh) in nose:
cv2.rectangle(faceColor, (ex,ey), (ex+ew,ey+eh), (0,255,255), 2)
for (ex,ey,ew,eh) in mouth:
cv2.rectangle(faceColor, (ex,ey), (ex+ew,ey+eh), (0,100,100), 2)
################################################################################
print 'Display Face Image'
plt.subplot(1,1,1), plt.imshow(img), plt.title('Face Image'), plt.xticks([]), plt.yticks([])
plt.show()
################################################################################
print 'Goodbye!'