您的位置:首页 > 编程语言

基于opencv的人脸检测代码

2014-11-20 09:24 429 查看
#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的调试里面的命令行参数里!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: