一、选题背景
二、设计目的和意义
三、设计方案
四、特征分类器的选择
4.1 常用人脸检测的特征分类器
4.3 人脸的Haar特征分类器使用
五、设计中主要函数介绍
5.1detectMultiScale函数详解
5.2VideoCapture类
六、实验结果及总结
七、实验源代码
基于OpenCV的摄像头实时人脸检测
一、选题背景
随着计算机与数字信号处理技术的高速发展,人脸检测技术在众多领域得到广泛应用,人脸检测技术是指在视频或图像中检测出现人脸位置、大小的过程。作为人脸信息处理中的一项关键技术,人脸检测技术己经超出了其它人脸识别模式的应用范畴,在视频处理,图像处理,身份验证,安全监测等方面有着重要的应用价值。openCV是由Intel提供的一系列包括C与C++的提供计算机视觉和图像处理的开源软件包,它为视频或图像处理搭建了很好的软件平台,本实验就是基于openCV,利用Haar特征分类器设计的。一个简单的人脸检测系统,该系统能够快速、准确的检测到图像或视频中的人脸。
二、设计目的和意义
学会使用OpenCV和VS做基本的图像处理工程项目,人脸识别在图像处理中是很成熟的项目,也很有实际应用价值,
三、设计方案
实验平台:win10+VS2013+OpenCV2.4.13
下面给出OpenCV实现人脸检测的一般步骤:
1.开启摄像头
2.加载人脸检测器
3.对图片进行灰度处理(其实可以不处理,上图中原图的标题栏就是未进行灰度处理进行的检测,这里的灰度是为下节人脸识别打基础)
4.对图片进行直方图均衡化(其实可以不处理,上图中原图的标题栏就是未进行灰度处理进行的检测和灰度图是为进行均衡化识别,这里的均衡化是为下节人脸识别打基础)
5.人脸检测
四、特征分类器的选择
4.1 常用人脸检测的特征分类器
在OpenCV中主要使用两种特征进行人脸检测,即Haar特征和LBP特征;在OpenCV中,使用已经训练好的XML格式的分类器进行人脸检测。在OpenCV的安装目录下的sources文件夹里的data文件夹里可以看到下图所示的内容:
上图中文件夹的名字“haarcascades”、“hogcascades”和“lbpcascades”分别表示通过“haar”、“hog”和“lbp”三种不同的特征而训练出的分类器:即各文件夹里的文件。"haar"特征主要用于人脸检测,“hog”特征主要用于行人检测,“lbp”特征主要用于人脸识别。打开“haarcascades”文件夹,如下图所示
图中的XML文件即是我们人脸检测所需要的分类器文件。在实际使用中,推荐使用上图中被标记的“haarcascade_frontalface_alt2.xml”分类器文件,准确率和速度都比较好。
人脸的Haar特征分类器就是一个XML文件,该文件中会描述人脸的Haar特征值。当然Haar特征的用途可不止可以用来描述人脸这一种,用来描述眼睛,嘴唇或是其它物体也是可以的。
4.3 人脸的Haar特征分类器使用
使用人脸的Haar特征分类器非常之简单,直接使用cvHaarDetectObjects。下面来看看这个函数的介绍:
函数功能:检测图像中的目录
函数原型:
CVAPI(CvSeq*) cvHaarDetectObjects(
const CvArr* image,
CvHaarClassifierCascade* cascade,
CvMemStorage* storage,
double scale_factorCV_DEFAULT(1.1),
int min_neighbors CV_DEFAULT(3),
int flags CV_DEFAULT(0),
CvSize min_sizeCV_DEFAULT(cvSize(0,0)),
CvSize max_sizeCV_DEFAULT(cvSize(0,0))
);
函数说明:
第一个参数表示输入图像,尽量使用灰度图以加快检测速度。
第二个参数表示Haar特征分类器,可以用cvLoad()函数来从磁盘中加载xml文件作为Haar特征分类器。
第三个参数为CvMemStorage类型,大家应该很熟悉这个CvMemStorage类型了,《OpenCV入门指南》中很多文章都介绍过了。
第四个参数表示在前后两次相继的扫描中,搜索窗口的比例系数。默认为1.1即每次搜索窗口依次扩大10%
第五个参数表示构成检测目标的相邻矩形的最小个数(默认为3个)。如果组成检测目标的小矩形的个数和小于 min_neighbors - 1 都会被排除。如果min_neighbors 为 0, 则函数不做任何操作就返回所有的被检候选矩形框,这种设定值一般用在用户自定义对检测结果的组合程序上。
第六个参数要么使用默认值,要么使用CV_HAAR_DO_CANNY_PRUNING,如果设置为CV_HAAR_DO_CANNY_PRUNING,那么函数将会使用Canny边缘检测来排除边缘过多或过少的区域,因此这些区域通常不会是人脸所在区域。
第七个,第八个参数表示检测窗口的最小值和最大值,一般设置为默认即可。
函数返回值:
函数将返回CvSeq对象,该对象包含一系列CvRect表示检测到的人脸矩形。
五、设计中主要函数介绍
主要有以下一些函数:
5.1 detectMultiScale函数详解
cvHaarDetectObjects是opencv1中的函数,opencv2中人脸检测使用的是 detectMultiScale函数。它可以检测出图片中所有的人脸,并将人脸用vector保存各个人脸的坐标、大小(用矩形表示),函数由分类器对象调用:
void detectMultiScale(
constMat& image,
CV_OUTvector
doublescaleFactor = 1.1,
intminNeighbors = 3,
intflags = 0,
SizeminSize = Size(),
SizemaxSize = Size()
);
函数介绍:
参数1:image--待检测图片,一般为灰度图像加快检测速度;
参数2:objects--被检测物体的矩形框向量组;
参数3:scaleFactor--表示在前后两次相继的扫描中,搜索窗口的比例系数。默认为1.1即每次搜索窗口依次扩大10%;
参数4:minNeighbors--表示构成检测目标的相邻矩形的最小个数(默认为3个)。如果组成检测目标的小矩形的个数和小于 min_neighbors - 1 都会被排除。如果min_neighbors 为 0, 则函数不做任何操作就返回所有的被检候选矩形框,这种设定值一般用在用户自定义对检测结果的组合程序上;
参数5:flags--要么使用默认值,要么使用CV_HAAR_DO_CANNY_PRUNING,如果设置为CV_HAAR_DO_CANNY_PRUNING,那么函数将会使用Canny边缘检测来排除边缘过多或过少的区域,因此这些区域通常不会是人脸所在区域;flags对于新的分类器没有用(但目前的haar分类器都是旧版的,CV_HAAR_DO_CANNY_PRUNING利用Canny边缘检测器来排除一些边缘很少或者很多的图像区域,CV_HAAR_SCALE_IMAGE就是按比例正常检测,CV_HAAR_FIND_BIGGEST_OBJECT只检测最大的物体,CV_HAAR_DO_ROUGH_SEARCH只做初略检测),
参数6、7:minSize和maxSize用来限制得到的目标区域的范围。
5.2 VideoCapture类
(1)VideoCapture capture
VideoCapture类的构造函数:
C++: VideoCapture::VideoCapture()
C++: VideoCapture::VideoCapture(const string& filename)
C++: VideoCapture::VideoCapture(int device)
功能:创建一个VideoCapture类的实例,如果传入对应的参数,可以直接打开视频文件或者要调用的摄像头。
参数:
filename – 打开的视频文件名。
device – 打开的视频捕获设备id ,如果只有一个摄像头可以填0,表示打开默认的摄像头。
(2)capture.open(0)
功能:打开一个视频文件或者打开一个捕获视频的设备(也就是摄像头)
C++: bool VideoCapture::open(const string& filename)
C++: bool VideoCapture::open(int device)
参数:
filename – 打开的视频文件名。
device – 打开的视频捕获设备id ,如果只有一个摄像头可以填0,表示打开默认的摄像头。
通过对VideoCapture类的构造函数和open函数分析,可以发现opencv读入视频的方法一般有如下两种。比如读取当前目录下名为"dog.avi"的视频文件,那么这两种写法分别如下。
(1)先实例化再初始化:
VideoCapture capture;
capture.open("dog.avi");
(2)在实例化的同时进行初始化:
VideoCapture("dog.avi");
六、实验结果及总结
实验结果如下图:
本实验完成了人脸识别的代码编写,最终生成了可执行文件,检测图片如上图,可以检测出人脸,但是由于外界因素如光照、佩戴眼镜、帽子等可对检测结果造成影响,导致检测不出来,后期还需优化算法及代码。
七、实验源代码
#include
#include
#include
#include
#include
#include"opencv2/core/core.hpp" //核心模块,Opencv最基本的结构(矩阵,点,线和形状)及相关基础运算操作
using namespace cv;
using namespace std;
#define W 1920
#define H 1080
string face_cascade_name ="D:/VS2013project/Face_D_2017_1_1/haarcascade_frontalface_alt2.xml";
CascadeClassifier face_cascade; //定义级联分类器,实例化对象
int facesnum = 0; //检测的人脸数初始化
void DectectorAndDis(Mat frame)
{
Matface_gray = Mat::zeros(H, W, CV_8UC3); //Mat(行,列,类型(值))
vector
cvtColor(frame,face_gray, CV_BGR2GRAY);//RGB转化为灰度,提高检测效率
equalizeHist(face_gray,face_gray);//直方图均衡化,提高识别率
face_cascade.detectMultiScale(face_gray,faces, 1.01, 3, 0 | CV_HAAR_SCALE_IMAGE, Size(30, 30));//多尺寸检测人脸
//标记每一个检测到的人脸
for(int i = 0; i < faces.size(); i++)
{
//检测到的人脸中心点
PointCvBox2D(int(faces[i].x + faces[i].width*0.5), int(faces[i].y +faces[i].height*0.5));
//检测到的人脸画椭圆
ellipse(frame,CvBox2D, Size(int(faces[i].width*0.5), int(faces[i].height*0.5)), 0, 0, 360,Scalar(255, 0, 0), 4, 8, 0);
}
//如果检测到的人脸数有变化,改变数值并将新值显示
if(facesnum != faces.size())
{
cout<< "人脸数:" << faces.size()<< endl;
facesnum= faces.size();
}
imshow("读取视频", frame);
}
int main(int argc, char* argv[])
{
//cv::Mattest =cv::imread("E:/code/Myprojects/ConsoleApplication1/test.jpg",0);
//cv::Mattest1;
//resize(test,test, Size(W, H));
//imshow("test",test);
//cv::Canny(test,test1, 1, 3, 3);
//imshow("test1",test1);
//test.convertTo(test,CV_32SC1);
VideoCapturecapture; //视频操作类实例化
capture.open(0);//如果是笔记本,0打开的是自带的摄像头,1 打开外接的相机
Matframe = Mat::zeros(H, W, CV_8UC3);
//Matframeaftcanny = Mat::zeros(H, W, CV_8UC3);
//加载人脸检测的Haar分类器
face_cascade.load(face_cascade_name);//用load函数加载XML分类器文件
while(1)
{
capture>> frame;//视频的每帧
//cv::Canny(frame,frameaftcanny, 100, 300, 3);
//imshow("边缘检测", frameaftcanny);
DectectorAndDis(frame);//检测每帧
cv::waitKey(10);//第一个参数: 等待x ms,如果在此期间有按键按下,则立即结束并返回按下按键的
}
return0;
}