人臉檢測實戰(zhàn)終極之OpenCV+Python實現(xiàn)人臉對齊_第1頁
人臉檢測實戰(zhàn)終極之OpenCV+Python實現(xiàn)人臉對齊_第2頁
人臉檢測實戰(zhàn)終極之OpenCV+Python實現(xiàn)人臉對齊_第3頁
人臉檢測實戰(zhàn)終極之OpenCV+Python實現(xiàn)人臉對齊_第4頁
人臉檢測實戰(zhàn)終極之OpenCV+Python實現(xiàn)人臉對齊_第5頁
已閱讀5頁,還剩8頁未讀 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

第人臉檢測實戰(zhàn)終極之OpenCV+Python實現(xiàn)人臉對齊目錄前言實現(xiàn)面部矯正器導入必要的包對齊人臉展示結(jié)果

前言

這篇博文的目的是演示如何使用OpenCV、Python和面部標志對齊人臉。

給定一組面部標志(輸入坐標),我們的目標是將圖像扭曲并轉(zhuǎn)換為輸出坐標空間。

在這個輸出坐標空間中,整個數(shù)據(jù)集中的所有面都應(yīng)該:

在圖像中居中。

旋轉(zhuǎn),使眼睛位于水平線上(即,旋轉(zhuǎn)面部,使眼睛位于相同的y坐標上)。

進行縮放,使面的大小大致相同。

為此,我們將首先調(diào)用一個實現(xiàn)的Python類FaceAligner,以使用仿射變換對齊人臉。

注意:仿射變換用于旋轉(zhuǎn)、縮放、平移等。我們可以將上述所有三個要求打包到一個cv2.warpAffine調(diào)用中;訣竅是創(chuàng)建旋轉(zhuǎn)矩陣M。

然后,我們將創(chuàng)建一個示例驅(qū)動程序Python腳本來接受輸入圖像、檢測人臉并對齊它們。

最后,我們將回顧我們使用OpenCV過程進行人臉對齊的結(jié)果。

實現(xiàn)面部矯正器

面部對齊算法本身基于MasteringOpenCVwithPracticalComputerVisionProjects(Baggio,2012)的第8章,如果您有C++背景或興趣,我強烈推薦它。本書在GitHub上提供了開放訪問的代碼示例。

新建facealigner.py實現(xiàn)FaceAligner類。

#importthenecessarypackages

fromimutils.face_utils.helpersimportFACIAL_LANDMARKS_68_IDXS

fromimutils.face_utils.helpersimportFACIAL_LANDMARKS_5_IDXS

fromimutils.face_utils.helpersimportshape_to_np

importnumpyasnp

importcv2

classFaceAligner:

def__init__(self,predictor,desiredLeftEye=(0.35,0.35),

desiredFaceWidth=256,desiredFaceHeight=None):

#storethefaciallandmarkpredictor,desiredoutputleft

#eyeposition,anddesiredoutputfacewidth+height

self.predictor=predictor

self.desiredLeftEye=desiredLeftEye

self.desiredFaceWidth=desiredFaceWidth

self.desiredFaceHeight=desiredFaceHeight

#ifthedesiredfaceheightisNone,setittobethe

#desiredfacewidth(normalbehavior)

ifself.desiredFaceHeightisNone:

self.desiredFaceHeight=self.desiredFaceWidth

導入必要的包

定義的構(gòu)造函數(shù)開始我們的FaceAligner類。

我們的構(gòu)造函數(shù)有4個參數(shù):

predictor:面部標志性預(yù)測器模型。

requiredLeftEye:一個可選的(x,y)元組,顯示默認值,指定所需的輸出左眼位置。對于此變量,通常會看到20-40%范圍內(nèi)的百分比。這些百分比控制對齊后人臉的可見程度。使用的確切百分比將因應(yīng)用程序而異。使用20%時,您基本上會獲得“放大”的臉部視圖,而使用較大的值時,臉部會顯得更“縮小”。

requiredFaceWidth:另一個可選參數(shù),以像素為單位定義我們想要的人臉。我們將此值默認為256像素。

requiredFaceHeight:最后一個可選參數(shù),以像素為單位指定我們所需的人臉高度值。

接下來,讓我們決定是想要一張方形的人臉圖像還是矩形的圖像。檢查requiredFaceHeight是否為None,如果是,我們將其設(shè)置為desiredFaceWidth,這意味著面部是方形的。方形圖像是典型情況?;蛘?,我們可以為desiredFaceWidth和desiredFaceHeight指定不同的值以獲得感興趣的矩形區(qū)域。

現(xiàn)在我們已經(jīng)構(gòu)建了我們的FaceAligner對象,接下來我們將定義一個對齊人臉的函數(shù)。

