Linux系統下利用OpenCV實現人臉檢測和基於LBPH演算法的人臉識別
本文主要的目的是進行人臉檢測和人臉識別。實驗環境為Ubuntu16.04 LTS虛擬機器版,技術為OpenCV,語言為c++。其中人臉檢測的主要過程是從一張圖片中檢測出人臉可以是一個或者是多個,然後用矩形或者圓形線圈標註出來。人臉識別是基於LBPH演算法實現,首先給定一張帶有人臉的圖片,需要提取出人臉,然後在一個圖片集中進行逐個的匹配將相似度最大的一個作為匹配結果,並將此人名字列印在圖片上。程式編譯和執行的工具是cmake。
下面是程式的程式碼和相關介紹。
1.原始碼
test.cpp檔案
//標頭檔案 #include <dirent.h> #include<opencv2/highgui/highgui.hpp> #include<opencv2/contrib/contrib.hpp> #include<opencv2/imgproc/imgproc.hpp> #include<opencv2/objdetect/objdetect.hpp> #include<iostream> #include<io.h> //名稱空間 using namespace std; using namespace cv; CascadeClassifier faceDetect; //人臉檢測物件 //函式宣告 vector<Rect> FaceDetector(Mat img);//檢測人臉,並返回人臉區域 void DrawFace(Mat img, vector<Rect> faces);//將人臉標註出來 void GetFilesNameAndLabels(char *path, vector<string>& filesName,vector<string>& labelsInfo); int main() { //變數 Mat frame; Mat src; Mat facePic; Mat recogPic; vector<Rect> faces; vector<string> filesName; char *path = "./smalljpgset"; string picture; string pic; namedWindow("1"); vector<Mat> trainPic;//訓練圖片 vector<int> labels;//與訓練圖片一一對應的標籤 int result; vector<string> labelsInfo; faceDetect.load("./models/haarcascade_frontalface_alt2.xml"); Ptr<FaceRecognizer> LBPHRecog = createLBPHFaceRecognizer(1, 8 ,3, 3, 10); //載入人臉庫 GetFilesNameAndLabels(path, filesName,labelsInfo); cout <<filesName.size()<< endl; for(int i = 0; i<filesName.size(); i++) { pic = filesName[i]; src = imread(pic); cvtColor(src, src, CV_RGB2GRAY); trainPic.push_back(src); labels.push_back(i); } LBPHRecog->train(trainPic, labels); //LBP人臉識別訓練函式 picture="./picture/Osama_bin_Laden_0001.jpg"; frame=imread(picture); recogPic = Mat::zeros(200, 200, frame.type()); faces = FaceDetector(frame); DrawFace(frame, faces); imshow("1",frame); waitKey(0); for(size_t i = 0; i<faces.size(); i++) { facePic = frame(Rect(faces[i])); resize(facePic, recogPic, recogPic.size()); cvtColor(recogPic, recogPic, CV_RGB2GRAY); result = LBPHRecog->predict(recogPic);//進行識別 //將識別結果顯示在實時畫面上 if(result ==-1) { putText(frame, "unknow", Point(faces[i].x, faces[i].y), 3, 0.5, Scalar(0, 255, 255), 1); } else putText(frame, labelsInfo[result], Point(faces[i].x, faces[i].y), 3, 0.5, Scalar(255, 0, 0) ,1,5); imshow("1", frame); waitKey(0); } return 0; } vector<Rect> FaceDetector(Mat img) { Mat src = Mat::zeros(240, 320, img.type()); vector<Rect> faces; cvtColor(img, img, CV_RGB2GRAY); resize(img, src, src.size()); faceDetect.detectMultiScale(img, faces, 1.2, 6, 0,Size(30,30)); cout <<faces.size()<< endl; return faces; } void DrawFace(Mat img, vector<Rect> faces) { for(size_t num = 0; num<faces.size(); num++) { rectangle(img, Point(faces[num].x, faces[num].y), Point(faces[num].x + faces[num].width, faces[num].y + faces[num].height), Scalar(0, 255, 0), 1, 8); } } void GetFilesNameAndLabels(char *path, vector<string>& filesName,vector<string>& labelsInfo) { string p; DIR * dir; struct dirent * ptr; dir = opendir(path); //開啟一個目錄 while((ptr = readdir(dir)) != NULL) //迴圈讀取目錄資料 { if(ptr->d_name[0] != '.')//d_name是一個char陣列,存放當前遍歷到的檔名 { filesName.push_back(p.assign(path).append("/").append(ptr->d_name)); labelsInfo.push_back(ptr->d_name); cout <<p << endl; } } closedir(dir);//關閉目錄指標 }
CmakeLists.txt
cmake_minimum_required(VERSION 2.8)
project( DisplayImage )
find_package( OpenCV REQUIRED )
add_executable( DisplayImage test.cpp )
target_link_libraries( DisplayImage ${OpenCV_LIBS} )
cmake會用到此檔案。
2.編譯與執行
執行如下命令
cmake .
make
之後會生成名字為DisplayImage的可執行檔案,然後執行
./DisplayImage
3.執行效果
人臉檢測圖:
人臉識別圖:
人名資訊圖:
程式會輸出以上資訊。當程式彈窗之後,關掉之後才能繼續彈窗。圖三中的11和1分別代表圖片集中的人數和人臉檢測圖片中的人臉數。
4.參考
http://blog.csdn.net/lsq2902101015/article/details/49717441
http://doc.okbase.net/zhaoweiwei/archive/238660.html
https://docs.opencv.org/master/db/df5/tutorial_linux_gcc_cmake.html