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

OpenCV人脸检测(C++代码)—— By wepon

2016-10-27 17:25 387 查看


OpenCV人脸检测(C++代码)—— By wepon

这篇文章简单总结一下人脸检测的代码实现,基于OpenCV,C++版本。之所以强调C++版本是因为OpenCV有很多其他语言的接口,之前我也写过人脸检测的Python实现《Python-OpenCV人脸检测(代码)》,这篇文章则讲C++实现,其实大同小异,C++相比于Python实现代码写起来会繁琐一点,这也是语言本身决定的吧。

为了保持代码风格一致,C++实现与之前的Python实现一样,都将人脸检测、眼睛检测、框出人脸、框出眼睛、截取保存人脸各个功能封装为函数,方便移植。


1、OpenCV中人脸检测采用的算法

在安装OpenCV的路径中(window系统),我们可以发现”…\opencv\sources\data”目录下有如下三个文件夹:



这正是OpenCV采用的算法。haarcascades文件下存放的是采用Haar特征的级联分类器(Cascade Classfier),hogcascades下存放采用HOG特征(梯度方向直方图)的级联分类器,lbpcascades下存放的是采用LBP特征的级联分类器。关于图像的Haar、LBP、HOG、SIFT等特征我将写另外的博文进行总结,这里就不详细展开。图中三个文件夹下存放了很多xml文件,这些是预先训练好的特征,用于构造分类器的,有人脸检测的、眼睛检测的、smile检测的、行人检测的等等。

在这篇文章中,仅以haarcascas下的”haarcascade_frontalface_alt.xml”和”haarcascade_eye.xml”作为例子。主要代码在下文讲解,更多代码也可以到我的github获取:here


2、代码实现

这个demo以下图为输入:



图像预处理
转化为灰度图
直方图均衡化

<code class="hljs bash has-numbering" style="display: block; padding: 0px; background: transparent; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal;">Mat img = imread(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"obama.jpg"</span>);
Mat img_gray;
cvtColor(img,img_gray,COLOR_BGR2GRAY );
equalizeHist(img_gray,img_gray);</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li></ul>


构造级联分类器

首先生成一个级联分类器的实例,然后用xml文件初始化该实例(调用load方法),最后调用该实例的detectMultiScale方法,作用在灰度图img_gray上,即可获取该图片中的各个人脸的坐标。detectMultiScale方法返回的是一个vector类型的容器,里面每个Rect存储的是人脸矩形的左上顶点、矩形宽度、矩形长度(x,y,width,height)。

<code class="hljs cpp has-numbering" style="display: block; padding: 0px; background: transparent; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal;">CascadeClassifier faces_cascade;
faces_cascade.load(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"haarcascade_frontalface_alt.xml"</span>);
<span class="hljs-stl_container" style="box-sizing: border-box;"><span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">vector</span><Rect></span> faces;
faces_cascade.detectMultiScale(img_gray,faces,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1.1</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>|CV_HAAR_SCALE_IMAGE, Size(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">30</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">30</span>) );</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li></ul>


框出人脸、眼睛

这部分用到的是opencv里的绘图工具,可以参考opencv文档基本绘画,这里不啰嗦。ellipse画椭圆、circle画圆形,它们的参数(比如circle的圆心半径)由级联分类器返回的Rect确定。

截取和保存人脸部分

可以根据级联分类器检测返回的Rect,获取图像的ROI,然后调用imwrite方法。

<code class="hljs fix has-numbering" style="display: block; padding: 0px; background: transparent; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal;"><span class="hljs-attribute" style="box-sizing: border-box;">Rect roi </span>=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;"> faces[i];
imwrite(saveName,img(roi));</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul>


由于检测出的face不只一个,所以saveName需要设计一下,具体在代码文件中有注释。
运行结果



转载请注明来源并完整保留文中链接:http://blog.csdn.net/u012162613/article/details/44081975
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: