欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

OpenCV基于haar分类器算法的人脸检测实现(一)

程序员文章站 2022-07-13 10:18:46
...

近期要开展一个新项目,关于场景图像信息获取的,具体涉及到场景中人脸检测、运动目标检测以及场景中给定目标的追踪问题,后面还会涉及到信息交互的界面开发。接下来将通过写博客的方式记录项目进展(问题及解决方案)和心得。

人脸检测

人脸检测不同于人脸识别,人脸检测通俗的意思就是在获取是场景数据(图像、视频)中,将具有人脸特征的目标检测出来,但不清楚检测到的人脸是谁,只知道这可能是一张脸;人脸识别就是在检测的基础上,能够对检测到的人脸进行辨识,进而知道这个人是“张三”还是“李四”或是“鸣人”还是“佐助”。

人脸检测/识别基本步骤

1.图像采集
静态图片、视频文件、摄像头、流媒体
2.图像预处理
简化图像、滤波、灰度化、二值化
3.特征提取
HAAR、HOGLBP…
4.匹配识别
分类对比

OpenCV识别代码

人脸检测通过调用OpenCV训练的人脸模型xml文件以及调用对应的库函数,即可实现不错的检测效果。

//#include <opencv/cv.h>
//#include <opencv/highgui.h>
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>

#include "opencv2\core\core.hpp"
#include "opencv2\imgproc\imgproc.hpp"
#include"opencv2\highgui\highgui.hpp"
#include "opencv2\objdetect\objdetect.hpp"

#include<sstream>
#include<string>

#include<opencv2/opencv.hpp>
#include <opencv2/highgui/highgui_c.h>
#include<iostream>


using namespace std;
using namespace cv;
void DetectFace(Mat, Mat);
CascadeClassifier faceCascade;
CascadeClassifier face_profile_Cascade;
CascadeClassifier eyes_Cascade;
int main(int argc, char** argv) {
	VideoCapture cap(0);
	//if (!cap.open("C:\\Users\\Desktop\\faceDetect-master\\faceDetect-master\\meinv.mp4")) {
	//	cout << "摄像头打开失败!!" << endl;	
	//	return -1;
	//}

	if (!cap.isOpened())  // if not success, exit program
	{
		cout << "Cannot open the video cam" << endl;
		return -1;
	}


	//D:\\openCV410\\opencv\\sources\\data\\haarcascades_cuda\\haarcascade_profileface.xml  
	//haarcascade_frontalface_alt2
	//haarcascade_profileface
	//D:\\openCV410\\opencv\\sources\\data\\haarcascades_cuda\\haarcascade_frontalface_alt2.xml
	//D:\\openCV410\\opencv\\sources\\data\\haarcascades\\haarcascade_profileface.xml
	//D:\\openCV410\\opencv\\build\\etc\\haarcascades\\haarcascade_profileface.xml

	if (!faceCascade.load("D:\\openCV410\\opencv\\sources\\data\\haarcascades_cuda\\haarcascade_frontalface_alt2.xml")) {
		cout << "人脸检测级联分类器没找到!!" << endl;
		return -1;
	}

	if (!face_profile_Cascade.load("D:\\openCV410\\opencv\\sources\\data\\haarcascades\\haarcascade_profileface.xml")) {
		cout << "人脸检测级联分类器没找到!!" << endl;
		return -1;
	}

	if (!eyes_Cascade.load("D:\\openCV410\\opencv\\sources\\data\\haarcascades_cuda\\haarcascade_eye_tree_eyeglasses.xml")) {
		cout << "眼睛检测级联分类器没找到!!" << endl;
		return -1;
	}

	Mat img, imgGray;
	int fps = 60;
	while (true) {
		cap >> img;
		cvtColor(img, imgGray, CV_BGR2GRAY);
		equalizeHist(imgGray, imgGray);//直方图均匀化
		DetectFace(img, imgGray);
		waitKey(1000 / fps);
	}
	return 0;
}

