參考自@星沉閣冰不語出品,轉載請注明作者和出處。
原連結:http://blog.csdn.net/xingchenbingbuyu/article/details/51386949
本人女學渣一枚研一,所有過程參考上面的大神,記錄一下我的曆程。
畢業論文将做【基于opencv的課堂點名和監控系統】,之前一直在做人臉檢測,如果各路大神有什麼好點子請在下方留言。下面開始。
人臉檢測可以利用opencv自帶的分類器,但是人臉識别就需要自己收集資料,自己訓練分類器了。opencv給出的有人臉識别的教程:Face Recognition with OpenCV。網上也可以找到中文版本的。
一、背景資料集
本次用的資料集市opencv給出的教程裡面的第一個資料集:The AT&T Facedatabase。又稱ORL人臉資料庫,40個人,每人10張照片。照片在不同時間、不同光照、不同表情(睜眼閉眼、笑或者不笑)、不同人臉細節(戴眼鏡或者不戴眼鏡)下采集。所有的圖像都在一個黑暗均勻的背景下采集的,正面豎直人臉(有些有有輕微旋轉)。
下載下傳下來之後是這樣的:
可以看到每個人一個檔案夾,每個檔案夾下是這個人的十張照片,但是不是我們熟悉的BMP或者是PNG或者是JPEG格式的,而是PGM格式的。windows7自帶的照片檢視器和畫圖軟體都不能打開這種格式的圖檔!!是以我們将用強大的imread()函數讀取,是以記得opencv文檔裡有這樣的描述:
#include<opencv2\opencv.hpp>
using namespace cv;
int main()
{
Mat img = imread("C:\\Users\\Apple\\Desktop\\ORL\\s40\\1.pgm");
imshow("1", img);
waitKey();
return ;
}
二、自己的人臉資料集
1.拍照程式
想要識别自己,單有别人的資料集還是不行的,還需要自己人臉的照片才行。這就需要我們收集自己的照片,然後和上面的那個資料集一起來訓練模型。在拿着手機自拍的過程中我想到,問什麼不寫一個程式用電腦的攝像頭自拍呢,随便還能研究下怎麼用opencv實作拍照的功能。經過一番實驗(其實還是費了好長時間),終于寫了一個拍照程式。
程式的功能就是打開電腦攝像頭,當P鍵按下的時候,儲存目前幀的圖像。簡單到沒朋友。
#include<opencv2\opencv.hpp>
using namespace cv;
int main()
{
VideoCapture cap();
Mat frame;
int i = ;
while ()
{
char key = waitKey();
cap >> frame;
imshow("frame", frame);
string filename = format("C:\\Users\\Apple\\Desktop\\hhh\\aaa%d.jpg", i);
switch (key)
{
case'p':
i++;
imwrite(filename, frame);
imshow("photo", frame);
waitKey();
destroyWindow("photo");
break;
default:
break;
}
}
}
然後我們就可以運作程式,不停地按下p鍵對自己一通狂拍了。
2.預處理
在得到自己的人臉照片之後,還需要對這些照片進行一些預處理才能拿去訓練模型。所謂預處理,其實就是檢測并分割出人臉,并改變人臉的大小與下載下傳的資料集中圖檔大小一緻。
檢測出人臉之後改變大小使之與ORL人臉資料庫人臉大小一緻。通過加斷點在Locals裡面或者是ImageWatch可以看到ORL人臉資料庫人臉的大小是92 x 112。(這個也是根據部落客部落格學習的)
那麼如何批量處理上面拍的照片呢?我給實驗室每位同學都來了20連拍,這個工作量還是很大的。答主給的程式不太全,編了一下午才調好了代碼。可以分割人臉并且變大小灰階與ORL資料庫人臉大小一緻,然後儲存下來,儲存的檔案夾一定要注意先提前建好。
代碼如下:
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/objdetect/objdetect.hpp>
using namespace cv;
int main()
{
char file_img[];
Mat t_img[];
vector<Rect> faces;
CascadeClassifier face_cascade;
face_cascade.load("haarcascade_frontalface_alt.xml");
//Size dst_size;
//讀取訓練樣本
for (int i = ; i < ; i++)
{
Mat img_gray;
int d = i + ;
sprintf(file_img, "C:\\Users\\Apple\\Desktop\\頭2\\%d.jpg", d);
Mat img = imread(file_img, );
cvtColor(img, img_gray, COLOR_BGR2GRAY);
equalizeHist(img_gray, img_gray);
//-- Detect faces;
//檢測人臉
face_cascade.detectMultiScale(img_gray, faces, , , CV_HAAR_DO_CANNY_PRUNING, Size(, ),Size(,));
if (faces.size() == )
{
continue;
}
Mat faceROI = img(faces[]);
Mat MyFace;
resize(faceROI, MyFace, Size(, ));
cvtColor(MyFace, MyFace, COLOR_BGR2GRAY);
string str = format("C:\\Users\\Apple\\Desktop\\頭3\\%d.jpg", d);
imwrite(str, MyFace);
imshow("ii", MyFace);
waitKey();
}
}
至此,我們就得到和ORL人臉資料庫人臉大小一緻的自己的人臉資料集。然後我們把自己的作為第41個人,在我們下載下傳的人臉檔案夾下建立一個s41的子檔案夾,把自己的人臉資料放進去。就成了這樣下面這樣,最後一個檔案夾裡面是我自己的頭像照片,我還多做了實驗室同學的資料集,一共五個人。
注意:我這裡儲存的圖像格式是.jpg的,而不是跟原資料集一樣是.pgm的。經測試仍然可以訓練出可以正确識别我自己人臉的模型來。但是如果大小不一緻會報錯。
跟着大神做了一天,十分疲憊。。
未完待續……