在优快云上拜读大牛们的博文已有余月,感慨颇深,也有过写些博文聊表自己的理解,但恐自己才学浅薄而误人子弟,也就作罢。今天无意中在大神Rachel-Zhang的博文中发现一首原创诗句,读完后就觉得其实之前自己的那些想法真是一叶障目。。
好诗篇胜过良药,读完神清气爽如饮甘霖哈哈,有兴趣的童鞋可以进去拜读一下,瞻仰瞻仰大神风采
http://blog.youkuaiyun.com/abcjennifer/article/details/8580321
言归正传,本文记录如何调用OpenCV中的Adboost分类器对输入照片进行人脸检测以及其中应该注意的一些事项。最后附上本人调通的程序和实验结果,以供日后翻看参考。
所用工具:VS2010 +OpenCV ;
输入:包含若干人脸的照片一张 (本程序中 E:\\Picture\\Face_net\\people.jpg);
输出:检测到的人脸数和所有时长以及检测结果。
在VS中进行OpenCV的配置可以参考浅墨大神的博文,链接如下:
http://blog.youkuaiyun.com/poem_qianmo/article/details/19809337
在照着教程配置的过程中也有可能因为自己的马虎而导致配置不当,这里列出我碰到的问题:
在添加附加项过程中,将附加项按名字排列,导致配置不当程序一直报错。
附加项添加正确配置:将opencv_**d.lib(Debug)和opencv_**.lib(Release)归为两类,opencv_**d.lib类文件排在前面,opencv_**.lib类文件排在后面,其中**代表文件名。效果图如下:
程序部分:
#include <opencv2/opencv.hpp>
#include <cstdio>
#include <cstdlib>
#include <Windows.h>
using namespace std;
int main()
{
// 加载Haar特征检测分类器
// haarcascade_frontalface_alt.xml系OpenCV自带的分类器下面是我机器上的文件路径
const char *pstrCascadeFileName = "D:\\Program Files\\OpenCV\\opencv2.4.4\\data\\haarcascades\\haarcascade_frontalface_alt.xml";
CvHaarClassifierCascade *pHaarCascade = NULL;
pHaarCascade = (CvHaarClassifierCascade*)cvLoad(pstrCascadeFileName);
// 载入图像
const char *pstrImageName = "E:\\Picture\\Face_net\\people.jpg";
IplImage *pSrcImage = cvLoadImage(pstrImageName, CV_LOAD_IMAGE_UNCHANGED);
IplImage *pGrayImage = cvCreateImage(cvGetSize(pSrcImage), IPL_DEPTH_8U, 1);
cvCvtColor(pSrcImage, pGrayImage, CV_BGR2GRAY);
// 人脸识别与标记
if (pHaarCascade != NULL)
{
CvScalar FaceCirclecolors[] =
{
{{0, 0, 255}},
{{0, 128, 255}},
{{0, 255, 255}},
{{0, 255, 0}},
{{255, 128, 0}},
{{255, 255, 0}},
{{255, 0, 0}},
{{255, 0, 255}}
};
<span style="white-space:pre"> </span>int scale=1.3;
CvMemStorage *pcvMStorage = cvCreateMemStorage(0);
cvClearMemStorage(pcvMStorage);
// 识别
DWORD dwTimeBegin, dwTimeEnd;
dwTimeBegin = GetTickCount();
CvSeq *pcvSeqFaces = cvHaarDetectObjects(pGrayImage, pHaarCascade, pcvMStorage);
dwTimeEnd = GetTickCount();
printf("人脸个数: %d 识别用时: %d ms\n", pcvSeqFaces->total, dwTimeEnd - dwTimeBegin);
// 标记
for(int i = 0; i <pcvSeqFaces->total; i++)
{ /* 画矩形*/
CvRect* r = (CvRect*)cvGetSeqElem(pcvSeqFaces, i);
cvRectangle(pSrcImage,cvPoint(r->x*scale,r->y*scale), cvPoint((r->x+r->width)*scale,(r->y+r->height)*scale), FaceCirclecolors[i % 8],2);
/*画圆*/
/* CvPoint center;
int radius;
center.x = cvRound((r->x + r->width * 0.5));
center.y = cvRound((r->y + r->height * 0.5));
radius = cvRound((r->width + r->height) * 0.25);
cvCircle(pSrcImage, center, radius, FaceCirclecolors[i % 8], 2); */
}
cvReleaseMemStorage(&pcvMStorage);
}
const char *pstrWindowsTitle = "人脸识别";
cvNamedWindow(pstrWindowsTitle, CV_WINDOW_AUTOSIZE);
cvShowImage(pstrWindowsTitle, pSrcImage);
cvWaitKey(0);
cvDestroyWindow(pstrWindowsTitle);
cvReleaseImage(&pSrcImage);
cvReleaseImage(&pGrayImage);
return 0;
}
运行结果:
关于程序,强调几点:
1、加载分类器时,最好使用绝对路径,当然也不是不能用相对路径,前提是.xml文件在你所建工程中。
2、不知道是因为版本或其他什么原因,有些版本的.xml文件可能不可用或已被损坏,从而导致编译错误。遇到这种情况的较少,但我就遇到过一次,主要表现在程序其他地方都没错,但就是不出结果或者直接在加载分类器处出错。解决方案的话我个人是换一个版本试试。
3、从实验结果可以看出,OpenCV中自带的分类器检测率还是蛮高的,但还是存在误检,如果个人要求较高的话可以自己去训练分类器。