void DetectFace(Mat img, Mat imgGray) {
	namedWindow("src", WINDOW_AUTOSIZE);
	vector<Rect> faces,profilefaces,eyes;
	faceCascade.detectMultiScale(imgGray, faces, 1.2, 5, 0, Size(30, 30));
	for (auto b : faces) {
		cout << "输出一张正面人脸位置:(x,y):" << "(" << b.x << "," << b.y << ") , (width,height):(" << b.width << "," << b.height << ")" << endl;
	}
	if (faces.size() > 0) {
		for (size_t i = 0; i < faces.size(); i++) {
			putText(img, "find_front!", cvPoint(faces[i].x, faces[i].y - 10), FONT_HERSHEY_PLAIN, 1.0, Scalar(0, 0, 255));

			//画矩形框,给定矩形框左上角的一个点,设定宽和高,最终确定矩形框的范围
			rectangle(img, Point(faces[i].x, faces[i].y), Point(faces[i].x + faces[i].width, faces[i].y + faces[i].height), Scalar(0, 0, 255), 1, 8);
			cout << faces[i] << endl;
			//将人脸从灰度图中抠出来
			Mat face_ = imgGray(faces[i]);
			//eyes_Cascade.detectMultiScale(face_, eyes, 1.2, 2, 0, Size(30, 30));
			//for (size_t j = 0; j < eyes.size(); j++) {
			//	Point eye_center(faces[i].x + eyes[j].x + eyes[j].width / 2, faces[i].y + eyes[j].y + eyes[j].height / 2);
			//	int radius = cvRound((eyes[j].width + eyes[j].height)*0.25);
			//	circle(img, eye_center, radius, Scalar(65, 105, 255), 4, 8, 0);
			//}
		}
	}
	//侧脸
	face_profile_Cascade.detectMultiScale(imgGray, profilefaces, 1.2, 5, 0, Size(30, 30));
	for (auto b : profilefaces) {
		cout << "输出一张侧面人脸位置:(x,y):" << "(" << b.x << "," << b.y << ") , (width,height):(" << b.width << "," << b.height << ")" << endl;
	}
	if (profilefaces.size() > 0) {
		for (size_t i = 0; i < profilefaces.size(); i++) {
			putText(img, "find_profile!", cvPoint(profilefaces[i].x, profilefaces[i].y - 10), FONT_HERSHEY_PLAIN, 1.0, Scalar(255, 0, 0));

			rectangle(img, Point(profilefaces[i].x, profilefaces[i].y), Point(profilefaces[i].x + profilefaces[i].width, profilefaces[i].y + profilefaces[i].height), Scalar(255, 0, 0), 1, 8);
			cout << profilefaces[i] << endl;
			//将人脸从灰度图中抠出来
			Mat face_ = imgGray(profilefaces[i]);
			//eyes_Cascade.detectMultiScale(face_, eyes, 1.2, 2, 0, Size(30, 30));
			//for (size_t j = 0; j < eyes.size(); j++) {
			//	Point eye_center(profilefaces[i].x + eyes[j].x + eyes[j].width / 2, profilefaces[i].y + eyes[j].y + eyes[j].height / 2);
			//	int radius = cvRound((eyes[j].width + eyes[j].height)*0.25);
			//	circle(img, eye_center, radius, Scalar(65, 105, 255), 4, 8, 0);
			//}
		}
	}

	imshow("src", img);
}

haarcascade_frontalface_alt2.xml 正脸检测训练文件
haarcascade_profileface.xml 侧脸检测训练文件

类似于以上训练文件,在安装OpenCV时,就已经配置到安装目录下的某个位置。我们在使用时,直接去调用对应目录下的文件即可。需要注意的是,文件最好使用OpenCV安装目录下的文件,不要自行下载相应的xml文件,然后再去调用下载后的文件目录下的文件,这样保证不会出现文件版本不一造成加载错误。

检测效果

正面检测:
OpenCV基于haar分类器算法的人脸检测实现(一)
侧脸检测:
OpenCV基于haar分类器算法的人脸检测实现(一)
在Opencv自带了很多中对应目标的训练文件,如下图所示,根据自己的检测需求,添加相应的文件及检测代码即可完成目标检测。
OpenCV基于haar分类器算法的人脸检测实现(一)
????~~感谢阅读????