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自带了很多中对应目标的训练文件,如下图所示,根据自己的检测需求,添加相应的文件及检测代码即可完成目标检测。
????~~感谢阅读????