這個函數(shù)有點長,所以我把它分成了5個代碼塊,讓它更容易理解:

defalign(self,image,gray,rect):

#convertthelandmark(x,y)-coordinatestoaNumPyarray

shape=self.predictor(gray,rect)

shape=shape_to_np(shape)

#extracttheleftandrighteye(x,y)-coordinates

(lStart,lEnd)=FACIAL_LANDMARKS_IDXS["left_eye"]

(rStart,rEnd)=FACIAL_LANDMARKS_IDXS["right_eye"]

leftEyePts=shape[lStart:lEnd]

rightEyePts=shape[rStart:rEnd]

定義了align函數(shù),它接受三個參數(shù):

image:RGB輸入圖像。

gray:灰度輸入圖像。

rect:由dlib的HOG人臉檢測器生成的邊界框矩形。

應(yīng)用dlib的面部標志預(yù)測器并將標志轉(zhuǎn)換為NumPy格式的(x,y)坐標。

接下來,從helpers.py腳本中找到的FACIAL_LANDMARK_IDXS字典中讀取left_eye和right_eye區(qū)域。這些2元組值存儲在左/右眼開始和結(jié)束索引中。

提取leftEyePts和rightEyePts。

接下來,計算每只眼睛的中心以及眼睛質(zhì)心之間的角度。

這個角度是對齊我們的圖像的關(guān)鍵組成部分。

眼睛之間的綠線夾角,如下圖所示,是我們比較關(guān)心的。

接下來是角度計算:

#computethecenterofmassforeacheye

leftEyeCenter=leftEyePts.mean(axis=0).astype("int")

rightEyeCenter=rightEyePts.mean(axis=0).astype("int")

#computetheanglebetweentheeyecentroids

dY=rightEyeCenter[1]-leftEyeCenter[1]

dX=rightEyeCenter[0]-leftEyeCenter[0]

angle=np.degrees(np.arctan2(dY,dX))-180

分別通過平均每只眼睛的所有(x,y)點來計算每只眼睛的質(zhì)心,也稱為質(zhì)心。

給定眼睛中心,我們可以計算(x,y)坐標的差異并取反正切以獲得眼睛之間的旋轉(zhuǎn)角度。

這個角度將允許我們校正旋轉(zhuǎn)。

為了確定角度,我們首先計算y方向的增量dY。這是通過在第38行找到rightEyeCenter和leftEyeCenter之間的差異來完成的。

類似地,我們計算dX,即第39行x方向的增量。

接下來,我們計算面部旋轉(zhuǎn)的角度。我們使用帶有參數(shù)dY和dX的NumPy的arctan2函數(shù),然后轉(zhuǎn)換為度數(shù),同時減去180以獲得角度。

在以下代碼塊中,我們計算所需的右眼坐標(作為左眼位置的函數(shù))并計算新結(jié)果圖像的比例。

#computethedesiredrighteyex-coordinatebasedonthe

#desiredx-coordinateofthelefteye

desiredRightEyeX=1.0-self.desiredLeftEye[0]

#determinethescaleofthenewresultingimagebytaking

#theratioofthedistancebetweeneyesinthe*current*

#imagetotheratioofdistancebetweeneyesinthe

#*desired*image

dist=np.sqrt((dX**2)+(dY**2))

desiredDist=(desiredRightEyeX-self.desiredLeftEye[0])

desiredDist*=self.desiredFaceWidth

scale=desiredDist/dist

根據(jù)所需的左眼x坐標計算所需的右眼。從1.0中減去self.desiredLeftEye[0]因為所需的RightEyeX值應(yīng)該與圖像的右邊緣等距,因為相應(yīng)的左眼x坐標與其左邊緣的距離相同。

然后可以通過獲取當前圖像中眼睛之間的距離與所需圖像中眼睛之間的距離的比率來確定人臉的比例

首先,計算歐幾里得距離比dist。

接下來,使用左右眼x值之間的差異,計算所需的距離,desiredDist。

通過在第52行乘以所需的面寬來更新所需的距離。這實質(zhì)上是根據(jù)所需的寬度縮放的眼睛距離。

最后,比例是通過將desiredDist除以我們之前計算的dist來計算的。

現(xiàn)在有了旋轉(zhuǎn)角度和比例,需要在計算仿射變換之前采取一些步驟。這包括找到眼睛之間的中點以及計算旋轉(zhuǎn)矩陣并更新其平移分量:

#computecenter(x,y)-coordinates(i.e.,themedianpoint)

#betweenthetwoeyesintheinputimage

