OpenCV3实现人脸识别(一)——基于OpenCV3级联分类器实现人脸检测与眼睛检测
前言
1.OpenCV官方訓(xùn)練好的人臉和眼睛的級(jí)聯(lián)分類器,3.30的版本都放在opencv\sources\data這個(gè)文件夾下,在OpenCV這個(gè)文件夾中,主要有 Haar特征 和 LBP特征進(jìn)行人臉檢測(cè),其中“l(fā)bpcascades”,“haarcascades”,“hogcascades”,這三個(gè)文件夾,分別放表示通過(guò)“haar”、“hog”和“l(fā)bp”三種不同的特征而訓(xùn)練出的分類器。"haar"特征主要用于人臉檢測(cè),“hog”特征主要用于行人檢測(cè),“l(fā)bp”特征主要用于人臉識(shí)別。
2.人臉檢測(cè)用的“haarcascades”文件夾里有檢測(cè)正臉的,檢測(cè)眼睛的,檢測(cè)嘴巴的,檢測(cè)笑臉的等幾種分類器,這里我只試了常用的人臉檢測(cè)器和眼睛的檢測(cè)器。
3.我用的是OpenCV3.30這個(gè),IDE是vs2015,Win7 64位,boost庫(kù),其中boost是用來(lái)操作文件的,為了方便測(cè)試整個(gè)文件夾的圖像,實(shí)現(xiàn)語(yǔ)言是C++。
一、資源準(zhǔn)備
1.從網(wǎng)上下載帶有人臉的圖像和不帶人臉的圖像,圖像大小沒(méi)有什么要求,我這里是壁紙網(wǎng)站下載的美女壁紙,如下圖:
2.找到自己安裝的OpenCV的源碼文件夾,在源碼文件下有個(gè)Data的目錄,打開(kāi)目錄下的haarcascades這個(gè)文件夾,可以看到里面有官方訓(xùn)練好的級(jí)聯(lián)分類器。
二、代碼實(shí)現(xiàn)
代碼我這里封裝了一個(gè)類,兩個(gè)方法,一個(gè)用來(lái)檢測(cè)人臉的,一個(gè)用來(lái)檢測(cè)人臉和眼睛的,然后在main里調(diào)用。
1.類聲明部分
2.類的實(shí)現(xiàn)文件
#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 << "請(qǐng)轉(zhuǎn)入正確的模型文件路徑!" << std::endl;exit(0);}eye_path = _eye_path;//判斷模型路徑fs::path eye_xml(eye_path);if (!fs::exists(eye_xml)){std::cout << "請(qǐng)轉(zhuǎn)入正確的模型文件路徑!" << std::endl;exit(0);}image_path = _image_path;//判斷圖像路徑fs::path src(image_path);if (!fs::exists(src)){std::cout << "傳入的圖像路徑錯(cuò)誤!" << std::endl;exit(0);} }FaceDetection::~FaceDetection() { }void FaceDetection::frontalFaceDetection() {//判斷模型是否能打開(kāi)if (!face_classifier.load(face_path)){std::cout << "模型文件無(wú)法讀取!" << 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 << "無(wú)法讀取人臉的分類文件!" << std::endl;exit(0);}if (!eye_cascader.load(eye_path)){std::cout << "無(wú)法讀取眼睛的分類文件!" << 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 << "無(wú)法打開(kāi)傳入的圖像文件!" << std::endl;exit(0);}Mat gray;//灰度化cvtColor(image, gray, COLOR_BGR2GRAY);//直方圖均衡化,用于提高圖像的質(zhì)量/*有時(shí)提高了圖像質(zhì)量之后,檢測(cè)的人臉有漏檢的現(xiàn)象*///equalizeHist(gray, gray);//存放檢測(cè)到人臉的矩形vector<Rect> faces;//開(kāi)始檢測(cè)face_classifier.detectMultiScale(gray, faces, 1.2, 3, 0, Size(24, 24));//畫出檢測(cè)到的矩形的位置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" //人臉檢測(cè)的分類器 string face_file = "E:/LIB/opencv330/opencv/sources/data/haarcascades/haarcascade_frontalface_alt.xml"; //眼睛檢測(cè)的分類器 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);//檢測(cè)人臉//face_eye.frontalFaceDetection();//檢測(cè)人臉與眼睛的face_eye.faceAndeye();system("pause");return 0; }三、測(cè)試結(jié)果
1.人臉檢測(cè),有漏檢的,也有誤檢的。
(1).有誤檢測(cè)了地方。
(2)完全成檢測(cè)到人臉。
(3)檢測(cè)不到,如果調(diào)下參數(shù)或用另一個(gè)分類能檢測(cè)到。
2.人臉與眼睛的檢測(cè)效果
(1)完全檢測(cè)到人臉和眼睛。
(2)有漏檢測(cè)和誤檢測(cè)的眼睛。
(3)有檢測(cè)不到的眼睛的。
結(jié)語(yǔ)
1.檢測(cè)結(jié)果并不理想,對(duì)檢測(cè)準(zhǔn)確率影響有環(huán)境的因素,和傳給檢測(cè)器之前的對(duì)圖像的處理,設(shè)置檢測(cè)的分類的參數(shù)等。
2.如果要在相對(duì)穩(wěn)定的環(huán)境下使用,最好的方法是使用該環(huán)境下的人臉樣品自己訓(xùn)練模型。
3.之后我會(huì)試用opencv和caffe的訓(xùn)練自己的數(shù)據(jù)模型,看是否能達(dá)到官方分類器的準(zhǔn)確率。
4.我用的分類器和圖像下載地址:https://download.csdn.net/download/matt45m/11070191 。
5.關(guān)于整個(gè)工程的源碼,運(yùn)行程序時(shí)的bug,或者有如何優(yōu)化代碼的想法都可以加這個(gè)群(487350510)互相討論學(xué)習(xí)。
總結(jié)
以上是生活随笔為你收集整理的OpenCV3实现人脸识别(一)——基于OpenCV3级联分类器实现人脸检测与眼睛检测的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: windows7 下vs2015使用op
- 下一篇: Visual Studio 2015 编