糖尿病康复,内容丰富有趣,生活中的好帮手!
糖尿病康复 > OpenCV3实现人脸识别(一)——基于OpenCV3级联分类器实现人脸检测与眼睛检测

OpenCV3实现人脸识别(一)——基于OpenCV3级联分类器实现人脸检测与眼睛检测

时间:2021-08-05 05:33:31

相关推荐

OpenCV3实现人脸识别(一)——基于OpenCV3级联分类器实现人脸检测与眼睛检测

前言

1.OpenCV官方训练好的人脸和眼睛的级联分类器,3.30的版本都放在opencv\sources\data这个文件夹下,在OpenCV这个文件夹中,主要有 Haar特征 和 LBP特征进行人脸检测,其中“lbpcascades”,“haarcascades”,“hogcascades”,这三个文件夹,分别放表示通过“haar”、“hog”和“lbp”三种不同的特征而训练出的分类器。"haar"特征主要用于人脸检测,“hog”特征主要用于行人检测,“lbp”特征主要用于人脸识别。

2.人脸检测用的“haarcascades”文件夹里有检测正脸的,检测眼睛的,检测嘴巴的,检测笑脸的等几种分类器,这里我只试了常用的人脸检测器和眼睛的检测器。

3.我用的是OpenCV3.30这个,IDE是vs,Win7 64位,boost库,其中boost是用来操作文件的,为了方便测试整个文件夹的图像,实现语言是C++。

一、资源准备

1.从网上下载带有人脸的图像和不带人脸的图像,图像大小没有什么要求,我这里是壁纸网站下载的美女壁纸,如下图:

2.找到自己安装的OpenCV的源码文件夹,在源码文件下有个Data的目录,打开目录下的haarcascades这个文件夹,可以看到里面有官方训练好的级联分类器。

二、代码实现

代码我这里封装了一个类,两个方法,一个用来检测人脸的,一个用来检测人脸和眼睛的,然后在main里调用。

1.类声明部分

#pragma once#include <opencv2/opencv.hpp>#include <opencv2\core\core.hpp>#include <opencv\highgui.h>#include <string>//boost 库(读取文件)#include<boost/filesystem.hpp>//定义一个boost库的命名空间namespace fs = boost::filesystem;using namespace std;using namespace cv;class FaceDetection{public:~FaceDetection();//人脸和眼睛的构造函数FaceDetection(string _image_path, string _face_path, string _eye_path);//检测人脸的方法void frontalFaceDetection();//检测人脸和眼睛的方法void faceAndeye();Mat eyeDetection(Mat image);Mat detection(Mat image);private://人脸检测的分类器路径string face_path;//图像路径或存放图像的路径string image_path;//眼睛的分类器路径string eye_path;CascadeClassifier face_classifier;CascadeClassifier eye_cascader;};

2.类的实现文件

