天天看点

OpenCV人脸检测与人脸识别

OpenCV人脸检测与人脸识别

tkorays(http://blog.csdn.net/tkorays)

成为领袖,而不是依赖别人的指挥。

        用OpenCV做人脸检测与人脸识别是一件比较简单的事情,因为OpenCV的库已经为我们做了很多工作,我们甚至不需要太了解原理,调用就行了。

        注意,人脸检测(Detection)和人脸识别(Recognition)不是同一个概念。所谓“检测”是将一张图片或视频的一帧里的人脸找出来,只是找出,并不需要知道他(她)是谁。而人脸“识别”,重在识别出人脸是谁。因此,人脸识别过程中常常是先找出人脸,再去判断人脸属于谁的。

        这篇博客我们使我们的代码尽量简化,能使读者一看就会。接下来,我们就一步步来介绍吧。

人脸检测

准备素材

        首先,我们准备好素材,找一些包含人脸的图片,这里我们随便拍几张就可以了。

        当然有很多人脸库可以利用,CSDN上有篇Blog介绍了一些人脸库,可以直接下载用:http://blog.csdn.net/onlyyouandme/article/details/5596915。

检测原理

        这里我们使用OpenCV的级联(Cascade)分类器来做人脸检测。所谓级联分类器,即将多个弱分类器组合起来得到一个性能比较好的分类器。如果你学过机器学习,那么你对这个肯定不会陌生。

        既然是分类器,首先肯定是要学习的,这里我们不需要做这一步的,因为OpenCV已经为我们训练好了人脸的分类器,我们要做的是加载这个级联分类器分类器文件。当然,级联分类器不止是做人脸检测的,你还可以使用它来检测其他物体,详情可以参考OpenCV官方教程“级联分类器训练”:http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/user_guide/ug_traincascade.html。

        主要使用的是CascadeClassifier这个类,以及load、detectMultiScale函数。

        首先加载已经训练好的分类器,参数保存在一个文件里,如OpenCV提供的用于人脸检测的分类器文件haarcascade_frontalface_default.xml等,这些文件可以在OpenCV安装文件的data目录里面找到。

        然后传入图片检测,得到检测结果(包含人脸的一个矩形区域)。

代码参考

/*
 * 一个最简单的人脸检测实现
 * @author tkorays<[email protected]>
 */

// 静态连接库包含
// 可以从 http://github.com/tkorays/cxxlib 获取
#include "../cxxlib/cv_lib.h" 
#pragma comment(lib, cvLIB("core"))
#pragma comment(lib, cvLIB("highgui"))
#pragma comment(lib, cvLIB("imgproc"))
#pragma comment(lib, cvLIB("objdetect"))
// -----------------------------------------

#include <string>
#include <iostream>
#include <opencv2\core\core.hpp>
#include <opencv2\highgui\highgui.hpp>
#include <opencv2\imgproc\imgproc.hpp>
#include <opencv2\objdetect\objdetect.hpp>
using namespace std;
using namespace cv;

#define FACE_CASCADE_FILE "E:/haarcascade_frontalface_default.xml"
#define FACE_IMG_FILE "E:/1.jpg"

int main() {
	Mat img = imread(FACE_IMG_FILE,CV_LOAD_IMAGE_GRAYSCALE); // 读取为灰度图片
	vector<Rect> result;
	CascadeClassifier face_detection;
	face_detection.load(FACE_CASCADE_FILE); // 加载级联分类器
	// 检测人脸,参数说明:
	// (原始图片,结果,尺度因子,最小邻居数,检测方法,最小检测窗口大小)
	face_detection.detectMultiScale(img, result, 1.1, 2, 0 | CV_HAAR_SCALE_IMAGE, cv::Size(30, 30));
	// 看检测出人脸的个数,人脸在图片中位置保存在vector的每个Rect中
	cout << "检测出人脸数: " << result.size() << endl;
	return 0;
}
           

人脸识别

准备素材

        人脸识别要准备的素材要稍微多点了,因为这里面我们要对分类器进行训练了。OpenCV并没有提供识别张三和李四人脸的分类器数据,我们需要自己对分类器训练,让它对不同人脸进行分类。

        这里我们只识别两个人,不妨每个人脸提供5张照片吧,要提高识别精度你可以多提供一些照片,但是训练时间也就变长了。

        人脸图片要求同样大小,只包括人脸部分,不包括其他部分。这个你可以使用OpenCV来做,也可以用一些截图工具(记住要同样大小的)。

OpenCV人脸检测与人脸识别

图1 人脸

识别原理

        原理,这里面没有什么可以多说的,如果真的要说会说很多。

       我们用到的主要就是FaceRecognizer这个类,这个类没有构造函数,必须通过函数调用来初始化。用于初始化的有三个函数:

OpenCV人脸检测与人脸识别

图2 人脸识别函数

        Create[Eigen|Fisher|LBPH]FaceRecognizer,三个函数对应着三种识别方法,如果你了解模式识别之类的东西,那你肯定知道他们是什么,如果不了解也没关系,除非你要深入研究,否则这里会用就可以了。

        然后就是训练与识别了,详细信息见代码。

代码参考

/*
* 一个最简单的人脸识别实现
* @author tkorays<[email protected]>
*/

// 静态连接库包含
// 可以从 http://github.com/tkorays/cxxlib 获取
#include "../cxxlib/cv_lib.h" 
#pragma comment(lib, cvLIB("core"))
#pragma comment(lib, cvLIB("contrib"))
#pragma comment(lib, cvLIB("highgui"))
#pragma comment(lib, cvLIB("imgproc"))
#pragma comment(lib, cvLIB("objdetect"))
// -----------------------------------------

#include <string>
#include <iostream>
#include <sstream>
#include <opencv2\core\core.hpp>
#include <opencv2\contrib\contrib.hpp>
#include <opencv2\highgui\highgui.hpp>
#include <opencv2\imgproc\imgproc.hpp>
#include <opencv2\objdetect\objdetect.hpp>
using namespace std;
using namespace cv;
string FACE_FILE_PATH = "E:/BigData/face_data/";

int main() {
	// 准备数据
	vector<Mat> faces;
	vector<int> labels;
	stringstream ss;
	string s_index;
	// 读取两个人的人脸数据
	// 特征脸以及fisher方法要求为灰度
	for (size_t i = 0; i < 5; i++) {
		ss << i;
		ss >> s_index;
		faces.push_back(imread(FACE_FILE_PATH + "PEOPLE_1/small/" + s_index + ".jpg",CV_LOAD_IMAGE_GRAYSCALE));
		labels.push_back(1);
	}
	for (size_t i = 0; i < 5; i++) {
		ss << i;
		ss >> s_index;
		faces.push_back(imread(FACE_FILE_PATH + "PEOPLE_2/small/" + s_index + ".jpg", CV_LOAD_IMAGE_GRAYSCALE));
		labels.push_back(2);
	}
	// --------------------------------------------------------------------------
	// 训练
	// 创建人脸识别类,这里可以选择特征脸,fisher,以及LBPH这三种方法
	// createEigenFaceRecognizer,createFisherFaceRecognizer,createLBPHFaceRecognizer
	Ptr<FaceRecognizer> face_recog = createEigenFaceRecognizer(20);
	face_recog->train(faces, labels); // 传入人脸图片以及标签
	int face_id = face_recog->predict(imread(FACE_FILE_PATH + "PEOPLE_1/small/" + "6.jpg", CV_LOAD_IMAGE_GRAYSCALE));
	// 识别
	cout << face_id << endl;

	return 0;
}
           

         注意,这里我们训练完后可以将训练好的一些参数保存起来(FaceRecognizer::save),以便下次使用不要再加载图片训练,而是像上面的级联分类器一样直接加载xml文件就可以工作了。

建议

        有不会用的函数不妨去OpenCV论坛的文档上去搜索,本博客只能让你入门,要深入研究还需要自己去挖掘:http://www.opencv.org.cn/opencvdoc/2.3.2/html/index.html

OpenCV人脸检测与人脸识别

图3 学会搜索

By tkorays(http://blog.csdn.net/tkorays)