基于opencv的人脸识别程序代码详解.docx
- 文档编号:29252489
- 上传时间:2023-07-21
- 格式:DOCX
- 页数:20
- 大小:22.05KB
基于opencv的人脸识别程序代码详解.docx
《基于opencv的人脸识别程序代码详解.docx》由会员分享,可在线阅读,更多相关《基于opencv的人脸识别程序代码详解.docx(20页珍藏版)》请在冰豆网上搜索。
基于opencv的人脸识别程序代码详解
#include"cv.h"
#include"highgui.h"
#include
#ifdef_EiC
#defineWIN32
#endif
staticCvMemStorage*storage=0;
staticCvHaarClassifierCascade*cascade=0;
voiddetect_and_draw(IplImage*image);
constchar*cascade_name=
"haarcascade_frontalface_alt.xml";//人脸检测分类器
intmain(intargc,char**argv)
{
CvCapture*capture=0;
IplImage*frame,*frame_copy=0;
intoptlen=strlen("--cascade=");
constchar*input_name;
if(argc>1&&strncmp(argv[1],"--cascade=",optlen)==0)
{
cascade_name=argv[1]+optlen;
input_name=argc>2?
argv[2]:
0;
}
else
{
cascade_name="E:
\毕业设计\智能机器人动态人脸识别系统\陈建州程序.xml";//分类器路径
input_name=argc>1?
argv[1]:
0;
}
cascade=(CvHaarClassifierCascade*)cvLoad(cascade_name,0,0,0);
if(!
cascade)//如果没有找到分类器,输出以下
{
fprintf(stderr,"ERROR:
Couldnotloadclassifiercascade\n");
fprintf(stderr,
"Usage:
facedetect--cascade=\"
return-1;
}
storage=cvCreateMemStorage(0);
capture=cvCaptureFromCAM(!
input_name?
0:
input_name[0]-'0');//读取摄像头
if(!
capture)//如果没有摄像头读取视频文件
capture=cvCaptureFromAVI("检测.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)
cvCopy(frame,frame_copy,0);
else
cvFlip(frame,frame_copy,0);
detect_and_draw(frame_copy);
if(cvWaitKey(10)>=0)
break;
}
cvReleaseImage(&frame_copy);
cvReleaseCapture(&capture);
}
else//没检测到视频文件或者摄像头
{
constchar*filename=(char*)"检测.jpg";//读图片
IplImage*image=cvLoadImage(filename,1);
if(image)
{
detect_and_draw(image);
cvWaitKey(0);
cvReleaseImage(&image);
}
else
{
FILE*f=fopen(filename,"rt");
if(f)
{
charbuf[1000+1];
while(fgets(buf,1000,f))
{
intlen=(int)strlen(buf);
while(len>0&&isspace(buf[len-1]))
len--;
buf[len]='\0';
image=cvLoadImage(buf,1);
if(image)
{
detect_and_draw(image);
cvWaitKey(0);
cvReleaseImage(&image);
}
}
fclose(f);
}
}
}
cvDestroyWindow("result");
return0;
}
voiddetect_and_draw(IplImage*img)
{
staticCvScalarcolors[]=
{
{{0,0,255}},
{{0,128,255}},
{{0,255,255}},
{{0,255,0}},
{{255,128,0}},
{{255,255,0}},
{{255,0,0}},
{{255,0,255}}
};
doublescale=1.3;
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);
inti;
cvCvtColor(img,gray,CV_BGR2GRAY);
cvResize(gray,small_img,CV_INTER_LINEAR);
cvEqualizeHist(small_img,small_img);
cvClearMemStorage(storage);
if(cascade)
{
doublet=(double)cvGetTickCount();
CvSeq*faces=cvHaarDetectObjects(small_img,cascade,storage,
1.1,2,0/*CV_HAAR_DO_CANNY_PRUNING*/,
cvSize(30,30));//检测人脸返回矩形人脸
t=(double)cvGetTickCount()-t;
printf("detectiontime=%gms\n",t/((double)cvGetTickFrequency()*1000.));
for(i=0;i<(faces?
faces->total:
0);i++)//找到矩形中心,把矩形转化为圆形
{
CvRect*r=(CvRect*)cvGetSeqElem(faces,i);
CvPointcenter;
intradius;
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);
cvCircle(img,center,radius,colors[i%8],3,8,0);
}
}
cvShowImage("result",img);
cvReleaseImage(&gray);
cvReleaseImage(&small_img);
}
OpenCV的人脸检测主要是调用训练好的cascade(Haar分类器)来进行模式匹配。
cvHaarDetectObjects,先将图像灰度化,根据传入参数判断是否进行canny边缘处理(默认不使用),再进行匹配。
匹配后收集找出的匹配块,过滤噪声,计算相邻个数如果超过了规定值(传入的min_neighbors)就当成输出结果,否则删去。
匹配循环:
将匹配分类器放大scale(传入值)倍,同时原图缩小scale倍,进行匹配,直到匹配分类器的大小大于原图,则返回匹配结果。
匹配的时候调用cvRunHaarClassifierCascade来进行匹配,将所有结果存入CvSeq*Seq(可动态增长元素序列),将结果传给cvHaarDetectObjects。
cvRunHaarClassifierCascade函数整体是根据传入的图像和cascade来进行匹配。
并且可以根据传入的cascade类型不同(树型、stump(不完整的树)或其他的),进行不同的匹配方式。
函数cvRunHaarClassifierCascade用于对单幅图片的检测。
在函数调用前首先利用cvSetImagesForHaarClassifierCascade设定积分图和合适的比例系数(=>窗口尺寸)。
当分析的矩形框全部通过级联分类器每一层的时返回正值(这是一个候选目标),否则返回0或负值。
为了了解OpenCV人脸检测中寻找匹配图像的详细过程,就把cvHaarDetectObjects和cvRunHaarClassifierCascade的源文件详细看了一遍,并打上了注释。
方便大家阅读。
附cvHaarDetectObjects代码:
CV_IMPLCvSeq*
cvHaarDetectObjects(constCvArr*_img,
CvHaarClassifierCascade*cascade,
CvMemStorage*storage,doublescale_factor,
intmin_neighbors,intflags,CvSizemin_size)
{
intsplit_stage=2;
CvMatstub,*img=(CvMat*)_img;//CvMat多通道矩阵*img=_img指针代换传入图
CvMat*temp=0,*sum=0,*tilted=0,*sqsum=0,*norm_img=0,*sumcanny=0,*img_small=0;
CvSeq*seq=0;
CvSeq*seq2=0;//CvSeq可动态增长元素序列
CvSeq*idx_seq=0;
CvSeq*result_seq=0;
CvMemStorage*temp_storage=0;
CvAvgComp*comps=0;
inti;
#ifdef_OPENMP
CvSeq*seq_thread[CV_MAX_THREADS]={0};
intmax_threads=0;
#endif
CV_FUNCNAME(“cvHaarDetectObjects”);
__BEGIN__;
doublefactor;
intnpass=2,coi;//npass=2
intdo_canny_pruning=flags&CV_HAAR_DO_CANNY_PRUNING;//true做canny边缘处理
if(!
CV_IS_HAAR_CLASSIFIER(cascade))
CV_ERROR(!
cascade?
CV_StsNullPtr:
CV_StsBadArg,“Invalidclassifiercascade”);
if(!
storage)
CV_ERROR(CV_StsNullPtr,“Nullstoragepointer”);
CV_CALL(img=cvGetMat(img,&stub,&coi));
if(coi)
CV_ERROR(CV_BadCOI,“COIisnotsupported”);//一些出错代码
if(CV_MAT_DEPTH(img->type)!
=CV_8U)
CV_ERROR(CV_StsUnsupportedFormat,“Only8-bitimagesaresupported”);
CV_CALL(temp=cvCreateMat(img->rows,img->cols,CV_8UC1));
CV_CALL(sum=cvCreateMat(img->rows+1,img->cols+1,CV_32SC1));
CV_CALL(sqsum=cvCreateMat(img->rows+1,img->cols+1,CV_64FC1));
CV_CALL(temp_storage=cvCreateChildMemStorage(storage));
#ifdef_OPENMP
max_threads=cvGetNumThreads();
for(i=0;i { CvMemStorage*temp_storage_thread; CV_CALL(temp_storage_thread=cvCreateMemStorage(0));//CV_CALL就是运行,假如出错就报错。 CV_CALL(seq_thread[i]=cvCreateSeq(0,sizeof(CvSeq),//CvSeq可动态增长元素序列 sizeof(CvRect),temp_storage_thread)); } #endif if(! cascade->hid_cascade) CV_CALL(icvCreateHidHaarClassifierCascade(cascade)); if(cascade->hid_cascade->has_tilted_features) tilted=cvCreateMat(img->rows+1,img->cols+1,CV_32SC1);//多通道矩阵图像长宽+14通道 seq=cvCreateSeq(0,sizeof(CvSeq),sizeof(CvRect),temp_storage);//创建序列seq矩形 seq2=cvCreateSeq(0,sizeof(CvSeq),sizeof(CvAvgComp),temp_storage);//创建序列seq2矩形和邻近 result_seq=cvCreateSeq(0,sizeof(CvSeq),sizeof(CvAvgComp),storage);//创建序列result_seq矩形和邻近 if(min_neighbors==0) seq=result_seq; if(CV_MAT_CN(img->type)>1) { cvCvtColor(img,temp,CV_BGR2GRAY);//img转为灰度 img=temp; } if(flags&CV_HAAR_SCALE_IMAGE)//flag&&匹配图 { CvSizewin_size0=cascade->orig_window_size;//CvSizewin_size0为分类器的原始大小 intuse_ipp=cascade->hid_cascade->ipp_stages! =0&& icvApplyHaarClassifier_32s32f_C1R_p! =0;//IPP相关函数 if(use_ipp) CV_CALL(norm_img=cvCreateMat(img->rows,img->cols,CV_32FC1));//图像的矩阵化4通道. CV_CALL(img_small=cvCreateMat(img->rows+1,img->cols+1,CV_8UC1));//小图矩阵化单通道长宽+1 for(factor=1;;factor*=scale_factor)//成scale_factor倍数匹配 { intpositive=0; intx,y; CvSizewin_size={cvRound(win_size0.width*factor), cvRound(win_size0.height*factor)};//winsize分类器行列(扩大factor倍) CvSizesz={cvRound(img->cols/factor),cvRound(img->rows/factor)};//sz图像行列(缩小factor倍)三个Cvsize CvSizesz1={sz.width–win_size0.width,sz.height–win_size0.height};//sz1图像减分类器行列 CvRectrect1={icv_object_win_border,icv_object_win_border, win_size0.width–icv_object_win_border*2,//icv_object_win_border(int)初始值=1 win_size0.height–icv_object_win_border*2};//矩形框rect1 CvMatimg1,sum1,sqsum1,norm1,tilted1,mask1;//多通道矩阵 CvMat*_tilted=0; if(sz1.width<=0||sz1.height<=0)//图片宽或高小于分类器–>跳出 break; if(win_size.width continue; //CV_8UC1见定义. //#defineCV_MAKETYPE(depth,cn)((depth)+(((cn)-1)< //深度+(cn-1)左移3位depth,depth+8,depth+16,depth+24. img1=cvMat(sz.height,sz.width,CV_8UC1,img_small->data.ptr);//小图的矩阵化img1单通道 sum1=cvMat(sz.height+1,sz.width+1,CV_32SC1,sum->data.ptr);//长宽+14通道8位多通道矩阵 sqsum1=cvMat(sz.height+1,sz.width+1,CV_64FC1,sqsum->data.ptr);//长宽+14通道16位 if(tilted) { tilted1=cvMat(sz.height+1,sz.width+1,CV_32SC1,tilted->data.ptr);//长宽+14通道8位 _tilted=&tilted1;//长宽+14通道8位 } norm1=cvMat(sz1.height,sz1.width,CV_32FC1,norm_img? norm_img->data.ptr: 0);//norm1图像减分类器行列4通道 mask1=cvMat(sz1.height,sz1.width,CV_8UC1,temp->data.ptr);//mask1灰度图 cvResize(img,&img1,CV_INTER_LINEAR);//img双线性插值输出到img1 cvIntegral(&img1,&sum1,&sqsum1,_tilted);//计算积分图像 if(use_ipp&&icvRectStdDev_32s32f_C1R_p(sum1.data.i,sum1.step, sqsum1.data.db,sqsum1.step,norm1.data.fl,norm1.step,sz1,rect1)<0) use_ipp=0; if(use_ipp)//如果ipp=true(intel视频处理加速等的函数库) { positive=mask1.cols*mask1.rows;//mask1长乘宽–>positive cvSet(&mask1,cvScalarAll(255));//mask1赋值为255 for(i=0;i { if(icvApplyHaarClassifier_32s32f_C1R_p(sum1.data.i,sum1.step, norm1.data.fl,norm1.step,mask1.data.ptr,mask1.step, sz1,&positive,cascade->hid_cascade->stage_classifier[i].threshold, cascade->hid_cascade->ipp_stages[i])<0) { use_ipp=0;//ipp=false; break; } if(positive<=0) break; } } if(! use_ipp)//如果ipp=false { cvSetImagesForHaarClassifierCascade(c
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 基于 opencv 识别 程序代码 详解