OpenCV人臉識別之一:數據收集和預處理
查閱更為簡潔方便的分類文章以及最新的課程、產品信息,請移步至全新呈現的http://www.leadai.org
本系列人臉識別文章用的是opencv2,最新版的opencv3.2的代碼請參考文章:
《OpenCV之識別自己的臉——C++源碼放送》;
《人臉識別源碼運行指南》(小編附在文末)
前段時間對人臉檢測進行了一些嘗試:人臉檢測(C++/Python)(http://www.jianshu.com/p/504c081d7397)但是檢測和識別是不同的,檢測解決的問題是圖片中有沒有人臉;而識別解決的問題是,如果一張圖片中有人臉,這是誰的臉。人臉檢測可以利用opencv自帶的分類器,但是人臉識別就需要自己收集數據,自己訓練分類器了。opencv給出的有人臉識別的教程:Face Recognition with OpenCV(https://docs.opencv.org/2.4/modules/contrib/doc/facerec/facerec_tutorial.html)。網上也可以找到中文版本的。
正所謂自己動手豐衣足食。站在巨人的肩膀上,參考前輩們的經驗,終於能夠識別出自己了。由於感覺內容較多,而且沒有時間一次性寫完,所以準備分階段來寫。每一篇博客是一個階段的工作。初步設想分為數據收集和預處理、訓練模型和人臉識別三個部分。今天先寫第一部分。
1、背景數據集
本次用的數據集市opencv給出的教程裡面的第一個數據集:The AT&T Facedatabase(http://www.cl.cam.ac.uk/research/dtg/attarchive/facedatabase.html)。又稱ORL人臉資料庫,40個人,每人10張照片。照片在不同時間、不同光照、不同表情(睜眼閉眼、笑或者不笑)、不同人臉細節(戴眼鏡或者不戴眼鏡)下採集。所有的圖像都在一個黑暗均勻的背景下採集的,正面豎直人臉(有些有有輕微旋轉)。
下載下來之後是這樣的:
可以看到每個人一個文件夾,每個文件夾下是這個人的十張照片,但是不是我們熟悉的BMP或者是PNG或者是JPEG格式的,而是PGM格式的。windows7自帶的照片查看器和畫圖軟體都不能打開這種格式的圖片。
不過好在我昨天剛對imread()函數研究過:使用imread()函數讀取圖片的六種正確姿勢。所以記得opencv文檔里有這樣的描述:
imread()還是很強大的,所以寫個程序看看那這些人是什麼樣吧。
2、自己的人臉數據集
1、拍照程序
想要識別自己,單有別人的數據集還是不行的,還需要自己人臉的照片才行。這就需要我們收集自己的照片,然後和上面的那個數據集一起來訓練模型。在拿著手機自拍的過程中我想到,問什麼不寫一個程序用電腦的攝像頭自拍呢,隨便還能研究下怎麼用opencv實現拍照的功能。經過一番實驗(其實還是費了好長時間),終於寫了一個拍照程序。
程序的功能就是打開電腦攝像頭,當P鍵按下(P是拍照的首字母?還是Photo的首字母?還是Picture的首字母?)的時候,保存當前幀的圖像。簡單到沒朋友(竟然耗費了那麼久!)。
while (1) n { nchar key = waitKey(100); ncap >> frame; nimshow("frame", frame); nstring filename = format("D:picpic%d.jpg", i); nswitch (key) n { ncasep: ni++; nimwrite(filename, frame); nimshow("photo", frame); n waitKey(500); n destroyWindow("photo"); n break; ndefault: nbreak; n }n }n
然後我們就可以運行程序,不停地按下p鍵對自己一通狂拍了。
2、預處理
在得到自己的人臉照片之後,還需要對這些照片進行一些預處理才能拿去訓練模型。所謂預處理,其實就是檢測並分割出人臉,並改變人臉的大小與下載的數據集中圖片大小一致。
人臉檢測在之前的博客中已經做了介紹,這裡就不再贅述。詳情參考:OpenCV人臉檢測(C++/Python)(http://www.jianshu.com/p/504c081d7397)。用ROI分割即可。
檢測出人臉之後改變大小使之與ORL人臉資料庫人臉大小一致。通過加斷點在Locals裡面或者是ImageWatch可以看到ORL人臉資料庫人臉的大小是92 x 112。
這裡只需要對檢測後得到的ROI做一次resize即可。
這兩步的代碼如下:
std::vector<Rect> faces; nMat img_gray; ncvtColor(img, img_gray, COLOR_BGR2GRAY); nequalizeHist(img_gray, img_gray); n//-- Detect faces nface_cascade.detectMultiScale(img_gray, faces, 1.1, 3, CV_HAAR_DO_ROUGH_SEARCH, Size(50, 50)); nfor (size_t j = 0; j < faces.size(); j++) n { nMat faceROI = img(faces[j]); n Mat MyFace; n if (faceROI.cols > 100) n{ nresize(faceROI, MyFace, Size(92, 112)); n string str = format("D:MyFacesMyFcae%d.jpg", i); nimwrite(str, MyFace); nimshow("ii", MyFace); n } nwaitKey(10);n}n
至此,我們就得到和ORL人臉資料庫人臉大小一致的自己的人臉數據集。然後我們把自己的作為第41個人,在我們下載的人臉文件夾下建立一個s41的子文件夾,把自己的人臉數據放進去。就成了這樣下面這樣,最後一個文件夾裡面是我自己的頭像照片:
最後那個at.txt放到下一次再說,訓練模型就靠它了。
這裡有一點值得注意:我這裡保存的圖像格式是.jpg的,而不是跟原數據集一樣是.pgm的。經測試仍然可以訓練出可以正確識別我自己人臉的模型來。但是如果大小不一致會報錯。
OpenCV之識別自己的臉——C++源碼放送
前言
在將近一年之前,我在CSDN專欄《OpenCV實踐之路》中連續發了三篇博客,完整地描述了基於OpenCV進行人臉識別的全過程。三篇都將近一萬的閱讀量和大量的評論的表明,人臉識別果然是大家在學習OpenCV過程中最感興趣的課題,之一。當然,也有可能是本科生畢設老師最感興趣的課題之一。
由於當時寫的時候是按照前後流程來的,所以源碼比較分散。加之我想當然地認為,很多源碼是之前博客中已經放出來的,可以一句帶過。這導致了很多同學學習的時候很不方面。但是我由於重裝系統,導致當初的源碼遺失,也一直沒有抽出時間去重新整理一下。這個清明節,沒有出門,根據之前的博客基於當下最新的OpenCV3.2重新整理了一遍源碼。現在放出來,以饗讀者。
小小的區別
當然了,重新整理也不是簡單的把源碼收集到一起,如果真的那麼簡單,也就不用去整理了,大家自行收集即可。因為OpenCV3.2人臉識別的內容也是有些小變動。所以現在的代碼跟原來的三篇博客仍然是統一的,但是有一些細節不同。
1、自動拍照
之前採集自己的圖像的時候,程序設定是運行之後按』p』鍵拍照並保存圖像,然後需要自己手動的去把圖像大小轉化為跟ORL人臉資料庫中的圖片大小一樣。
現在一切自動,只需要運行即可拍照,變化尺寸,並保存。默認設定拍10張照片,與ORL人臉資料庫一致。
2、Python腳本生成at.txt
當時寫博客的時候還不會用Python,所以生成的at.txt並不是s1文件夾對應的label就是1,s2就對應2。而是比較混亂的。誰是誰需要自己去記憶。
經過修改後的Python腳本可以是文件夾可label完美對應起來了。
3、訓練代碼
訓練人臉識別模型的代碼部分有些改動,主要是因為OpenCV的變動。
頭文件和命名空間需要各加一句:
#include<opencv2face.hpp>nusing namespace cv::face;n
創建模型部分的改變,原來的代碼是
Ptr<FaceRecognizer> model = createEigenFaceRecognizer();nPtr<FaceRecognizer> model1 = createFisherFaceRecognizer();nPtr<FaceRecognizer> model2 = createLBPHFaceRecognizer();n
現在改為:
Ptr<BasicFaceRecognizer> model = createEigenFaceRecognizer(); Ptr<BasicFaceRecognizer> model1 = createFisherFaceRecognizer(); Ptr<LBPHFaceRecognizer> model2 = createLBPHFaceRecognizer();n
其餘部分沒有太大變化。
下載辦
源碼已經分別上傳到Github、百度網盤。其中github由於大小限制,不含我訓練好的模型。
Github:`https://github.com/LiuXiaolong19920720/recognise-your-own-face
百度網盤:鏈接:http://pan.baidu.com/s/1nuPFthR 密碼:slh8
還要再強調的一點是:人臉識別源碼運行指南
人臉識別的源碼放出來之後,不少小夥伴下載之後仍然不能運行成功。於是被逼無奈,把源代碼改成了我認為最容易運行成功的版本。即使如此,我認為寫下這個指南還是有必要的。因為反覆回答相同的問題實在是太累人了。
重複一遍,本文環境為win7+vs2015+opencv3.2_with_contrib
源碼下載地址
網盤: http://pan.baidu.com/s/1b1J23O 密碼:kv1e(謹記此網盤鏈接與密碼,是該系列最新代碼下載的地址)
幾個問題
首先還是說明幾個問題,雖然都說過,但是還是有人問。以後再有人問就直接給他這篇文章。
找不到FaceRecognizer
FaceRecognizer在opencv的contrib模塊里的face模塊裡面。而opencv官方下載的opencv默認是不帶contrib的,要實現人臉識別需要用編譯了contrib模塊的opencv。一般來說需要自己編譯。但是自己編譯比較麻煩,網上有人分享了編譯好的opencv3.2的版本,下載地址如下:
鏈接:http://pan.baidu.com/s/1qYx3v8S 密碼:i0c0
csv文件(也即at.txt)難以自動生成。
源碼中我已經寫了一個名為add_label.py的python腳本,運行此腳本可以自動生成at.txt。
有時程序崩潰但是黑窗無報錯信息。
一個可能的原因是,添加附加依賴項的時候,debug模式最好只添加*d.lib。而release模式最好只添加*.lib。
運行指南
方便起見,下載的源碼的文件夾下已經包含了需要用的ORL人臉資料庫。在配置好opencv的情況下,需要以下幾步。
1、首先用VS打開face-rec.sln。在解決方案管理器中的源文件下添加take_photos.cpp,如果源文件下還有其他cpp文件,請它們排除到項目之外。然後運行此拍照程序。如果拍照效果不好,請自動調整人臉與攝像頭之間的距離,或者調節光照條件。拍好的照片會保存在att_facess41文件夾下。
2、生成csv文件。需要電腦上安裝有Python2,如果是Python3的話需要把print語句注釋掉,沒有實際測試過。如果對python有了解,應該不難。在add_label.py所在文件夾下shift+右鍵然後選擇在此處打開命令行窗口。在命令行輸入命令:python add_label.py,Enter運行即可。
3、回到VS。把take_photos.cpp排除到項目之外,添加train.cpp到源文件,運行。最後輸出3行類似下面的語句表示訓練模型成功。此時打開工程文件夾可以看到生成的後綴為xml的模型文件。
Predicted class = 9 / Actual class = 9.
4、回到VS。把train.cpp排除到項目之外,添加rec-your-own-face.cpp到源文件,運行。此時應該會打開攝像頭並識別自己的臉。
最後
此人臉識別程序只能做學習研究,因為這個正確率略低。有更高要求的小夥伴請自行探究更好的方法,在這方面我能指點內容的有限。
原文鏈接:http://www.jianshu.com/p/c722d20944f2
CSDN博客地址:http://blog.csdn.net/xingchenbingbuyu/article/details/73733490作者公眾號:公眾號CVPy,旨在分享OpenCV和Python的實戰內容,歡迎關注。查閱更為簡潔方便的分類文章以及最新的課程、產品信息,請移步至全新呈現的「LeadAI學院官網」:
http://www.leadai.org
推薦閱讀: