基于OpenCV与MFC的人脸识别
基于OpenCV與MFC的人臉識別
本問的完成借鑒了:
基于OpenCV3實現人臉識別(實踐篇)
1、 步驟
數據集制作,數據預處理,模型訓練,人臉識別。
1.1數據集制作
1.1.1準備工作
利用OpenCV基于MFC做的界面獲取自己的數據信息,結合ORL人臉數據庫。ORL庫中共計40人,每人各10張在不同時間、不同光照、不同表情(睜眼閉眼、笑或者不笑)、不同人臉細節(戴眼鏡或者不戴眼鏡)下采集的圖,總計400張圖。
ORL庫可以自行網上下載。
1.1.2個人數據集準備
本文基于OpenCV3.4.5和VS2015實現。
首先是建立一個基于對話框的MFC界面工程我以face1命名,包含兩個Picture Control,和3個按鈕。左側的Picture Control用于實現個人數據獲取,右側的用于之后的識別。兩個Picture Control按照自己設定好ID。雙擊打開攝像頭按鈕進入第一個按鈕的程序編寫。
第一個按鈕程序如下:
這部分程序的使用還要進行如下操作,先包含如下頭文件,使用相應的命名空間以及建立一個全局變量。
#include <opencv2\opencv.hpp> #include <vector> #include <iostream> #include<stdio.h> using namespace std; using namespace cv; VideoCapture cap;因為使用的是MFC的picture control顯示,而我們所用的是OpenCV的Mat來定義圖片變量,要想在picture control上顯示出來需要做變換把Mat轉換為合適的類型。網上用的最多的是已經消失在opencv3中的"Cvvimage.h"來完成,但是大多數都不好用,因此本文中采用的是在查詢了多為大佬后的文章得到的一個方法建立了一個函數轉換成CImage圖來顯示在picture中。(當然我們也可以通過opencv的一個函數的兩次調用也能解決但不方便我們理解原理)
程序如下:
當然我們需要先再MFC界面這個類也就是Cface1Dlg.h中添加函數聲明
int Cface1Dlg::ShowMat(cv::Mat img, HWND hWndDisplay);
然后準備部分的工作就完成了。
當然上述的按鈕中添加的程序還包括了接下來說的數據預處理工作。
1.2數據預處理
在得到自己的人臉照片之后,還需要對這些照片進行一些預處理才能拿去訓練模型。所謂預處理,其實就是檢測并分割出人臉,并改變人臉的大小與下載的數據集中圖片大小一致。
調用opencv訓練好的分類器和自帶的檢測函數檢測人臉人眼等的步驟簡單直接:
1.加載分類器,當然分類器事先要放在工程目錄中去。分類器本來的位置是在*\opencv\sources\data\haarcascades(harr分類器,也有其他的可以用,也可以自己訓練)這個分類器的可以復制到MFC工程文件夾的目錄中,或者直接復制他的路徑調用。
2.調用detectMultiScale()函數檢測,調整函數的參數可以使檢測結果更加精確。
3.把檢測到的人臉等用矩形(或者圓形等其他圖形)畫出來。
下圖來自CSDN的博主快樂成長吧的博客
運行看看可以得到:
框上面的數字對應正在獲得的圖為第幾張。
至此,我們就得到和ORL人臉數據庫人臉大小一致的自己的人臉數據集。得到圖能在工程文件夾中找到,然后我們把自己的作為第41個人,在我們下載的人臉文件夾下建立一個s41的子文件夾,把自己的人臉數據放進去。就成了這樣下面這樣,最后一個文件夾里面是我自己的頭像照片:
(附本文學習時并未使用ORL數據集,只是按起樣子自己準備了一些人物數據,因此并未達到40余人的數據集,這段話也是應引用博主快樂成長吧的博客)。
這里有一點值得注意:保存的圖像格式是*.jpg的,而不是跟原數據集一樣是*.pgm的。經測試仍然可以訓練出可以正確識別我和其他準備識別的人臉的模型來。但是如果大小不一致會報錯,所以大小:92*112。
1.3模型訓練
模型訓練也要做準備工作,首先我們要得到處理后數據集的csv文件,當我們寫人臉模型的訓練程序的時候,我們需要讀取人臉和人臉對應的標簽。直接在數據庫中讀取顯然是低效的。所以我們用csv文件讀取。csv文件中包含兩方面的內容,一是每一張圖片的位置所在,二是每一個人臉對應的標簽,就是為每一個人編號。這個at.txt就是我們需要的csv文件。引用他人的圖做介紹:
前面是圖片的位置,后面是圖片所屬人臉的人的標簽。對于大量的數據時,要生成這樣一個文件直接用手工的方式一個一個輸入顯然不可取的,我們先利用cmd窗口,進入到存放我們的人臉數據的文件夾,然后利用輸入:
dir /b/s *.pgm *.jpg >at.txt生成一個at.txt文件。圖如下(引用他人圖)
這個文件中只有路徑但是沒有標簽,因此選擇利用opencv的python腳本加標簽。opencv教程里面為我們提供了自動生成csv文件的腳本。
路徑類似這樣:
但是opencv_contrib-3.4.5這個屬于拓展庫需要自行去下載以及利用CMake添加生成。這里就不說明了。如果沒安裝我們也可以創建一個create_csv.py文件:程序如下:
import sys import os.path if __name__ == "__main__":#if len(sys.argv) != 2:# print ("usage: create_csv <base_path>")# sys.exit(1)BASE_PATH="數據集的路徑"SEPARATOR=";"fh=open("數據集中at.txt的路徑",'w')label = 0for dirname, dirnames, filenames in os.walk(BASE_PATH):for subdirname in dirnames:subject_path = os.path.join(dirname, subdirname)for filename in os.listdir(subject_path):abs_path = "%s/%s" % (subject_path, filename)print ("%s%s%d" % (abs_path, SEPARATOR, label))fh.write(abs_path)fh.write(SEPARATOR)fh.write(str(label))fh.write("\n")label = label + 1fh.close
填寫如圖然后保存,我們安裝了python3環境的話直接右鍵選擇打開方式為python即可運行產生at.txt在對應的數據集的文件夾中。
接下來在準備工作完成后,開始訓練模型。
在訓練前我們要現在自己下載自己裝的opencv對應的擴展庫opencv_contrib否則無法使用opencv的人臉識別模型,因為現在的opencv功能愈發龐大愈發雜,因此都開始修改為opencv+擴展庫兩部分按需下載。這個可以搜索解決。
現在數據集、csv文件都已經準備好了。接下來要做的就是訓練模型了。
這里我們用到了opencv的Facerecognizer類。opencv中所有的人臉識別模型都是來源于這個類,這個類為所有人臉識別算法提供了一種通用的接口。文檔里的一個小段包含了我們接下來要用到的幾個函數:
OpenCV 自帶了三個人臉識別算法:Eigenfaces(特征臉),Fisherfaces 和局部二進制模式直方圖 (LBPH)。先不深究算法。直接用。接下來就分別訓練這三種人臉模型。Facerecognizer的強大是因為每一種模型的訓練只需要三行代碼:
我們可以新建立一個win32控制臺程序專門做訓練用,修改只要把at.txt的路徑改成自己的即可,程序如下:
運行后,模型訓練完,會測試三個模型,產生三個結果。借用大佬圖:
1.4人臉識別:
基本流程如下:
1.打開攝像頭。
2.加載人臉檢測器,加載人臉模型。
3.人臉檢測
4.把檢測到的人臉與人臉模型里面的對比,找出這是誰的臉。
5.如果人臉是自己拍照的人臉,顯示自己的名字。
此處的代碼我們在MFC對話框中的人臉識別按鈕中加入,雙擊這份按鈕進入響應函數中寫代碼。
對比如下的頭文件和命名空間將沒有的補充。
按鈕中的代碼如下:
VideoCapture cap(0); //打開默認攝像頭 if (!cap.isOpened()){return ;}Mat frame;Mat gray;//這個分類器是人臉檢測所用CascadeClassifier cascade;bool stop = false;//訓練好的文件名稱,放置在可執行文件同目錄下 cascade.load("haarcascade_frontalface_alt2.xml");//感覺用lbpcascade_frontalface效果沒有它好,注意哈!要是正臉model = FisherFaceRecognizer::create();//1.加載訓練好的分類器model->read("G:\\實驗室任務\\myface\\MyFaceFisherModel.xml");// opencv2用load//3.利用攝像頭采集人臉并識別while (1){cap >> frame;vector<Rect> faces(0);//建立用于存放人臉的向量容器cvtColor(frame, gray, CV_RGB2GRAY);//測試圖像必須為灰度圖//gray=frame;equalizeHist(gray, gray); //變換后的圖像進行直方圖均值化處理 //檢測人臉cascade.detectMultiScale(gray, faces,1.1, 4, 0//|CV_HAAR_FIND_BIGGEST_OBJECT | CV_HAAR_DO_ROUGH_SEARCH,//| CV_HAAR_SCALE_IMAGE,Size(70, 70), Size(1000, 1000));Mat* pImage_roi = new Mat[faces.size()]; //定以數組Mat face;Point text_lb;//文本寫在的位置//框出人臉string str;for (int i = 0; i < faces.size(); i++){pImage_roi[i] = gray(faces[i]); //將所有的臉部保存起來text_lb = Point(faces[i].x, faces[i].y);if (pImage_roi[i].empty())continue;switch (Predict(pImage_roi[i])) //對每張臉都識別{case 0:str = "XXX",; break; //case后的數字調整為自己的人臉數據對應的標簽號碼。如標簽為0,str對應相應的名字。case 1:str = "XXX"; break;case 2:str = "XXX"; break;case 3:str = "XXX"; break;default: str = "Error"; break;}Scalar color = Scalar(g_rng.uniform(0, 255), g_rng.uniform(0, 255), g_rng.uniform(0, 255));//所取的顏色任意值rectangle(frame, Point(faces[i].x, faces[i].y), Point(faces[i].x + faces[i].width, faces[i].y + faces[i].height), color, 3, 8);//放入緩存putText(frame, str, text_lb, FONT_HERSHEY_COMPLEX, 2, Scalar(0, 0, 255));//添加文字}delete[]pImage_roi;ShowMat(frame, GetDlgItem(IDC_SHOW2)->GetSafeHwnd());waitKey(200);}最后結果如圖:
2、原理
參考:基于OpenCV3實現人臉識別(原理篇)
總結
以上是生活随笔為你收集整理的基于OpenCV与MFC的人脸识别的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: docker安装mangoDB
- 下一篇: Qt音视频开发41-人脸识别嵌入式