利用opencv中的级联分类器进行人脸检測-opencv学习(1)
OpenCV支持的目标检測的方法是利用样本的Haar特征进行的分类器训练,得到的级联boosted分类器(Cascade Classification)。注意,新版本号的C++接口除了Haar特征以外也能够使用LBP特征。
先介绍一下相关的结构,级联分类器的计算特征值的基础类FeatureEvaluator,功能包含读操作read、复制clone、获得特征类型getFeatureType,分配图片分配窗体的操作setImage、setWindow,计算有序特征calcOrd,计算绝对特征calcCat,创建分类器特征的结构create函数。级联分类器类CascadeClassifier。目标级联矩形的分组函数groupRectangles。
接下来,我尝试使用CascadeClassifier这个级联分类器类检測视频流中的目标(haar支持的目标有人脸、人眼、嘴、鼻、身体。这里尝试比較成熟的人脸和眼镜)。用load函数载入XML分类器文件(眼下提供的分类器包含Haar分类器和LBP分类器(LBP分类器数据较少))详细过程例如以下:
这里再补充一点:后来我又进行了一些实验,对正面人脸分类器进行了实验,总共同拥有4个,alt、alt2、alt_tree、default。对照下来发现alt和alt2的效果比較好,alt_tree耗时较长,default是一个轻量级的,常常出现误检測。所以还是推荐大家使用haarcascade_frontalface_atl.xml和haarcascade_frontalface_atl2.xml。
1)载入级联分类器
调用CascadeClassifier类成员函数load实现,代码为:
<span style="font-size:18px;">CascadeClassifier face_cascade;
face_cascade.load("haarcascade_frontalface_alt.xml");</span>
2)读取视频流
3)对每一帧使用该分类器
这里先将图像变成灰度图,对它应用直方图均衡化,做一些预处理的工作。接下来检測人脸,调用detectMultiScale函数,该函数在输入图像的不同尺度中检測物体,參数image为输入的灰度图像,objects为得到被检測物体的矩形框向量组,scaleFactor为每个图像尺度中的尺度參数,默认值为1.1,minNeighbors參数为每个级联矩形应该保留的邻近个数(没能理解这个參数,-_-|||),默觉得3,flags对于新的分类器没实用(但眼下的haar分类器都是旧版的,CV_HAAR_DO_CANNY_PRUNING利用Canny边缘检測器来排除一些边缘非常少或者非常多的图像区域,CV_HAAR_SCALE_IMAGE就是按比例正常检測,CV_HAAR_FIND_BIGGEST_OBJECT仅仅检測最大的物体,CV_HAAR_DO_ROUGH_SEARCH仅仅做初略检測),默觉得0.minSize和maxSize用来限制得到的目标区域的范围。这里调用的代码例如以下:
<span style="font-size:18px;">face_cascade.detectMultiScale( frame_gray, faces, 1.1, 2, 0|CV_HAAR_SCALE_IMAGE, Size(30, 30) );</span>
代码例如以下
<span style="font-size:18px;"> #include "opencv2/objdetect/objdetect.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp" #include <iostream>
#include <stdio.h> using namespace std;
using namespace cv; /** 函数声明 */
void detectAndDisplay( Mat frame ); /** 全局变量 */
string face_cascade_name = "haarcascade_frontalface_alt.xml";
string eyes_cascade_name = "haarcascade_eye_tree_eyeglasses.xml";
CascadeClassifier face_cascade;
CascadeClassifier eyes_cascade;
string window_name = "Capture - Face detection";
RNG rng(12345); /** @主函数 */
int main( int argc, const char** argv )
{
CvCapture* capture;
Mat frame; //-- 1. 载入级联分类器文件
if( !face_cascade.load( face_cascade_name ) ){ printf("--(!)Error loading\n"); return -1; };
if( !eyes_cascade.load( eyes_cascade_name ) ){ printf("--(!)Error loading\n"); return -1; }; //-- 2. 打开内置摄像头视频流
capture = cvCaptureFromCAM( -1 );
if( capture )
{
while( true )
{
frame = cvQueryFrame( capture ); //-- 3. 对当前帧使用分类器进行检測
if( !frame.empty() )
{ detectAndDisplay( frame ); }
else
{ printf(" --(!) No captured frame -- Break!"); break; } int c = waitKey(10);
if( (char)c == 'c' ) { break; }
}
}
return 0;
} /** @函数 detectAndDisplay */
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) ); 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( frame, center, Size( faces[i].width*0.5, faces[i].height*0.5), 0, 0, 360, Scalar( 255, 0, 255 ), 4, 8, 0 ); Mat faceROI = frame_gray( faces[i] );
std::vector<Rect> eyes; //-- 在每张人脸上检測双眼
eyes_cascade.detectMultiScale( faceROI, eyes, 1.1, 2, 0 |CV_HAAR_SCALE_IMAGE, Size(30, 30) ); for( int j = 0; j < eyes.size(); j++ )
{
Point center( faces[i].x + eyes[j].x + eyes[j].width*0.5, faces[i].y + eyes[j].y + eyes[j].height*0.5 );
int radius = cvRound( (eyes[j].width + eyes[i].height)*0.25 );
circle( frame, center, radius, Scalar( 255, 0, 0 ), 4, 8, 0 );
}
}
//-- 显示结果图像
imshow( window_name, frame );
}
</span>
结果:
下图就是使用上述代码对内置摄像头的视频流进行人脸检測的结果图像:
注意复制分类器文件 haarcascade_frontalface_alt.xml 和haarcascade_eye_tree_eyeglasses.xml 到你的当前文件夹下. 他们在OpenCV安装文件夹
opencv/data/haarcascades 里面.
下图是使用分类器文件 lbpcascade_frontalface.xml (LBP特征训练的) 进行的检測结果. 对于双眼的检測依然使用刚才使用过的分类器.
參考:
利用opencv中的级联分类器进行人脸检測-opencv学习(1)的更多相关文章
- OpenCv 人脸检測的学习
近期公司要组织开发分享,可是自己还是新手真的不知道分享啥了,然后看了看前段时间研究过OpenCv,那么就分享他把. openCv就不介绍了,说下人脸检測.事实上是通过openCv里边已经训练好的xml ...
- 使用级联分类器实现人脸检测(OpenCV自带的数据)
#include <opencv2/opencv.hpp> #include <iostream> using namespace cv; using namespace st ...
- Viola-Jones人脸检測
OpenCV中有一个基于树的技术:Haar分类器,它建立了boost筛选式级联. 它能够识别出人脸和其它刚性物体. 对于检測"基本刚性"的物体(脸,汽车,自行车,人体等)这类识别任 ...
- OpenCV中基于Haar特征和级联分类器的人脸检测
使用机器学习的方法进行人脸检测的第一步需要训练人脸分类器,这是一个耗时耗力的过程,需要收集大量的正负样本,并且样本质量的好坏对结果影响巨大,如果样本没有处理好,再优秀的机器学习分类算法都是零. 今年3 ...
- 【从零学习openCV】IOS7下的人脸检測
前言: 人脸检測与识别一直是计算机视觉领域一大热门研究方向,并且也从安全监控等工业级的应用扩展到了手机移动端的app,总之随着人脸识别技术获得突破,其应用前景和市场价值都是不可估量的,眼下在学习ope ...
- OpenCV人脸检測(完整源代码+思路)
本博文IDE为vs2013 OpenCV2.49 话不多说,先看视频演示(20S演示): 例如以下: https://v.youku.com/v_show/id_XMjYzMzkxMTYyMA==.h ...
- OpenFace库(Tadas Baltrusaitis)中基于Haar Cascade Classifiers进行人脸检測的測试代码
Tadas Baltrusaitis的OpenFace是一个开源的面部行为分析工具.它的源代码能够从 https://github.com/TadasBaltrusaitis/OpenFace 下载. ...
- 基于QT和OpenCV的人脸检測识别系统(1)
人脸识别分为两大步骤 1.人脸检測 这个是首要实现的.你得实现人脸显示的时候把人脸框出来,当然算法非常多,另一些人眼检測鼻子检測什么的 主要用的是这个 const char *faceCascadeF ...
- Matlab人脸检測方法(Face Parts Detection)具体解释
今天同学让我帮忙制作一个人脸表情识别的样本库,当中主要是对人脸进行裁剪,这里用到了一个相对较新的Matlab人脸检測方法Face Parts Detection.网上百度了一下发现关于Matlab人脸 ...
随机推荐
- BZOJ 1225: [HNOI2001] 求正整数( dfs + 高精度 )
15 < log250000 < 16, 所以不会选超过16个质数, 然后暴力去跑dfs, 高精度计算最后答案.. ------------------------------------ ...
- 关于Ubuntu远程ssh连接失败的问题
在做机器人项目的时候,用的是Ubuntu的linux,跟之前的CentOS的操作命令有一点差别,就比如防火墙的名字,在Ubuntu系统中叫什么ufw,真是有点不好接受. 为了能模拟环境,我又弄了一台电 ...
- 深入浅出—JAVA(1)
1.基本概念 JAVA的工作方式 编写源代码文件--用编译器运行源代码(javac)--编译器会产出字节码--通过JAVA虚拟机读取与执行字节码(jvm). JAVA的程序结构 什么是源文件? 源文件 ...
- SQL Identity自增列清零方法
1.使用DBCC控制台命令: dbcc checkident(表名,RESEED,0) 2.truncate table 也可将当前标识值清零 但当有外键等约束时,无法truncate表 可以先禁用外 ...
- hibernate 数据关联一对一 3.2
第一种一对一 person和card,card的id即作为主键,又作为外键 // 各村对方的一个对象 public class Person { private Integer id; privat ...
- 利用Mono.Cecil动态修改程序集来破解商业组件(仅用于研究学习)
原文 利用Mono.Cecil动态修改程序集来破解商业组件(仅用于研究学习) Mono.Cecil是一个强大的MSIL的注入工具,利用它可以实现动态创建程序集,也可以实现拦截器横向切入动态方法,甚至还 ...
- 雪佛兰Suburban_百度百科
雪佛兰Suburban_百度百科 雪佛兰Suburban
- linux之文本编辑器
[目标] 管理员在进行系统操作的时候,不可避免地会对文本进行修改,如进行各种服务程序配置文件的修改,使程序对用户提供不同的服务效果.在本章我们向大家介绍Linux上常见的编辑器ed.vi.emacs, ...
- linux下磁盘分区
转自于:http://pengyl.blog.51cto.com/5591604/1193963 命令:fdisk 功能:查看磁盘使用情况和分割磁盘 使用方法: 一.在 ...
- sqlserver 分页查询总结
sqlserver2008不支持关键字limit ,所以它的分页sql查询语句将不能用mysql的方式进行,幸好sqlserver2008提供了top,rownumber等关键字,这样就能通过这几个关 ...