1. 程式人生 > >Matlab人臉檢測方法(Face Parts Detection)詳解

Matlab人臉檢測方法(Face Parts Detection)詳解

  今天同學讓我幫忙製作一個人臉表情識別的樣本庫,其中主要是對人臉進行裁剪,這裡用到了一個相對較新的Matlab人臉檢測方法Face Parts Detection,網上百度了一下發現關於Matlab人臉檢測的程式碼和資源並不多,故此專門撰寫一篇部落格來詳細介紹這個人臉檢測方法的用途。

  一、下載對應的工具包

  首先下載對應的工具包,matlab最方便的地方莫過於此了,直接下載、配置簡單、並且可以檢視原始碼,這裡給出對應的工具包下載地址:Face Parts Detection工具包

  點選“Download Zip”下載按鈕開始下載,下載完成後解壓,得到如下檔案:

  二、配置工具包

  下載完成後開始配置工具箱。首先需要強調一點,這個方法需要依賴兩個Matlab影象處理方面的工具箱

Image Processing ToolboxComputer Vision System Toolbox,幾乎所有版本的Matlab都預設集成了Image Processing工具箱,但對於Computer Vision System工具箱只有相對較高版本(Matlab2013及以上)的Matlab版本才進行了整合,因此如果在程式執行過程中提示缺少對應的工具箱,則需要手動進行配置Computer Vision System。

  假設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值均相等的三通道圖在視覺上同樣變現為灰度圖,不過單通道圖肯定是灰度圖。

如果覺得這篇文章對您有所啟發,歡迎關注我的公眾號,我會盡可能積極和大家交流,謝謝。