码迷,mamicode.com
首页 > 编程语言 > 详细

OpenCV Using Python——调整基于HAAR特征的AdaBoost级联分类器的物体识别的参数

时间:2015-03-07 14:18:19      阅读:291      评论:0      收藏:0      [点我收藏+]

标签:opencv   python   haar cascade   参数调整   adaboost   

调整基于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. 代码实现

        有人声称用不到25行的代码实现人脸检测,笔者为说明问题,暂时不作代码长度的考虑。下面为笔者应用OpenCV库中检测人脸,左眼,右眼,鼻子,嘴巴等XML文件的实现代码。
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!'

4. 调整参数的步骤

(1)默认参数:设置默认参数观察是否检测到物体;
(2)检测物体的范围:修改minSize(检测的对象最小尺寸,单位:像素*像素)和maxSize(检测对象的最大尺寸),使对象落在检测器的大小范围内;
(3)投票数:设置minNeighbor为0,观察所有的投票结果,投票结果最集中的位置为最终的检测结果。增加投票数滤除误检测的对象,检测到对象的条件越苛刻;减少投票数增加检测到对象的几率,检测到对象的条件越宽松;
(4)尺度:被检测对象的尺度变化,尺度变化的图像的集合可以构成图像金字塔。scaleFactor的合理的范围在1.1~1.4之间,尺度越大,越容易漏掉检测的对象,但检测速度加快;尺度越小,检测越细致准确,但检测速度变慢。

5. 实验结果

        第一幅和第二幅人脸为标准的正脸,应该说检测的过程得还挺完美。
        第三幅人脸检测结果也算是尽力了。刚开始用第二幅图的参数时,检测人脸的分类器会在左边的蜗牛壳那边检测出第二个人脸。通过调整minSize和maxSize才将背景的伪正结果给去掉了。接着是左眼的检测,大爱丽丝的左眼比小爱丽丝的左眼范围大太多,所以需要将左眼的minSize和maxSize调小。调整右眼的参数时,右眼的检测结果重叠在左眼上,我认为是左眼的位姿比较暧昧,同时满足了左右眼的检测标准。检测鼻子时,一直检测不到结果,因为肉眼查看图像发现小爱丽丝的鼻子为细长状,头微微低下使鼻尖处的宽度不够大。检测嘴巴时,嘴巴的投票全部在左眼上,确实小爱丽丝的嘴由于脸部微侧显得特别小,并且相比之下,左眼的形状也更像嘴巴。

技术分享

结语

        Paul Viola大神的文章只给出了大致的框架。本来希望自己写一遍这个实现的过程,但我只写完了积分图像和AdaBoost分类器。最后怎么结合还要查找更多的材料,但有可能就到此为止了,毕竟这个库函数调一调速度可以很快的。

OpenCV Using Python——调整基于HAAR特征的AdaBoost级联分类器的物体识别的参数

标签:opencv   python   haar cascade   参数调整   adaboost   

原文地址:http://blog.csdn.net/shadow_guo/article/details/44114421

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!