eyesCenter=(int((leftEyeCenter[0]+rightEyeCenter[0])//2),

int((leftEyeCenter[1]+rightEyeCenter[1])//2))

#grabtherotationmatrixforrotatingandscalingtheface

M=cv2.getRotationMatrix2D(eyesCenter,angle,scale)

#updatethetranslationcomponentofthematrix

tX=self.desiredFaceWidth*0.5

tY=self.desiredFaceHeight*self.desiredLeftEye[1]

M[0,2]+=(tX-eyesCenter[0])

M[1,2]+=(tY-eyesCenter[1])

計算eyeCenter,即左右眼之間的中點。這將用于我們的旋轉(zhuǎn)矩陣計算。本質(zhì)上,這個中點位于鼻子的頂部,是我們將面部旋轉(zhuǎn)的點:

為了計算旋轉(zhuǎn)矩陣M,我們使用cv2.getRotationMatrix2D指定eyeCenter、角度和比例。這三個值中的每一個都先前已計算過,因此請根據(jù)需要返回。

cv2.getRotationMatrix2D的參數(shù)說明如下:

eyeCenter:眼睛之間的中點是我們將圍繞面部旋轉(zhuǎn)的點。

angle:我們將面部旋轉(zhuǎn)到的角度,以確保眼睛位于同一水平線上。

scale:我們將放大或縮小圖像的百分比,確保圖像縮放到所需的大小。

現(xiàn)在必須更新矩陣的平移分量,使人臉在仿射變換后仍然在圖像中。

取所需面寬的一半并將值存儲為tX,即x方向的平移。

為了計算tY,y方向的平移,將所需的面部高度乘以所需的左眼y值,desiredLeftEye[1]。

使用tX和tY,通過從它們對應(yīng)的眼睛中點值(第66行和第67行)中減去每個值來更新矩陣的平移分量。

然后應(yīng)用仿射變換來對齊人臉:

#applytheaffinetransformation

(w,h)=(self.desiredFaceWidth,self.desiredFaceHeight)

output=cv2.warpAffine(image,M,(w,h),

flags=cv2.INTER_CUBIC)

#returnthealignedface

returnoutput

為方便起見,將desiredFaceWidth和desiredFaceHeight分別存儲到w和h中(第70行)。

然后調(diào)用cv2.warpAffine執(zhí)行最后一步。此函數(shù)調(diào)用需要3個參數(shù)和1個可選參數(shù):

image:人臉圖像。

M:平移、旋轉(zhuǎn)和縮放矩陣。

(w,h):輸出面所需的寬度和高度。

flags:用于扭曲的插值算法,在本例中為INTER_CUBIC。要了解其他可能的標志和圖像轉(zhuǎn)換,請參閱OpenCV文檔。

最后,對齊的臉面。

對齊人臉

開始編寫人臉對齊腳本,將其命名為Nowlet'sputthisalignmentclasstoworkwithasimpledriverscript.Openupanewfile,nameitalign_faces.py:

#importthenecessarypackages

fromimutils.face_utilsimportFaceAligner

fromimutils.face_utilsimportrect_to_bb

importargparse

importimutils

importdlib

importcv2

#constructtheargumentparserandparsethearguments

ap=argparse.ArgumentParser()

ap.add_argument("-p","--shape-predictor",required=True,

help="pathtofaciallandmarkpredictor")

ap.add_argument("-i","--image",required=True,

help="pathtoinputimage")

args=vars(ap.parse_args())

如果您的系統(tǒng)上沒有安裝imutils和/或dlib,請確保通過pip安裝/升級它們:

pipinstall--upgradeimutils

pipinstall--upgradedlib

win10安裝dlib參考:如何安裝dlibgpu版本

#initializedlib'sfacedetector(HOG-based)andthencreate

#thefaciallandmarkpredictorandthefacealigner

detector=dlib.get_frontal_face_detector()

predictor=dlib.shape_predictor(args["shape_predictor"])

fa=FaceAligner(predictor,desiredFaceWidth=256)

使用dlib的get_frontal_face_detector初始化我們的檢測器對象。

使用--shape-predictor來實例化我們的面部標志預(yù)測器,這是dlib的預(yù)訓練預(yù)測器的路徑。

通過在第21行初始化一個對象fa來利用剛剛在上一節(jié)中構(gòu)建的FaceAligner類。我們指定了256像素的人臉寬度。

接下來,加載圖像并為人臉檢測做準備:

#loadtheinputimage,resizeit,andconvertittograyscale

image=cv2.imread(args["image"])

image=imutils.resize(image,width=800)

gray=cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)

#showtheoriginalinputimageanddetectfacesinthegrayscale

#image

cv2.imshow("Input",image)

rects=detector(gray,2)

加載由命令行參數(shù)--image指定的圖像。調(diào)整圖像的大小,保持第25行的縱橫比,使其寬度為800像素。然后將圖像轉(zhuǎn)換為灰度。

處理輸入圖像中的人臉檢測,我們在其中應(yīng)用了dl

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論