OpenCV——人臉識別數據處理(1)

Opencv
前段時間對人臉檢測和人臉標記進行了一些嘗試:檢測解決的問題是圖片中有沒有人臉;而識別解決的問題是,如果一張圖片中有人臉,這是誰的臉。人臉檢測可以利用opencv自帶的分類器,但是人臉識別就需要自己收集數據,自己訓練分類器了。opencv給出的有人臉識別的教程:Face Recognition with OpenCV。網上也可以找到中文版本的。

正所謂自己動手豐衣足食。站在巨人的肩膀上,參考前輩們的經驗,終於能夠識別出自己了。由於感覺內容較多,而且沒有時間一次性寫完,所以準備分階段來寫。每一篇博客是一個階段的工作。初步設想分爲數據收集和預處理、訓練模型和人臉識別三個部分。今天先寫第一部分。

一、背景數據集

本次用的數據集市opencv給出的教程裏面的第一個數據集:The AT&T Facedatabase。又稱ORL人臉數據庫,40個人,每人10張照片。照片在不同時間、不同光照、不同表情(睜眼閉眼、笑或者不笑)、不同人臉細節(戴眼鏡或者不戴眼鏡)下采集。所有的圖像都在一個黑暗均勻的背景下采集的,正面豎直人臉(有些有有輕微旋轉)。

下載下來之後是這樣的:

這裏寫代碼片
這裏寫圖片描述
可以看到每個人一個文件夾,每個文件夾下是這個人的十張照片,但是不是我們熟悉的BMP或者是PNG或者是JPEG格式的,而是PGM格式的。windows7自帶的照片查看器和畫圖軟件都不能打開這種格式的圖片。不過好在我昨天剛對imread()函數研究過:使用imread()函數讀取圖片的六種正確姿勢。所以記得opencv文檔裏有這樣的描述:
這裏寫圖片描述
imread()還是很強大的,所以寫個程序看看那這些人是什麼樣吧。
這裏寫圖片描述
二、自己的人臉數據集

1.拍照程序

想要識別自己,單有別人的數據集還是不行的,還需要自己人臉的照片才行。這就需要我們收集自己的照片,然後和上面的那個數據集一起來訓練模型。在拿着手機自拍的過程中我想到,問什麼不寫一個程序用電腦的攝像頭自拍呢,隨便還能研究下怎麼用opencv實現拍照的功能。經過一番實驗(其實還是費了好長時間),終於寫了一個拍照程序。

程序的功能就是打開電腦攝像頭,當P鍵按下(P是拍照的首字母?還是Photo的首字母?還是Picture的首字母?)的時候,保存當前幀的圖像。簡單到沒朋友(竟然耗費了那麼久!)。

while (1)  
        {  
            char key = waitKey(100);  
            cap >> frame;  
            imshow("frame", frame);  
            string filename = format("D:\\pic\\pic%d.jpg", i);  

            switch (key)  
            {  
            case'p':  
                i++;  
                imwrite(filename, frame);  
                imshow("photo", frame);  
                waitKey(500);  
                destroyWindow("photo");  
                break;  
            default:  
                break;  
            }  
        }  
</pre><p></p><pre>  

然後我們就可以運行程序,不停地按下p鍵對自己一通狂拍了。
2.預處理

在得到自己的人臉照片之後,還需要對這些照片進行一些預處理才能拿去訓練模型。所謂預處理,其實就是檢測並分割出人臉,並改變人臉的大小與下載的數據集中圖片大小一致。

人臉檢測在之前的博客中已經做了介紹,這裏就不再贅述。詳情參考:OpenCV實踐之路——人臉檢測(C++/Python)。用ROI分割即可。

檢測出人臉之後改變大小使之與ORL人臉數據庫人臉大小一致。通過加斷點在Locals裏面或者是ImageWatch可以看到ORL人臉數據庫人臉的大小是92 x 112。
這裏寫圖片描述這裏寫圖片描述
這裏只需要對檢測後得到的ROI做一次resize即可。

這兩步的代碼如下:

std::vector<Rect> faces;  
Mat img_gray;  

cvtColor(img, img_gray, COLOR_BGR2GRAY);  
equalizeHist(img_gray, img_gray);  

//-- Detect faces  
face_cascade.detectMultiScale(img_gray, faces, 1.1, 3, CV_HAAR_DO_ROUGH_SEARCH, Size(50, 50));  

for (size_t j = 0; j < faces.size(); j++)  
{  
    Mat faceROI = img(faces[j]);  
    Mat MyFace;  
    if (faceROI.cols > 100)  
    {  
        resize(faceROI, MyFace, Size(92, 112));  
        string  str = format("D:\\MyFaces\\MyFcae%d.jpg", i);  
        imwrite(str, MyFace);  
        imshow("ii", MyFace);  
    }  
    waitKey(10);  
}  

至此,我們就得到和ORL人臉數據庫人臉大小一致的自己的人臉數據集。然後我們把自己的作爲第41個人,在我們下載的人臉文件夾下建立一個s41的子文件夾,把自己的人臉數據放進去。就成了這樣下面這樣,最後一個文件夾裏面是我自己的頭像照片:
這裏寫圖片描述
最後那個at.txt放到下一次再說,訓練模型就靠它了。

這裏有一點值得注意:我這裏保存的圖像格式是.jpg的,而不是跟原數據集一樣是.pgm的。經測試仍然可以訓練出可以正確識別我自己人臉的模型來。但是如果大小不一致會報錯。

之後的內容放到下一次記錄。未完待續……


因爲上次是直接調用的百度接口,而不知其運行於原理,故學習opencv(開源)實現人臉識別功能。
這裏是c++版的代碼,可以學習相關知識。

本文由@星沉閣冰不語出品,轉載請註明作者和出處。
文章鏈接: http://blog.csdn.net/xingchenbingbuyu/article/details/50708765

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章