基于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的调试里面的命令行参数里!

#include "stdafx.h" #include "cv.h" #include "highgui.h" #include <stdio.h> int _tmain(int argc, _TCHAR* argv[]) { CvCapture* capture=0; /*初始化一个视频捕获操作。告诉底层的捕获api我想从Capture1.avi中捕获图片, 底层api将检测并选择相应的解码器并做好准备工作*/ capture = cvCaptureFromFile( "F:\\1.avi"); //设置要读的视频(avi格式) static CvMemStorage* storage = 0; static CvHaarClassifierCascade* cascade = 0; cascade = (CvHaarClassifierCascade*)cvLoad("haarcascade_frontalface_alt.xml",0,0,0); if( !cascade || !capture ) return -1; storage = cvCreateMemStorage(0); /*创建一个窗口,用“Video”作为窗口的标识符*/ cvNamedWindow( "Video",1); /*如果初始化失败,那么capture为空指针,程序停止,否则进入捕获循环*/ if( capture ) { for(;;) { IplImage* frame = cvQueryFrame( capture ); IplImage* img = NULL; CvSeq* faces; if( !frame ) break; img = cvCloneImage(frame); img->origin = 0; if( frame->origin ) cvFlip(img,img); cvClearMemStorage( storage ); //目标检测 faces = cvHaarDetectObjects( img, cascade, storage,1.1, 2, CV_HAAR_DO_CANNY_PRUNING, cvSize(20, 20) ); for( int i = 0; i < (faces ? faces->total : 0); i++ ) { CvRect* r = (CvRect*)cvGetSeqElem( faces, i ); cvRectangle( img, cvPoint(r->x,r->y), cvPoint(r->x+r->width,r->y+r->height), CV_RGB(255,0,0), 1); } cvShowImage( "Video", img ); //设置每帧图像的间隔 Sleep(50); /*如果你敲了键盘,就退出程序,否则继续捕获下一帧*/ if( cvWaitKey(10)>0 ) break; } /*退出之前结束底层api的捕获操作,比如会使得别的程序无法访问已经被它们打开的文件*/ cvReleaseCapture( &capture;); } /*销毁窗口*/ cvDestroyWindow("Video"); return 0; }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值