基於opencv的人臉檢測代碼

#define CV_NO_BACKWARD_COMPATIBILITY
#include "cv.h"
#include "highgui.h"
#include "opencv2/opencv.hpp"
#include <iostream>
#include <cstdio>
#ifdef _EiC
#define WIN32
#endif


using namespace std;
using namespace cv;
void detectAndDraw( Mat& img,
CascadeClassifier& cascade, CascadeClassifier& nestedCascade,
double scale);
String cascadeName ="haarcascade_frontalface_alt.xml";
String nestedCascadeName ="haarcascade_eye_tree_eyeglasses.xml";
CascadeClassifier face_cascade;
CascadeClassifier face_cascade1;
void detectAndDisplay( Mat & frame );
int main( int argc, const char** argv )
{



Mat frame, frameCopy, image;
//const String scaleOpt = "--scale=";
//size_t scaleOptLen = scaleOpt.length();
//const String cascadeOpt = "--cascade=";
//size_t cascadeOptLen = cascadeOpt.length();
//const String nestedCascadeOpt = "--nested-cascade";
//size_t nestedCascadeOptLen = nestedCascadeOpt.length();
//String inputName;
//CascadeClassifier cascade, nestedCascade;//應該是存儲haarcascade用到的形狀文件
//double scale = 1;//檢測出物體後所畫的圓圈的大小
//for( int i = 1; i < argc; i++ )
//{
// if( cascadeOpt.compare( 0, cascadeOptLen, argv[i], cascadeOptLen ) == 0 )
// cascadeName.assign( argv[i] + cascadeOptLen );
// else if( nestedCascadeOpt.compare( 0, nestedCascadeOptLen, argv[i], nestedCascadeOptLen ) == 0 )
// {
// if( argv[i][nestedCascadeOpt.length()] == '=' )
// nestedCascadeName.assign( argv[i] + nestedCascadeOpt.length() + 1 );
// if( !nestedCascade.load( nestedCascadeName ) )
// cerr << "WARNING: Could not load classifier cascade for nested objects" << endl;
// }
// else if( scaleOpt.compare( 0, scaleOptLen, argv[i], scaleOptLen ) == 0 )
// {
// if( !sscanf( argv[i] + scaleOpt.length(), "%lf", &scale ) || scale < 1 )
// scale = 1;
// }
// else if( argv[i][0] == '-' )
// {
// cerr << "WARNING: Unknown option %s" << argv[i] << endl;
// }
// else
// inputName.assign( argv[i] );
//}
//if( !cascade.load( cascadeName ) )
//{
// cerr << "ERROR: Could not load classifier cascade" << endl;
// cerr << "Usage: facedetect [--cascade=\"<cascade_path>\"]\n"
// "   [--nested-cascade[=\"nested_cascade_path\"]]\n"
// "   [--scale[=<image scale>\n"
// "   [filename|camera_index]\n" ;
// return -1;
//}
//if( inputName.empty() || (isdigit(inputName.c_str()[0]) && inputName.c_str()[1] == '\0') )
// capture = cvCaptureFromCAM( inputName.empty() ? 0 : inputName.c_str()[0] - '0' );
//else if( inputName.size() )
//{
// image = imread( inputName, 1 );
// if( image.empty() )
// capture = cvCaptureFromAVI( inputName.c_str() );
//}
//else
// image = imread( "lena.jpg", 1 );


//CvCapture* capture = cvCreateCameraCapture(-1);
//NamedWindow( "result", 1 );
VideoCapture capture(0);
//capture>>frame;

if(!face_cascade.load(cascadeName))
{
std::cerr<<"load cascade error!"<<std::endl;
return 0;
}


//if( capture )
//{
   cv::namedWindow("show",WINDOW_AUTOSIZE);
while(1)
{
//從攝像頭獲取的圖像中獲取一幀
/*IplImage* iplImg = cvQueryFrame( capture );
frame = iplImg;*/

capture>>frame;


if( frame.empty() )
continue;


frame.copyTo( frameCopy );
detectAndDisplay(frameCopy );
detectAndDraw(frameCopy,face_cascade, face_cascade1,1);


//cv::imshow("show", frame );
cv::imshow("show", frameCopy );


char key = cv::waitKey(20);
if(key == 'q')
break;


//if( iplImg->origin == IPL_ORIGIN_TL )
// frame.copyTo( frameCopy );
////else
//flip( frame, frameCopy, 0 );
// detectAndDraw( frameCopy, cascade, nestedCascade, scale );
//if( waitKey( 10 ) >= 0 )
// break;
}
//waitKey(0);
   //cvReleaseCapture( &capture );
   //}
//else
//{
// //檢測圖片中的圖像,當參數輸入時圖片時用到這部分
// if( !image.empty() )
// {
// detectAndDraw( image, cascade, nestedCascade, scale );
// waitKey(0);
// }
// else if( !inputName.empty() )
// {


// FILE* f = fopen( inputName.c_str(), "rt" );
// if( f )
// {
// char buf[1000+1];
// while( fgets( buf, 1000, f ) )
// {
// int len = (int)strlen(buf), c;
// while( len > 0 && isspace(buf[len-1]) )
// len--;
// buf[len] = '\0';
// cout << "file " << buf << endl;
// image = imread( buf, 1 );
// if( !image.empty() )
// {
// detectAndDraw( image, cascade, nestedCascade, scale );
// c = waitKey(0);
// if( c == 27 || c == 'q' || c == 'Q' )
// break;
// }
// }
// fclose(f);
// }
// }
//}
//cvDestroyWindow("result");
return 0;
}
//檢測的核心部分
void detectAndDraw( Mat& img,
CascadeClassifier& cascade, CascadeClassifier& nestedCascade,
double scale)
{
if(!cascade.load(cascadeName)&&nestedCascade.load(nestedCascadeName) )
{
std::cerr<<"load cascade error!"<<std::endl;

}
int i = 0;
double t = 0;//用來記錄檢測出人臉所用的時間
vector<Rect> faces;//存儲檢測到的人臉所在矩形區域
const static Scalar colors[] =  { CV_RGB(0,0,255),
CV_RGB(0,128,255),
CV_RGB(0,255,255),
CV_RGB(0,255,0),
CV_RGB(255,128,0),
CV_RGB(255,255,0),
CV_RGB(255,0,0),
CV_RGB(255,0,255)} ;//畫圓圈的顏色
//存儲圖片的矩陣
Mat gray, smallImg( cvRound (img.rows/scale), cvRound(img.cols/scale), CV_8UC1 );
//將輸入的圖像裝換成CV_BGR2GRAY,應該是灰度圖
cvtColor( img, gray, CV_BGR2GRAY );
//調整圖像大小
resize( gray, smallImg, smallImg.size(), 0, 0, INTER_LINEAR );
equalizeHist( smallImg, smallImg );//直方圖均衡化
//imshow("eque",smallImg);
t = (double)cvGetTickCount();//記錄檢測所用時間,返回CPU時鐘數


cascade.detectMultiScale(
smallImg,//Matrix of type CV 8U containing the image in which to detect objects.
faces,//Vector of rectangles such that each rectangle contains the detected object.
1.1,//Specifies how much the image size is reduced at each image scale.
2,//Speficifes how many neighbors should each candiate rectangle have to retain it.
0
//|CV_HAAR_FIND_BIGGEST_OBJECT
//|CV_HAAR_DO_ROUGH_SEARCH
|CV_HAAR_SCALE_IMAGE,//This parameter is not used for new cascade and have the same meaning
//for old cascade as in function cvHaarDetectObjects.
Size(30, 30) //The minimum possible object size. Objects smaller than that are ignored.
);
for( int i = 0; i < faces.size(); i++ )
{
Point center( faces[i].x + faces[i].width*0.5, faces[i].y + faces[i].height*0.5 );
ellipse(img, center, Size( faces[i].width*0.5, faces[i].height*0.5), 0, 0, 360, Scalar( 255, 0, 255 ), 4, 8, 0 );
}
t = (double)cvGetTickCount() - t;
printf( "detection time = %g ms\n", t/((double)cvGetTickFrequency()*1000.) );
//在人臉裏面檢測人眼
for( vector<Rect>::const_iterator r = faces.begin(); r != faces.end(); r++, i++ )
{

Mat smallImgROI;
vector<Rect> nestedObjects;//存儲人眼的矩形區域
Point center;
Scalar color = colors[i%8];
int radius;
//繪製包住人臉的圓圈
//計算圓圈的圓心和半徑
center.x = cvRound((r->x + r->width*0.5)*scale);
center.y = cvRound((r->y + r->height*0.5)*scale);
radius = cvRound((r->width + r->height)*0.25*scale);
circle( img, center, radius, color, 3, 8, 0 );
if( nestedCascade.empty() )
continue;
smallImgROI = smallImg(*r);
//找人眼
nestedCascade.detectMultiScale( smallImgROI, nestedObjects,
1.1, 2, 0
//|CV_HAAR_FIND_BIGGEST_OBJECT
//|CV_HAAR_DO_ROUGH_SEARCH
//|CV_HAAR_DO_CANNY_PRUNING
|CV_HAAR_SCALE_IMAGE
,
Size(30, 30) );
//畫人眼
for( vector<Rect>::const_iterator nr = nestedObjects.begin(); nr != nestedObjects.end(); nr++ )
{
center.x = cvRound((r->x + nr->x + nr->width*0.5)*scale);
center.y = cvRound((r->y + nr->y + nr->height*0.5)*scale);
radius = cvRound((nr->width + nr->height)*0.25*scale);
circle( img, center, radius, color, 3, 8, 0 );
}

cv::imshow( "result", img );   
}






void detectAndDisplay( Mat & frame )
{
std::vector<Rect> faces;
Mat frame_gray;
cvtColor( frame, frame_gray, CV_BGR2GRAY );
//equalizeHist( frame_gray, frame_gray );


face_cascade.detectMultiScale( frame_gray, faces, 1.1, 2, 0|CV_HAAR_SCALE_IMAGE, Size(30, 30) );

std::cout<<"face count:\t"<<faces.size()<<std::endl;
for( int i = 0; i < faces.size(); i++ )
{
cv::Point center( faces[i].x + faces[i].width*0.5, faces[i].y + faces[i].height*0.5 );
ellipse( frame, center, Size( faces[i].width*0.5, faces[i].height*0.5), 0, 0, 360, Scalar( 255, 0, 255 ), 4, 8, 0 );
}


}

要把haarcascade_eye_tree_eyeglasses.xml和haarcascade_frontalface_alt.xml兩個.xml文件添加到當前文件夾下(這兩個文件在opencv2.0 source中的data文件夾下),還要把這兩個文件添加到vs2010的調試裏面的命令行參數裏!

發佈了13 篇原創文章 · 獲贊 5 · 訪問量 6701
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章