OpenCV
CvSeq* cvHaarDetectObjects( const CvArr* image, CvHaarClassifierCascade* cascade,
CvMemStorage* storage, double scale_factor=1.1,
int min_neighbors=3, int flags=0,
CvSize min_size=cvSize(0,0) );
image
被檢圖像
cascade
harr 分類器級聯的內部標識形式
storage
用來存儲檢測到的一序列候選目標矩形框的內存區域。
scale_factor
在前後兩次相繼的掃描中,搜索窗口的比例係數。例如1.1指將搜索窗口依次擴大10%。
min_neighbors
構成檢測目標的相鄰矩形的最小個數(缺省-1)。如果組成檢測目標的小矩形的個數和小於min_neighbors
-1 都會被排除。如果min_neighbors
爲 0, 則函數不做任何操作就返回所有的被檢候選矩形框,這種設定值一般用在用戶自定義對檢測結果的組合程序上。
flags
操作方式。當前唯一可以定義的操作方式是 CV_HAAR_DO_CANNY_PRUNING
。如果被設定,函數利用Canny邊緣檢測器來排除一些邊緣很少或者很多的圖像區域,因爲這樣的區域一般不含被檢目標。人臉檢測中通過設定閾值使用了這種方法,並因此提高了檢測速度。
min_size
檢測窗口的最小尺寸。缺省的情況下被設爲分類器訓練時採用的樣本尺寸(人臉檢測中缺省大小是~20×20)。
函數
cvHaarDetectObjects 使用針對某目標物體訓練的級聯分類器在圖像中找到包含目標物體的矩形區域,並且將這些區域作爲一序列的矩形框返回。函數以不同比例大小的掃描窗口對圖像進行幾次搜索(察看cvSetImagesForHaarClassifierCascade)。每次都要對圖像中的這些重疊區域利用cvRunHaarClassifierCascade進行檢測。有時候也會利用某些繼承(heuristics)技術以減少分析的候選區域,例如利用
Canny 裁減 (prunning)方法。 函數在處理和收集到候選的方框(全部通過級聯分類器各層的區域)之後,接着對這些區域進行組合並且返回一系列各個足夠大的組合中的平均矩形。調節程序中的缺省參數(scale_factor
=1.1,
min_neighbors
=3, flags
=0)用於對目標進行更精確同時也是耗時較長的進一步檢測。爲了能對視頻圖像進行更快的實時檢測,參數設置通常是:scale_factor
=1.2,
min_neighbors
=2, flags
=CV_HAAR_DO_CANNY_PRUNING,
min_size
=<minimum possible face size> (例如, 對於視頻會議的圖像區域).
例子:利用級聯的Haar classifiers尋找檢測目標(e.g. faces).
#include "cv.h"
#include "highgui.h"
CvHaarClassifierCascade* load_object_detector( const char* cascade_path )
{
return (CvHaarClassifierCascade*)cvLoad( cascade_path );
}
void detect_and_draw_objects( IplImage* image,
CvHaarClassifierCascade* cascade,
int do_pyramids )
{
IplImage* small_image = image;
CvMemStorage* storage = cvCreateMemStorage(0);
CvSeq* faces;
int i, scale = 1;
/* if the flag is specified, down-scale the 輸入圖像 to get a
performance boost w/o loosing quality (perhaps) */
if( do_pyramids )
{
small_image = cvCreateImage( cvSize(image->width/2,image->height/2), IPL_DEPTH_8U, 3 );
cvPyrDown( image, small_image, CV_GAUSSIAN_5x5 );
scale = 2;
}
/* use the fastest variant */
faces = cvHaarDetectObjects( small_image, cascade, storage, 1.2, 2, CV_HAAR_DO_CANNY_PRUNING );
/* draw all the rectangles */
for( i = 0; i < faces->total; i++ )
{
/* extract the rectanlges only */
CvRect face_rect = *(CvRect*)cvGetSeqElem( faces, i, 0 );
cvRectangle( image, cvPoint(face_rect.x*scale,face_rect.y*scale),
cvPoint((face_rect.x+face_rect.width)*scale,
(face_rect.y+face_rect.height)*scale),
CV_RGB(255,0,0), 3 );
}
if( small_image != image )
cvReleaseImage( &small_image );
cvReleaseMemStorage( &storage );
}
/* takes image filename and cascade path from the command line */
int main( int argc, char** argv )
{
IplImage* image;
if( argc==3 && (image = cvLoadImage( argv[1], 1 )) != 0 )
{
CvHaarClassifierCascade* cascade = load_object_detector(argv[2]);
detect_and_draw_objects( image, cascade, 1 );
cvNamedWindow( "test", 0 );
cvShowImage( "test", image );
cvWaitKey(0);
cvReleaseHaarClassifierCascade( &cascade );
cvReleaseImage( &image );
}
return 0;
}