在OpenCV中,人脸检测也是其热门应用之一。在OpenCV的特征检测专题就详细介绍了人脸检测的原理——通过Haar特征来识别是否为人脸。Haar特征检测原理与Haar特征分类器的训练放到下一篇《【OpenCV入门指南】第十四篇 Haartraining》来讲,本篇主要介绍如何在OpenCV中使用Haar特征分类器来对图像中的人脸进行检测和识别。下面将分成五步来详细示范如何在OpenCV中进行人脸识别:
一.人脸的Haar特征分类器是什么
二.在哪找人脸的Haar特征分类器
三.怎么用人脸的Haar特征分类器
四.人脸识别示例代码
五.人脸识别程序运行结果
一.人脸的Haar特征分类器是什么
人脸的Haar特征分类器就是一个XML文件,该文件中会描述人脸的Haar特征值。当然Haar特征的用途可不止可以用来描述人脸这一种,用来描述眼睛,嘴唇或是其它物体也是可以的。
二.在哪找人脸的Haar特征分类器
OpenCV有已经自带了人脸的Haar特征分类器。OpenCV安装目录中的\data\ haarcascades目录下的haarcascade_frontalface_alt.xml与haarcascade_frontalface_alt2.xml都是用来检测人脸的Haar分类器。这个haarcascades目录下还有人的全身,眼睛,嘴唇的Haar分类器。读者可以仿照本方的例子来试验下效果看看。

三.怎么用人脸的Haar特征分类器
CascadeClassifier类
class CascadeClassifier
用于检测物体的级联分类器类。
CascadeClassifier::CascadeClassifier
从一个文件读取分类器。
C++: CascadeClassifier:: CascadeClassifier (const string& filename )
参数 filename – 所要读取分类器文件的文件名 CascadeClassifier::empty
检查分类器是否已经载入。
C++: bool CascadeClassifier:: empty ( ) const
CascadeClassifier::load
从一个文件读取分类器。
C++: bool CascadeClassifier:: load (const string& filename )
参数 filename – 所要读取分类器文件的文件名。文件可以是旧版的HAAR分类器模型也可以是新版的分类器模型。 CascadeClassifier::read
读取一个文件存储节点的分类器。
C++: bool CascadeClassifier::read(const FileNode& node)
CascadeClassifier::detectMultiScale
对不同大小的输入图像进行物体识别,并返回一个识别到的物体的矩阵列表。
C++: void CascadeClassifier:: detectMultiScale (const Mat& image, vector<Rect>& objects, double scaleFactor=1.1, int minNeighbors=3, int flags=0, Size minSize=Size(), Size maxSize=Size() )
参数
- image – 需要检测的 CV_8U 输入矩阵。
- objects – 输出vector载体容器用于保存被识别的物体矩阵。
- scaleFactor – 指定每张图片的缩小比例的参数。
- minNeighbors – 指定每个候选矩阵至少包含的邻近元素个数。
- flags – 与旧版级联分类器模型函数cvHaarDetectObjects的flags相同. 此参数不被用于新版模型。
- minSize – 最小可能的对象的大小,小于的对象将被忽略。
- maxSize – 最大可能的对象的大小,大于的对象将被忽略。
CascadeClassifier::setImage
设置被用于检测的图像。
C++: bool CascadeClassifier:: setImage (Ptr<FeatureEvaluator>& feval, const Mat& image )
参数
- feval – 用于特征计算的特征求值程序的指针。
- image – 需要进行特征检测的 CV_8U 输入矩阵。
这个函数将在每张图片中被 CascadeClassifier::detectMultiScale() 自动调用。 但如果你想在不同位置手动使用 CascadeClassifier::runAt(),你需要先调用该函数,使得图像被积分计算。
CascadeClassifier::runAt
在指定点运行检测。
C++: int CascadeClassifier:: runAt (Ptr<FeatureEvaluator>& feval, Point pt, double& weight )
参数 feval – 用于特征计算的特征求值程序。
pt – 指定检测窗口左上角的点。窗口的大小和检测的图片大小一致。
如果级联分类器检测到给定的位置中的一个对象,该函数返回1。否则,它会返回已被否决的候选区域在哪个阶段的否定的指数。
使用CascadeClassifier::setImage() 设置图像的检测工作。
四.人脸识别示例代码
#include "opencv2/core/core.hpp"
#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;
//屏蔽窗口
#pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"")
//需要载入的级联分类器文件
string face_cascade_name = "D:/opencv/opencv/data/haarcascades/haarcascade_frontalface_alt.xml";
//级联分类器类
CascadeClassifier face_cascade;
string window_name = "人脸识别";
void detectAndDisplay( Mat frame );
int main(){
Mat image = imread("c:/1.jpg");
if(!image.data ){
printf("[error] 没有图片\n");
return -1;
}
//载入级联分类器,并判断是否载入成功,如果不成功则打印提示
if( !face_cascade.load( face_cascade_name ) ){
printf("[error] 无法加载级联分类器文件!\n");
return -1;
}
detectAndDisplay(image);
waitKey(0);
}
void detectAndDisplay( Mat frame ){
std::vector<Rect> faces;
Mat frame_gray;
//将frame转换成灰度图,输出到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 );
}
imshow( window_name, frame );
}
识别结果:
可以成功识别人脸,
嗯。。换成动漫图片试试。。
无法识别。。原因可能是动漫人物的五官和现实人脸不太一致
2D动漫图不行,那么3D呢?
成功识别了,哈哈