人臉識別之一影象採集及人臉庫的建立
人臉識別之第一步,人臉庫的建立。
在官方文件中,提供一個人臉庫的下載,可以下載回來看看人家的是什麼格式的。
我們選擇AT&T人臉庫下載的下載:http://www.cl.cam.ac.uk/research/dtg/attarchive/facedatabase.html
AT&T Facedatabase又稱ORL人臉資料庫,40個人,每人10張照片。照片在不同時間、不同光照、不同表情(睜眼閉眼、笑或者不笑)、不同人臉細節(戴眼鏡或者不戴眼鏡)下采集。所有的影象都在一個黑暗均勻的背景下采集的,正面豎直人臉(有些有有輕微旋轉)。
下載回來的是壓縮包,先解壓得到orl_faces資料夾,資料夾下有40個資料夾,命名從“s1”~"s40",每個資料夾放的是同一人的照片,裡面有10張人臉照。
但都是 .pgm 格式的 92 x 112 圖片,在windows下打不開,可在linux下開啟,如下:
看一遍官方提供的人臉庫,大概知道如何存放、處理圖片。後面參考官方方法建立自己的圖片即可。
廢話少說,馬上行動。
一、實現步驟與方法
思路很清晰,如下:
1、開啟攝像頭,採集影象;
2、載入人臉分類器;
3、人臉檢測,並框出人臉部分並顯示影象;
4、在檢測到人臉條件下,一鍵拍照;
5、對人臉部分,調整大小並寫成指定目錄下的影象檔案;
二、實現程式碼
你可自己寫程式碼實現這功能,亦可直接COPY程式碼來用,這只是輔助功能而已。
程式碼如下:
#include "opencv2/objdetect.hpp" #include "opencv2/core.hpp" #include "opencv2/imgproc.hpp" #include "opencv2/highgui.hpp" #include <iostream> #include <stdio.h> using namespace cv; using namespace std; int resize_save(Mat& faceIn, char *path, int FaceSeq); int get_face(char *path); int main(int argc, char *argv[]) { if(argc != 2) { printf("usage: %s <path>\n", argv[0]); return -1; } get_face(argv[1]); return 0; } int get_face(char *path) { CascadeClassifier face_cascade; VideoCapture camera; char key = 0; Mat frame; int ret = 0; int faceNum = 1; vector<Rect> faces; Mat img_gray; Mat faceImg; camera.open(0); // 開啟攝像頭 if(!camera.isOpened()) { cout << "open camera failed. " << endl; return -1; } cout << "open camera succeed. " << endl; // 載入人臉分類器 ret = face_cascade.load("/root/library/opencv/opencv-3.2.0/data/haarcascades/haarcascade_frontalface_alt2.xml"); if( !ret ) { printf("load xml failed.\n"); return -1; } cout << "load xml succeed. " << endl; while (1) { camera >> frame; if(frame.empty()) { continue; } cvtColor(frame, img_gray, COLOR_BGR2GRAY); equalizeHist(img_gray, img_gray); // 檢測目標 face_cascade.detectMultiScale(img_gray, faces, 1.1, 3, 0, Size(50, 50)); for(size_t i =0; i<faces.size(); i++) { /* 畫矩形框出目標 */ rectangle(frame, Point(faces[0].x, faces[0].y), Point(faces[0].x + faces[0].width, faces[0].y + faces[0].height), Scalar(0, 255, 0), 1, 8); } imshow("camera", frame); // 顯示 key = waitKey(1); // 顯示後要新增延時 switch (key) { case 'p': // 按 P 一鍵拍臉 // 只限定檢測一個人臉 if(faces.size() == 1) { faceImg = frame(faces[0]); ret = resize_save(faceImg, path, faceNum); // 調整大小及儲存 if(ret == 0) { printf("resize_save success.\n"); faceNum ++; } } break; case 27: // 按 Esc 鍵退出 cout << "Esc..." << endl; return 0; default: break; } } } int resize_save(Mat& faceIn, char *path, int FaceSeq) { string strName; Mat image; Mat faceOut; int ret; if(faceIn.empty()) { printf("faceIn is empty.\n"); return -1; } if (faceIn.cols > 100) { resize(faceIn, faceOut, Size(92, 112)); // 調整大小,這裡選擇與官方人臉庫圖片大小相容 strName = format("%s/%d.jpg", path, FaceSeq); // 先要建立資料夾 ret = imwrite(strName, faceOut); // 檔名字尾要正確 .jpg .bmp ... if(ret == false) // 出現錯誤,請檢測檔名字尾、檔案路徑是否存在 { printf("imwrite failed!\n"); printf("please check filename[%s] is legal ?!\n", strName.c_str()); return -1; } imshow(strName, faceOut); } waitKey(20); return 0; }
操作說明:
編譯成功後,執行可執行檔案須提供引數,該引數為存放人臉影象的目錄,且須為已有目錄。
按“P”鍵一鍵拍照取臉儲存,按“Esc”鍵退出。
若執行 imwrite() 函式失敗時,請檢查引數目錄是否存在,要儲存的檔名字尾是否合法。
此程式儲存為 .jpg 格式,命名採用編號法由1遞增。
三、執行示例
$ ./get_face abc
四、構建人臉庫
按照以上步驟,可得到單個人的多張人臉照,人臉庫由多個人(>=2)的人臉照組成,如下:
人臉庫須大於或等於2人,這裡暫收集5人照片。
參照官方人臉庫,從“s1”~"s4"命名,每個資料夾放著同一個人的多張人臉照。
能力有限,歡迎指出不足,感激不盡!
人臉識別之第一步,人臉庫的建立。