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是vs2015,Win7 64位,boost庫,其中boost是用來操作文件的,為了方便測試整個文件夾的圖像,實現語言是C++。
一、資源準備
1.從網上下載帶有人臉的圖像和不帶人臉的圖像,圖像大小沒有什么要求,我這里是壁紙網站下載的美女壁紙,如下圖:
2.找到自己安裝的OpenCV的源碼文件夾,在源碼文件下有個Data的目錄,打開目錄下的haarcascades這個文件夾,可以看到里面有官方訓練好的級聯分類器。
二、代碼實現
代碼我這里封裝了一個類,兩個方法,一個用來檢測人臉的,一個用來檢測人臉和眼睛的,然后在main里調用。
1.類聲明部分
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.我用的分類器和圖像下載地址:https://download.csdn.net/download/matt45m/11070191 。
5.關于整個工程的源碼,運行程序時的bug,或者有如何優化代碼的想法都可以加這個群(487350510)互相討論學習。
總結
以上是生活随笔為你收集整理的OpenCV3实现人脸识别(一)——基于OpenCV3级联分类器实现人脸检测与眼睛检测的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: windows7 下vs2015使用op
- 下一篇: Visual Studio 2015 编