OpenCV自带的AdaBoot检测器对人脸检测有着很好的效果,对于双眼的检测结果也很不错,前提是人脸足够大,如大小为320x240的一帧图像,人脸达到150x150大小。 本文简单的包装了一下这个检测器。 #if !defined(AFX_HARR_DETECTOR_H_INCLUDED) #define AFX_HARR_DETECTOR_H_INCLUDED #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #include "cv.h" #include "highgui.h" #include <stdio.h> #include <stdlib.h> #include <string.h> #include <assert.h> #include <math.h> #include <float.h> #include <limits.h> #include <time.h> #include <ctype.h> typedef struct { int m_ScaleImg; double m_ScaleFactor; int m_MinNeighbors; bool m_FlagsDoCanny; CvSize m_MinSize; } HarrParam; class CHarrDetector { public: void Process(IplImage *image, const CvRect *pRoi) { assert(image != NULL); assert(image->nChannels == 1); IplImage* gray = image; IplImage* small_img; int i, isFaceFound = 0; CvRect roi; m_bFound = false; if (m_SmallImage == NULL) { m_SmallImage = cvCreateImage( cvSize( cvRound (image->width/m_ScaleImg), cvRound (image->height/m_ScaleImg)), 8, 1 ); } small_img = m_SmallImage; cvResize( gray, small_img, CV_INTER_LINEAR ); cvEqualizeHist( small_img, small_img ); cvClearMemStorage( m_storage ); if (pRoi != NULL) { roi = *pRoi; roi.x /= m_ScaleImg; roi.y /= m_ScaleImg; roi.width /= m_ScaleImg; roi.height/= m_ScaleImg; cvSetImageROI(small_img , roi); } if( m_cascade ) { CvSeq* faces = cvHaarDetectObjects( small_img, m_cascade, m_storage, m_ScaleFactor, m_MinNeighbors, m_FlagsDoCanny, m_MinSize ); m_bFound = false; m_Blob.height = 0; m_Blob.width = 0; for( i = 0; i < (faces ? faces->total : 0); i++ ) { CvRect* r = (CvRect*)cvGetSeqElem( faces, i ); CvRect rect; rect.x = r->x * m_ScaleImg; rect.y = r->y * m_ScaleImg; rect.height = r->height * m_ScaleImg; rect.width = r->width * m_ScaleImg; if (pRoi != NULL) { rect.x += pRoi->x; rect.y += pRoi->y; } m_bFound = true; if (m_Blob.height < rect.height && m_Blob.width < rect.width) { m_Blob = rect; } } } if (pRoi != NULL) { cvResetImageROI(small_img); } }; void SetParam(HarrParam *pParam) { assert(pParam != NULL); m_ScaleImg = pParam->m_ScaleImg; m_ScaleFactor = pParam->m_ScaleFactor; m_MinNeighbors = pParam->m_MinNeighbors-1; m_FlagsDoCanny = pParam->m_FlagsDoCanny; m_MinSize = pParam->m_MinSize; }; void Init(const char *cascade_name) { assert(cascade_name != NULL); m_cascade = NULL; m_storage = NULL; m_SmallImage = NULL; m_ScaleImg = 4; m_ScaleFactor = 1.1f; m_MinNeighbors = -1; m_FlagsDoCanny = 0; m_MinSize = cvSize(30, 30); if (m_cascade == NULL) { m_cascade = (CvHaarClassifierCascade*)cvLoad( cascade_name, 0, 0, 0 ); } assert(m_cascade != NULL); m_storage = cvCreateMemStorage(0); assert(m_storage != NULL); }; CHarrDetector() { m_bFound = false; }; ~CHarrDetector() { if (m_SmallImage != NULL) { cvReleaseImage(&m_SmallImage); } if (m_storage != NULL) { cvReleaseMemStorage( &m_storage ); } }; public: bool m_bFound; CvRect m_Blob; private: int m_ScaleImg; double m_ScaleFactor; int m_MinNeighbors; int m_FlagsDoCanny; CvSize m_MinSize; private: CvHaarClassifierCascade* m_cascade; CvMemStorage *m_storage; IplImage *m_SmallImage; }; class CFaceFounder : public CHarrDetector { public: CFaceFounder() { const char *cascade_name = "C://Program Files//OpenCV//data//haarcascades//haarcascade_frontalface_alt2.xml"; Init(cascade_name); HarrParam param; param.m_FlagsDoCanny = 0; param.m_MinNeighbors = -1; param.m_MinSize = cvSize(30, 30); param.m_ScaleFactor = 1.8f; param.m_ScaleImg = 4; SetParam(¶m); }; }; class CEyesFounder : public CHarrDetector { public: CEyesFounder() { const char *cascade_name = "C://Program Files//OpenCV//data//haarcascades//Eyes45x11.xml"; Init(cascade_name); HarrParam param; param.m_FlagsDoCanny = 0; param.m_MinNeighbors = -1; param.m_MinSize = cvSize(45, 11); param.m_ScaleFactor = 1.1f; param.m_ScaleImg = 2; SetParam(¶m); }; }; class CMouthFounder : public CHarrDetector { public: CMouthFounder() { const char *cascade_name = "C://Program Files//OpenCV//data//haarcascades//Mouth25x15.xml"; Init(cascade_name); HarrParam param; param.m_FlagsDoCanny = 0; param.m_MinNeighbors = -1; param.m_MinSize = cvSize(25, 15); param.m_ScaleFactor = 1.1f; param.m_ScaleImg = 2; SetParam(¶m); }; }; class CNoseFounder : public CHarrDetector { public: CNoseFounder() { const char *cascade_name = "C://Program Files//OpenCV//data//haarcascades//Nose25x15.xml"; Init(cascade_name); HarrParam param; param.m_FlagsDoCanny = 0; param.m_MinNeighbors = -1; param.m_MinSize = cvSize(25, 15); param.m_ScaleFactor = 1.1f; param.m_ScaleImg = 2; SetParam(¶m); }; }; #endif // !defined(AFX_HARR_DETECTOR_H_INCLUDED)