Haar+adaboost人脸识别 easy code

1. 代码流程

    (1). 先将haar训练好的特征文件(xml)加载进来,这里识别的是图片中的人脸(**face**.xml)和眼睛(**eye**.xml)训练好的分类器, 使用faceDetector.load即可完成

    (2). 然后计算图片中的haar特征,一般用积分图的方法计算14种haar特征

    (3). 最后将得到的特征跟已经加载的.xml中的特征比较进行判据,这里使用的是adaboost集成分类器,最后得到最终判据。(2)和(3)均可以在faceDetector.detectMultiScale一次计算完成。

    (4). 计算得到face或者eye都保存在长方形的数组中,使用rectangle绘制到图片上就可以看到效果。

2. 原理学习链接

    (1). haar特征是什么:  Haar特征介绍

这里个人理解要看一下积分图是怎么计算的,通过积分图中像素的周边统计值 即可以通过加减计算得到这个像素的摸一个模板的haar特征,积分图设计比较方便,它可以保存了很多我们需要的图片统计信息。

    (2). Adaboost集成分类器:  这里也有一个通俗的理解教程: Adaboost入门教程

 

3. 简单代码和结果如下(结果有一定误差,需要更精确的参数):

#include <opencv2/opencv.hpp>
#include <opencv2/face.hpp>

using namespace cv;
using namespace cv::face;
using namespace std;

int main()
{
	String haar_face_datapath = "haarcascade_frontalface_default.xml";
	String haar_eye_datapath = "etc/haarcascades/haarcascade_eye.xml";
	Mat src = imread("jiupin.jpeg");
	Mat grayImg, roiFaceGray, roiFaceColor;
	vector<Rect> faces, eyes;
	imshow("src", src);
	cout << "height : " << src.rows << " ; width : " << src.cols << endl;

	// 初始化检测器
	CascadeClassifier faceDetector;
	faceDetector.load(haar_face_datapath);
    //图片要转化成灰度图像
	cvtColor(src, grayImg, CV_BGR2GRAY);
    //进行识别
	faceDetector.detectMultiScale(grayImg, faces, 1.1, 1, 0, Size(100, 100), Size(300, 300));

    // 识别了脸区域的基础上进行眼睛识别
	faceDetector.load(haar_eye_datapath);
	for (int i = 0; i < faces.size(); i++)
	{
		rectangle(src, faces[i], Scalar(128,0,255),2);
		roiFaceGray = grayImg(faces[i]);
		roiFaceColor = src(faces[i]);
		faceDetector.detectMultiScale(roiFaceGray, eyes, 1.1, 5, 0, Size(25, 25), Size(50, 50));
		for (int j = 0; j < eyes.size(); j++)
		{
			rectangle(roiFaceColor, eyes[j], Scalar(0, 255, 255),2);
		}
	}
	imshow("result", src);
	imwrite("jiupin-result.jpeg", src);
	waitKey(0);
    return 0;
}

 

 

Haar特征计算简单示例: (这一段自己想着做的,有计算错误的大佬及时告知啊^&6, 感谢)

void calculateHaar(Mat src)
{
	//计算积分图
	Mat grayImg;
	cvtColor(src, grayImg, CV_BGR2GRAY);
	// normalize(grayImg, grayImg, 0, 255, NORM_MINMAX, CV_8UC1); //思考一下这里要不要添加
	imshow("grayImg", grayImg);
	for (int i = 0; i < grayImg.rows; i++)
	{
		for (int j = 0; j < grayImg.cols; j++)
		{
			grayImg.at<uchar>(i, j) = 255 - grayImg.at<uchar>(i, j);
		}
	}
	Mat integImg(grayImg.size(), CV_32SC1);
	Mat haarImg01(grayImg.size(), CV_32SC1);
	Mat grayIntegImg;
	integImg.at<int>(0, 0) = grayImg.at<uchar>(0, 0);
	for (int i = 1; i < grayImg.cols; i++)
	{
		integImg.at<int>(0, i) = grayImg.at<uchar>(0, i) + integImg.at<int>(0, i - 1);
		//cout << "grayImg.cols : " << integImg.at<int>(0, i) << endl;
	}
	for (int i = 1; i < grayImg.rows; i++)
	{
		integImg.at<int>(i, 0) = grayImg.at<uchar>(i, 0) + integImg.at<int>(i - 1, 0);
		//cout << "grayImg.rows : " << integImg.at<int>(i, 0) << endl;
	}
	for (int i = 1; i < grayImg.rows; i++)
	{
		for (int j = 1; j < grayImg.cols; j++)
		{
			integImg.at<int>(i, j) = integImg.at<int>(i - 1, j) - integImg.at<int>(i - 1, j - 1) + integImg.at<int>(i, j - 1) + grayImg.at<uchar>(i, j);
		}
	}
	//cout << "grayImg first one : " << grayImg.at<uchar>(0, 0) << endl;
	//cout << "integImg first one : " << integImg.at<int>(0, 0) << endl;
	//cout << "integImg last one : " << integImg.at<int>(grayImg.rows-1, grayImg.cols-1) << endl;
	normalize(integImg, grayIntegImg, 0, 255, NORM_MINMAX, CV_8UC1);
	imshow("gray integration image", grayIntegImg);

	// 计算图片的haar特征简单模板,其他模板也可以,这里使用10 * 10 的 kernel, all * w1 - black * w2
	int kernelH = 10, kernelW = 10, min = 0, max = 0, all , black;
	
	for (int i = 0; i < grayImg.rows- kernelH; i++)
	{
		for (int j = 0; j < grayImg.cols- kernelW; j++)
		{
			all = integImg.at<int>(i + kernelH, j + kernelW) - integImg.at<int>(i, j + kernelW)
				- integImg.at<int>(i + kernelH, j) + integImg.at<int>(i, j);
			black = integImg.at<int>(i + kernelH / 2, j + kernelW) - integImg.at<int>(i, j + kernelW)
				- integImg.at<int>(i + kernelH / 2, j) + integImg.at<int>(i, j);

			haarImg01.at<int>(i, j) = all - black - black;

			if (min > haarImg01.at<int>(i, j))
			{
				min = haarImg01.at<int>(i, j); // 没有必要做,最后可以一步归一化完成
			}
			if (max < haarImg01.at<int>(i, j))
			{
				max = haarImg01.at<int>(i, j); // 没有必要做,最后可以一步归一化完成
			}
		}
	}
	cout << "min " << min << ", max : " << max << endl;
    // 这一步可以不要,但是为了把图片最后结果显示出来,不然归一化normalize的时候图片显示不出来
	for (int i = 0; i < grayImg.rows; i++)
	{
		for (int j = grayImg.cols - kernelW; j < grayImg.cols; j++)
		{
			haarImg01.at<int>(i, j) = (max + min) / 2;
		}
	}
	for (int i = grayImg.rows - kernelH; i < grayImg.rows; i++)
	{
		for (int j = 0; j < grayImg.cols; j++)
		{
			haarImg01.at<int>(i, j) = (max + min) / 2;
		}
	}
	
	normalize(haarImg01, grayIntegImg, 0, 255, NORM_MINMAX, CV_8UC1);
	imshow("gray haar image", grayIntegImg);

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值