请注意您首先要已配置好opencv环境,代码中视频路径换位自己的视频路径。
// oc22.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#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>
char filename[128];//存放截取人脸的文件名
char num[128];//存放要在人脸图片中显示的数字
int count = 1;//计截取的图片的数
static CvMemStorage* storage = 0;
static CvHaarClassifierCascade* cascade = 0;
void detect_and_draw( IplImage* image );
const char* cascade_name =
//"haarcascade_frontalface_alt.xml"; //opencv自带的特征分类器
"D:\\opencv\\sources\\data\\haarcascades\\haarcascade_upperbody.xml";
int _tmain(int argc, _TCHAR* argv[])
{
CvCapture* capture = 0;
IplImage *frame, *frame_copy = 0;
cascade = (CvHaarClassifierCascade*)cvLoad( cascade_name, 0, 0, 0 );
if( !cascade )
{
printf("No cascade!!!!\n");
return -1;
}
storage = cvCreateMemStorage(0);
// capture = cvCaptureFromCAM( -1);//摄像头视频
// capture = cvCaptureFromAVI("F:\\OPENCV实验室\\test.avi");//存好的视频文件
capture = cvCaptureFromFile("E:\\00012.avi" );
cvNamedWindow( "result", 1 );
if( capture )
{
for(;;)
{
if( !cvGrabFrame( capture ))
break;
frame = cvRetrieveFrame( capture );
if( !frame )
break;
if( !frame_copy )
frame_copy = cvCreateImage( cvSize(frame->width,frame->height),
IPL_DEPTH_8U, frame->nChannels );
if( frame->origin == IPL_ORIGIN_TL )
cvResize( frame, frame_copy, 1 );
else
cvFlip( frame, frame_copy, 0 );
detect_and_draw( frame_copy );
if( cvWaitKey( 10 ) >= 0 )
break;
}
cvReleaseImage( &frame_copy );
cvReleaseCapture( &capture );
}
cvDestroyWindow("result");
return 0;
}
void detect_and_draw( IplImage* img )
{
static CvScalar colors[] =
{
{{0,0,255}},
{{0,128,255}},
{{0,255,255}},
{{0,255,0}},
{{255,128,0}},
{{255,255,0}},
{{255,0,0}},
{{255,0,255}}
};
int addwid;//截取人头像时宽度增加 20141106
int addhei;//截取人头像时高度增加 20141106
double scale =1;
IplImage* gray = cvCreateImage( cvSize(img->width,img->height), 8, 1 );
IplImage* small_img = cvCreateImage( cvSize( cvRound (img->width/scale),
cvRound (img->height/scale)), /*缩小图片以提高运行速度*/
8, 1 );
int i;
//对图片的预处理,这里要慎重,不然可能影响人脸检测的效果,可根据实际情况决定
cvCvtColor( img, gray, CV_BGR2GRAY ); //颜色空间转换,彩色转灰
cvResize( gray, small_img, CV_INTER_LINEAR );//重新调整图像,CV_INTER_LINEAR是双线性插值(默认方法)
cvEqualizeHist( small_img, small_img ); //使灰度图象直方图均衡化
//cvDilate(small_img,small_img,NULL,1);//膨胀
//cvErode(small_img,small_img,NULL,1);//腐蚀
//cvSmooth(small_img,small_img,CV_MEDIAN,3,0,0,0);//中值滤波
cvClearMemStorage( storage );
if( cascade )
{
double t = (double)cvGetTickCount(); //从操作系统启动所经过的毫秒数
CvSeq* faces = cvHaarDetectObjects( small_img, cascade, storage,
1.2,2, CV_HAAR_DO_CANNY_PRUNING,cvSize(50,50) ); //找出人脸的矩形区域
t = ((double)cvGetTickCount()-t); //人脸检测的用时
printf( "detection time = %gms\n", t/((double)cvGetTickFrequency()*1000.) );
//截图用
IplImage * frame1 = cvCreateImage( cvSize(img->width,img->height),
IPL_DEPTH_8U, img->nChannels );
cvCopy( img, frame1, 0 );
for( i = 0; i < (faces ? faces->total : 0); i++ )
{
CvRect* r = (CvRect*)cvGetSeqElem( faces, i );
//截图
if(r->x*scale-10<0||r->y*scale-10<0||frame1->width<r->x*scale+r->width*scale+10
||frame1->height<r->y*scale+r->height+10)//判断截图是否越界 20141106
{
cvSetImageROI(frame1, cvRect(r->x* scale,r->y* scale,r->width* scale,r->height* scale));//越界时设置源图像ROI 20141106
addwid=0;
addhei=0;//越界时以获取的矩形区域截图 20141106
}
else
{
cvSetImageROI(frame1, cvRect(r->x* scale-10,r->y* scale-10,r->width* scale+20,r->height* scale+20));//设置源图像ROI
//frame1指向ROI
addwid=20;
addhei=20;//非越界时在获取的矩形宽和高的基础上扩大一些 20141106
}
IplImage* pDest = cvCreateImage(cvSize(r->width*scale+addwid,r->height* scale+addhei),8,3);//创建目标图像
cvCopy(frame1,pDest,0); //复制图像
//在图片上书写数字
sprintf(num, "%d", count);
CvFont font;
cvInitFont( &font, CV_FONT_VECTOR0,0.5, 1, 0,2, 8);
CvSize text_size;
int baseline;
cvGetTextSize(num, &font, &text_size, &baseline);
cvPutText(pDest, num , cvPoint(4,text_size.height+baseline), &font, CV_RGB(255,0,0));
sprintf(filename, "img_%d.jpg", count++);
cvSaveImage(filename,pDest);//保存目标图像
cvReleaseImage( &pDest );
cvResetImageROI(frame1);//使frame1指向源图像20141106
//用圆圈出人脸
CvPoint center;
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.3*scale);
cvCircle( img, center, radius, colors[i%8], 2, 8, 0 );
}
cvReleaseImage( &frame1 );//释放截图用
}
cvShowImage( "result", img );
cvReleaseImage( &gray );
cvReleaseImage( &small_img );
}