#include "FaceDetection.h"FaceDetection::FaceDetection(string _image_path, string _face_path, string _eye_path){face_path = _face_path;//判断模型路径fs::path face_xml(face_path);if (!fs::exists(face_xml)){std::cout << "请转入正确的模型文件路径!" << std::endl;exit(0);}eye_path = _eye_path;//判断模型路径fs::path eye_xml(eye_path);if (!fs::exists(eye_xml)){std::cout << "请转入正确的模型文件路径!" << std::endl;exit(0);}image_path = _image_path;//判断图像路径fs::path src(image_path);if (!fs::exists(src)){std::cout << "传入的图像路径错误!" << std::endl;exit(0);}}FaceDetection::~FaceDetection(){}void FaceDetection::frontalFaceDetection(){//判断模型是否能打开if (!face_classifier.load(face_path)){std::cout << "模型文件无法读取!" << std::endl;exit(0);}//判断传入的是否是文件夹if (fs::is_directory(image_path)){fs::recursive_directory_iterator begin_iter(image_path);fs::recursive_directory_iterator end_iter;for (; begin_iter != end_iter; ++begin_iter){string file_path = begin_iter->path().string();if (!fs::is_directory(file_path)){string image_path = begin_iter->path().string();Mat src = imread(image_path);if (!src.empty()){Mat src_image = imread(image_path);Mat image = detection(src_image);imshow("detect faces", image);waitKey(30);}}}}else{Mat src_image = imread(image_path);if(!src_image.empty()){Mat image = detection(src_image);imshow("detect faces", image);waitKey(30);}}}void FaceDetection::faceAndeye(){namedWindow("face_eye", CV_WINDOW_AUTOSIZE);if (fs::is_directory(image_path)){fs::recursive_directory_iterator begin_iter(image_path);fs::recursive_directory_iterator end_iter;for (; begin_iter != end_iter; ++begin_iter){string file_path = begin_iter->path().string();if (!fs::is_directory(file_path)){string image_path = begin_iter->path().string();Mat src = imread(image_path);if (!src.empty()){Mat src_image = imread(image_path);Mat image = eyeDetection(src_image);imshow("face_eye", image);waitKey(30);}}}}else{Mat src_image = imread(image_path);if (!src_image.empty()){Mat image = eyeDetection(src_image);imshow("face_eye", image);waitKey(30);}}}Mat FaceDetection::eyeDetection(Mat frame){if (!face_classifier.load(face_path)) {std::cout << "无法读取人脸的分类文件!" << std::endl;exit(0);}if (!eye_cascader.load(eye_path)){std::cout << "无法读取眼睛的分类文件!" << std::endl;exit(0);}Mat gray;vector<Rect> faces;vector<Rect> eyes;cvtColor(frame, gray, COLOR_BGR2GRAY);equalizeHist(gray, gray);face_classifier.detectMultiScale(gray, faces, 1.2, 3, 0, Size(30, 30));for (size_t t = 0; t < faces.size(); t++) {Rect roi;roi.x = faces[static_cast<int>(t)].x;roi.y = faces[static_cast<int>(t)].y;roi.width = faces[static_cast<int>(t)].width;roi.height = faces[static_cast<int>(t)].height / 2;Mat faceROI = frame(roi);eye_cascader.detectMultiScale(faceROI, eyes, 1.2, 3, 0, Size(20, 20));for (size_t k = 0; k < eyes.size(); k++) {Rect rect;rect.x = faces[static_cast<int>(t)].x + eyes[k].x;rect.y = faces[static_cast<int>(t)].y + eyes[k].y;rect.width = eyes[k].width;rect.height = eyes[k].height;rectangle(frame, rect, Scalar(0, 0, 255), 2, 8, 0);}rectangle(frame, faces[static_cast<int>(t)], Scalar(0, 255, 0), 2, 8, 0);}return frame;}Mat FaceDetection::detection(Mat image){if (image.empty()){std::cout << "无法打开传入的图像文件!" << std::endl;exit(0);}Mat gray;//灰度化cvtColor(image, gray, COLOR_BGR2GRAY);//直方图均衡化,用于提高图像的质量/*有时提高了图像质量之后,检测的人脸有漏检的现象*///equalizeHist(gray, gray);//存放检测到人脸的矩形vector<Rect> faces;//开始检测face_classifier.detectMultiScale(gray, faces, 1.2, 3, 0, Size(24, 24));//画出检测到的矩形的位置for (size_t t = 0; t < faces.size(); t++){rectangle(image, faces[static_cast<int>(t)], Scalar(0, 0, 255), 2, 8, 0);}return image;}

3.main文件

#include "FaceDetection.h"//人脸检测的分类器string face_file = "E:/LIB/opencv330/opencv/sources/data/haarcascades/haarcascade_frontalface_alt.xml";//眼睛检测的分类器string eye_file = "E:/LIB/opencv330/opencv/sources/data/haarcascades/haarcascade_eye.xml";//图像路径或目录string image_path = "C:/Users/matt/Desktop/face/";int main(){FaceDetection face_eye(image_path,face_file,eye_file);//检测人脸//face_eye.frontalFaceDetection();//检测人脸与眼睛的face_eye.faceAndeye();system("pause");return 0;}

三、测试结果

1.人脸检测,有漏检的,也有误检的。

(1).有误检测了地方。

(2)完全成检测到人脸。

(3)检测不到,如果调下参数或用另一个分类能检测到。

2.人脸与眼睛的检测效果

(1)完全检测到人脸和眼睛。

(2)有漏检测和误检测的眼睛。

(3)有检测不到的眼睛的。

结语

1.检测结果并不理想,对检测准确率影响有环境的因素,和传给检测器之前的对图像的处理,设置检测的分类的参数等。

2.如果要在相对稳定的环境下使用,最好的方法是使用该环境下的人脸样品自己训练模型。

3.之后我会试用opencv和caffe的训练自己的数据模型,看是否能达到官方分类器的准确率。

4.我用的分类器和图像下载地址:/download/matt45m/11070191 。

5.关于整个工程的源码,运行程序时的bug,或者有如何优化代码的想法都可以加这个群(487350510)互相讨论学习。

如果觉得《OpenCV3实现人脸识别(一)——基于OpenCV3级联分类器实现人脸检测与眼睛检测》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。