Matlab人臉檢測方法(Face Parts Detection)詳解
今天同學讓我幫忙製作一個人臉表情識別的樣本庫,其中主要是對人臉進行裁剪,這裡用到了一個相對較新的Matlab人臉檢測方法Face Parts Detection,網上百度了一下發現關於Matlab人臉檢測的程式碼和資源並不多,故此專門撰寫一篇部落格來詳細介紹這個人臉檢測方法的用途。
一、下載對應的工具包
首先下載對應的工具包,matlab最方便的地方莫過於此了,直接下載、配置簡單、並且可以檢視原始碼,這裡給出對應的工具包下載地址:Face Parts Detection工具包。
點選“Download Zip”下載按鈕開始下載,下載完成後解壓,得到如下檔案:
二、配置工具包
下載完成後開始配置工具箱。首先需要強調一點,這個方法需要依賴兩個Matlab影象處理方面的工具箱
假設Matlab已經配置好了以上兩個工具箱,接下來開始配置Face Parts Detection工具包,方法極其簡單,只需在Set Path對話方塊中將當前工具箱的資料夾(這裡是Face_detection_Parts資料夾)路徑新增到系統的搜尋路徑即可:
三、進行批量人臉檢測
工具箱配置完成後開始利用其進行人臉檢測。
3.1、批量讀取圖片
首先,需要對資料庫中的影象進行批量讀取,讀取完之後再進行人臉檢測。首先給出批量讀取的程式碼,稍後解釋:
clear; stImageFilePath = 'E:\CAS-PEAL-R1(1)\CAS-PEAL-R1\FRONTAL\Expression\'; stImageSavePath = 'E:\Face_Detection\'; dirImagePathList = dir(strcat(stImageFilePath,'*.tif')); %讀取該資料夾下所有圖片的路徑(字串格式) iImageNum= length(dirImagePathList); %獲取圖片的總數量 if iImageNum > 0 %批量讀入圖片,進行五官檢測,再批量檢測 for i = 1 : iImageNum iSaveNum = int2str(i); stImagePath = dirImagePathList(i).name; mImageCurrent = imread(strcat(stImageFilePath,stImagePath)); end end
這裡採用dir()函式的方法來讀取目錄下所有檔案的檔名,dirImagePathList(i).name中儲存了資料夾下的所有檔案的名稱。有關Matlab中dir()函式的用法大家可以參考網路資料。stImageFilePath變數儲存了當前圖片所在資料夾的路徑(這裡為E:\CAS-PEAL-R1(1)\CAS-PEAL-R1\FRONTAL\Expression\),stImageSavePath變數指定了裁剪之後的人臉影象的儲存路徑。這裡需要注意的一點就是儲存裁剪結果的資料夾需要事先建立好(或者在程式中通過mkdir等函式來提前建立)。通過strcat()函式來判斷當前影象名稱中是否包含“.tif”來確定其是否為影象檔案(這裡的資料庫中的影象檔案都是tif格式的),
3.2、編寫人臉檢測函式
批量讀取影象完成後,開始進行人臉檢測,這裡選擇將人臉檢測封裝為一個指令碼檔案方便呼叫,這裡暫且將其命名為face_segment.m檔案。
首先,需要判斷當前影象的通道數,因為Face Parts Detection方法只能針對三通道影象進行人臉檢測,如果當前影象為灰度圖(單通道圖),則需要先將其轉換為三通道矩陣形式:
%%%%%%%%%%%%%%%%%%%%將灰度圖變為三通道圖%%%%%%%%%%%%%%%%%%%% if(size(mImageSrc,3) == 1) mImage2detect(:,:,1) = mImageSrc; mImage2detect(:,:,2) = mImageSrc; mImage2detect(:,:,3) = mImageSrc; else mImage2detect = mImageSrc; end
然後開始呼叫工具箱進行人臉檢測,就兩句程式碼即可(可見作者將程式封裝得何其之好):
%%%%%%%%%%%%%%%%%%%%對影象進行人臉檢測%%%%%%%%%%%%%%%%%%%% FaceDetector = buildDetector(); [bbox,bbimg,faces,bbfaces] = detectFaceParts(FaceDetector,mImage2detect,2);
對於bbox,bbimg,faces,bbfaces這四個檢測結果的具體含義,在detectFaceParts.m檔案的開頭部分作者給出了詳細的解釋,我們這裡只用到bbox這個變數,它裡面分別儲存了所檢測出的人臉區域(一個矩形框)的左上角座標以及寬度和高度。
檢測完成之後,再統一將影象轉換為灰度圖,保證格式的統一,方便儲存:
%%%%%%%%%%%%%%%%%%%%輸入影象灰度化%%%%%%%%%%%%%%%%%%%% if 1 ~= size(mImageSrc,3) mImageSrc = rgb2gray(mImageSrc); mImageSrc = double(mImageSrc); elseif 1 == size(mImageSrc,3) mImageSrc = double(mImageSrc); end
接下來開始對人臉區域進行分割。這個有兩種分割策略,一種是直接使用檢測到的人臉框bbox對原圖進行擷取,在不可控的採集條件下只能用這種方法來分割人臉;第二種策略是針對人臉框bbox首先確定人臉區域的中心點,然後再以中心點為基準向四周按照一定比例進行外擴,這種方法僅適合採集條件嚴格可控、人臉大致對齊的人臉資料庫,恰好我們所處理的資料庫滿足這種要求,因此在這裡採用第二種策略進行人臉區域分割,程式碼如下:
%%%%%%%%%%%%%%%%%%%%得到人臉區域框的中心點%%%%%%%%%%%%%%%%%%%% recFace.x = bbox(1,1); recFace.y = bbox(1,2); recFace.width = bbox(1,3); recFace.height = bbox(1,4); ptFaceCenter.x = recFace.x + recFace.width / 2; ptFaceCenter.y = recFace.y + recFace.height / 2; %%%%%%%%%%%%%%%%%%%%以中心點為基準進行外擴(即對人臉選框進行調整)%%%%%%%%%%%%%%%%%%%% recFace.x = ptFaceCenter.x - recFace.width * 0.4; recFace.y = ptFaceCenter.y - recFace.height * 0.35; recFace.width = recFace.width * 0.8 ; recFace.height = recFace.height * 0.8 ; mFaceResult = uint8(imcrop(mImageSrc,[recFace.x,recFace.y,recFace.width,recFace.height]));
這裡只涉及到了簡單的幾何知識,因此不再贅述,確定好人臉矩形區域之後,使用imcrop()函式進行區域分割。這裡給出face_segment.m檔案的完整程式碼:
%=============================================================================== %函式名稱:face_segment %輸入引數:mImageSrc,待分割的人臉影象,可能是灰度影象,也可能是彩色影象 %輸出引數:mFaceResult,分割後的人臉結果,應為灰度影象 %主要步驟:1)進行人臉檢測,得到臉部區域的框框 % 2)得到臉部影象框的中心點 % 3)根據中心點,對影象進行等比例外擴,得到合適大小的人臉影象 %注意事項:1)首先需要判斷該影象是否為灰度圖,若為灰度圖,需要先將其轉換為三通道彩色圖 %=============================================================================== function mFaceResult = face_segment(mImageSrc) %%%%%%%%%%%%%%%%%%%%將灰度圖變為三通道圖%%%%%%%%%%%%%%%%%%%% if(size(mImageSrc,3) == 1) mImage2detect(:,:,1) = mImageSrc; mImage2detect(:,:,2) = mImageSrc; mImage2detect(:,:,3) = mImageSrc; else mImage2detect = mImageSrc; end %%%%%%%%%%%%%%%%%%%%對影象進行人臉檢測%%%%%%%%%%%%%%%%%%%% FaceDetector = buildDetector(); [bbox,bbimg,faces,bbfaces] = detectFaceParts(FaceDetector,mImage2detect,2); %%%%%%%%%%%%%%%%%%%%輸入影象灰度化%%%%%%%%%%%%%%%%%%%% if 1 ~= size(mImageSrc,3) mImageSrc = rgb2gray(mImageSrc); mImageSrc = double(mImageSrc); elseif 1 == size(mImageSrc,3) mImageSrc = double(mImageSrc); end %%%%%%%%%%%%%%%%%%%%得到人臉區域框的中心點%%%%%%%%%%%%%%%%%%%% recFace.x = bbox(1,1); recFace.y = bbox(1,2); recFace.width = bbox(1,3); recFace.height = bbox(1,4); ptFaceCenter.x = recFace.x + recFace.width / 2; ptFaceCenter.y = recFace.y + recFace.height / 2; %%%%%%%%%%%%%%%%%%%%以中心點為基準進行外擴(即對人臉選框進行調整)%%%%%%%%%%%%%%%%%%%% recFace.x = ptFaceCenter.x - recFace.width * 0.4; recFace.y = ptFaceCenter.y - recFace.height * 0.35; recFace.width = recFace.width * 0.8 ; recFace.height = recFace.height * 0.8 ; mFaceResult = uint8(imcrop(mImageSrc,[recFace.x,recFace.y,recFace.width,recFace.height])); end
四、人臉批量儲存
在完成人臉檢測函式之後,開始對人臉進行檢測分割和批量儲存,這裡直接給出程式碼:
clear; stImageFilePath = 'E:\CAS-PEAL-R1(1)\CAS-PEAL-R1\FRONTAL\Expression\'; stImageSavePath = 'E:\Face_Detection\'; dirImagePathList = dir(strcat(stImageFilePath,'*.tif')); %讀取該資料夾下所有圖片的路徑(字串格式) iImageNum = length(dirImagePathList); %獲取圖片的總數量 if iImageNum > 0 %批量讀入圖片,進行五官檢測,再批量檢測 for i = 1 : iImageNum iSaveNum = int2str(i); stImagePath = dirImagePathList(i).name; mImageCurrent = imread(strcat(stImageFilePath,stImagePath)); mFaceResult = face_segment(mImageCurrent); imwrite(mFaceResult,strcat(stImageSavePath,iSaveNum,'.bmp')); end end
這段程式碼的邏輯相對簡單,呼叫strcat()字串拼接函式來完成檢測結果的自動命名,考慮到版權問題,這裡不貼上最終的人臉分割結果,但程式親測可用,沒有問題。
五、注意事項
1、OpenCv人臉檢測函式
進行人臉檢測是Matlab並不是唯一選擇,OpenCv也同樣封裝的人臉檢測函式,不過OpenCv中封裝的人臉檢測函式是基於AdaBoost演算法,相對經典而古老,效能不如本文中所介紹的人臉檢測演算法,並且OpenCv在讀取tif格式的影象檔案時顯得異常麻煩。
2、原理介紹
在這篇博文中我們只介紹了Face Parts Detection演算法的具體用法,至於去人臉檢測原理,將來有時間了我再專門寫博文進行介紹。
3、打不開MathWork官網的話我可以給發郵箱
如果出現不能正常登陸MathWork網站,無法下載工具箱的情況,可以給我發郵件,我會抓時間提供相應的工具箱
4、灰度圖不等於單通道圖
在這裡再強調一個小問題,就是灰度圖與單通道圖的關係,理論上來說這兩個名詞完全屬於不同的概念,灰度圖不一定是單通道圖,因為三個通道的RGB值均相等的三通道圖在視覺上同樣變現為灰度圖,不過單通道圖肯定是灰度圖。
如果覺得這篇文章對您有所啟發,歡迎關注我的公眾號,我會盡可能積極和大家交流,謝謝。