OpenCV人臉識別之一:數據收集和預處理

查閱更為簡潔方便的分類文章以及最新的課程、產品信息,請移步至全新呈現的leadai.org

本系列人臉識別文章用的是opencv2,最新版的opencv3.2的代碼請參考文章:

《OpenCV之識別自己的臉——C++源碼放送》;

《人臉識別源碼運行指南》(小編附在文末)

前段時間對人臉檢測進行了一些嘗試:人臉檢測(C++/Python)(jianshu.com/p/504c081d7)但是檢測和識別是不同的,檢測解決的問題是圖片中有沒有人臉;而識別解決的問題是,如果一張圖片中有人臉,這是誰的臉。人臉檢測可以利用opencv自帶的分類器,但是人臉識別就需要自己收集數據,自己訓練分類器了。opencv給出的有人臉識別的教程:Face Recognition with OpenCV(docs.opencv.org/2.4/mod)。網上也可以找到中文版本的。

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

1、背景數據集

本次用的數據集市opencv給出的教程裡面的第一個數據集:The AT&T Facedatabase(cl.cam.ac.uk/research/d)。又稱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)(jianshu.com/p/504c081d7)。用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:`github.com/LiuXiaolong1

百度網盤:鏈接:pan.baidu.com/s/1nuPFth 密碼:slh8

還要再強調的一點是:人臉識別源碼運行指南

人臉識別的源碼放出來之後,不少小夥伴下載之後仍然不能運行成功。於是被逼無奈,把源代碼改成了我認為最容易運行成功的版本。即使如此,我認為寫下這個指南還是有必要的。因為反覆回答相同的問題實在是太累人了。

重複一遍,本文環境為win7+vs2015+opencv3.2_with_contrib

源碼下載地址

網盤: pan.baidu.com/s/1b1J23O 密碼:kv1e(謹記此網盤鏈接與密碼,是該系列最新代碼下載的地址)

幾個問題

首先還是說明幾個問題,雖然都說過,但是還是有人問。以後再有人問就直接給他這篇文章。

找不到FaceRecognizer

FaceRecognizer在opencv的contrib模塊里的face模塊裡面。而opencv官方下載的opencv默認是不帶contrib的,要實現人臉識別需要用編譯了contrib模塊的opencv。一般來說需要自己編譯。但是自己編譯比較麻煩,網上有人分享了編譯好的opencv3.2的版本,下載地址如下:

鏈接:pan.baidu.com/s/1qYx3v8 密碼: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到源文件,運行。此時應該會打開攝像頭並識別自己的臉。

最後

此人臉識別程序只能做學習研究,因為這個正確率略低。有更高要求的小夥伴請自行探究更好的方法,在這方面我能指點內容的有限。

原文鏈接:jianshu.com/p/c722d2094

CSDN博客地址:blog.csdn.net/xingchenb

作者公眾號:公眾號CVPy,旨在分享OpenCV和Python的實戰內容,歡迎關注。

查閱更為簡潔方便的分類文章以及最新的課程、產品信息,請移步至全新呈現的「LeadAI學院官網」:

leadai.org

推薦閱讀:

TAG:OpenCV | 人脸识别 | 数据收集 |