人臉檢測(cè)實(shí)戰(zhàn)終極:使用 OpenCV 和 Python 進(jìn)行人臉對(duì)齊

      網(wǎng)友投稿 1059 2022-05-30

      使用 OpenCV 和 Python 進(jìn)行人臉對(duì)齊

      這篇博文的目的是演示如何使用 OpenCV、Python 和面部標(biāo)志對(duì)齊人臉。

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

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

      在圖像中居中。

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

      進(jìn)行縮放,使面的大小大致相同。

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

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

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

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

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

      面部對(duì)齊算法本身基于 Mastering OpenCV with Practical Computer Vision Projects (Baggio, 2012) 的第 8 章,如果您有 C++ 背景或興趣,我強(qiáng)烈推薦它。 本書在 GitHub 上提供了開放訪問(wèn)的代碼示例。

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

      # import the necessary packages from imutils.face_utils.helpers import FACIAL_LANDMARKS_68_IDXS from imutils.face_utils.helpers import FACIAL_LANDMARKS_5_IDXS from imutils.face_utils.helpers import shape_to_np import numpy as np import cv2 class FaceAligner: def __init__(self, predictor, desiredLeftEye=(0.35, 0.35), desiredFaceWidth=256, desiredFaceHeight=None): # store the facial landmark predictor, desired output left # eye position, and desired output face width + height self.predictor = predictor self.desiredLeftEye = desiredLeftEye self.desiredFaceWidth = desiredFaceWidth self.desiredFaceHeight = desiredFaceHeight # if the desired face height is None, set it to be the # desired face width (normal behavior) if self.desiredFaceHeight is None: self.desiredFaceHeight = self.desiredFaceWidth

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      導(dǎo)入必要的包

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

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

      predictor :面部標(biāo)志性預(yù)測(cè)器模型。

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

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

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

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

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

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

      def align(self, image, gray, rect): # convert the landmark (x, y)-coordinates to a NumPy array shape = self.predictor(gray, rect) shape = shape_to_np(shape) # extract the left and right eye (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]

      1

      2

      3

      4

      5

      6

      7

      8

      9

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

      image : RGB 輸入圖像。

      gray :灰度輸入圖像。

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

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

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

      提取leftEyePts 和 rightEyePts 。

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

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

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

      接下來(lái)是角度計(jì)算:

      # compute the center of mass for each eye leftEyeCenter = leftEyePts.mean(axis=0).astype("int") rightEyeCenter = rightEyePts.mean(axis=0).astype("int") # compute the angle between the eye centroids dY = rightEyeCenter[1] - leftEyeCenter[1] dX = rightEyeCenter[0] - leftEyeCenter[0] angle = np.degrees(np.arctan2(dY, dX)) - 180

      1

      2

      3

      4

      5

      6

      7

      分別通過(guò)平均每只眼睛的所有 (x, y) 點(diǎn)來(lái)計(jì)算每只眼睛的質(zhì)心,也稱為質(zhì)心。

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

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

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

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

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

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

      # compute the desired right eye x-coordinate based on the # desired x-coordinate of the left eye desiredRightEyeX = 1.0 - self.desiredLeftEye[0] # determine the scale of the new resulting image by taking # the ratio of the distance between eyes in the *current* # image to the ratio of distance between eyes in the # *desired* image dist = np.sqrt((dX ** 2) + (dY ** 2)) desiredDist = (desiredRightEyeX - self.desiredLeftEye[0]) desiredDist *= self.desiredFaceWidth scale = desiredDist / dist

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      根據(jù)所需的左眼 x 坐標(biāo)計(jì)算所需的右眼。從 1.0 中減去 self.desiredLeftEye[0] 因?yàn)樗璧腞ightEyeX 值應(yīng)該與圖像的右邊緣等距,因?yàn)橄鄳?yīng)的左眼 x 坐標(biāo)與其左邊緣的距離相同。

      然后可以通過(guò)獲取當(dāng)前圖像中眼睛之間的距離與所需圖像中眼睛之間的距離的比率來(lái)確定人臉的比例

      首先,計(jì)算歐幾里得距離比 dist 。

      接下來(lái),使用左右眼 x 值之間的差異,計(jì)算所需的距離,desiredDist。

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

      最后,比例是通過(guò)將 desiredDist 除以我們之前計(jì)算的 dist 來(lái)計(jì)算的。

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

      # compute center (x, y)-coordinates (i.e., the median point) # between the two eyes in the input image eyesCenter = (int((leftEyeCenter[0] + rightEyeCenter[0]) // 2), int((leftEyeCenter[1] + rightEyeCenter[1]) // 2)) # grab the rotation matrix for rotating and scaling the face M = cv2.getRotationMatrix2D(eyesCenter, angle, scale) # update the translation component of the matrix tX = self.desiredFaceWidth * 0.5 tY = self.desiredFaceHeight * self.desiredLeftEye[1] M[0, 2] += (tX - eyesCenter[0]) M[1, 2] += (tY - eyesCenter[1])

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

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

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

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

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

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

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

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

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

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

      使用 tX 和 tY ,通過(guò)從它們對(duì)應(yīng)的眼睛中點(diǎn)值(第 66 行和第 67 行)中減去每個(gè)值來(lái)更新矩陣的平移分量。

      然后應(yīng)用仿射變換來(lái)對(duì)齊人臉:

      # apply the affine transformation (w, h) = (self.desiredFaceWidth, self.desiredFaceHeight) output = cv2.warpAffine(image, M, (w, h), flags=cv2.INTER_CUBIC) # return the aligned face return output

      1

      2

      3

      4

      5

      6

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

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

      image : 人臉圖像。

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

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

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

      最后,對(duì)齊的臉面。

      對(duì)齊人臉

      開始編寫人臉對(duì)齊腳本,將其命名為Now let’s put this alignment class to work with a simple driver script. Open up a new file, name it align_faces.py:

      # import the necessary packages from imutils.face_utils import FaceAligner from imutils.face_utils import rect_to_bb import argparse import imutils import dlib import cv2 # construct the argument parser and parse the arguments ap = argparse.ArgumentParser() ap.add_argument("-p", "--shape-predictor", required=True, help="path to facial landmark predictor") ap.add_argument("-i", "--image", required=True, help="path to input image") args = vars(ap.parse_args())

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

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

      pip install --upgrade imutils pip install --upgrade dlib

      1

      2

      win10安裝dlib參考:如何安裝dlib gpu版本_AI浩-CSDN博客

      # initialize dlib's face detector (HOG-based) and then create # the facial landmark predictor and the face aligner detector = dlib.get_frontal_face_detector() predictor = dlib.shape_predictor(args["shape_predictor"]) fa = FaceAligner(predictor, desiredFaceWidth=256)

      1

      2

      3

      4

      5

      使用 dlib 的 get_frontal_face_detector 初始化我們的檢測(cè)器對(duì)象。

      使用 --shape-predictor 來(lái)實(shí)例化我們的面部標(biāo)志預(yù)測(cè)器,這是 dlib 的預(yù)訓(xùn)練預(yù)測(cè)器的路徑。

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

      接下來(lái),加載圖像并為人臉檢測(cè)做準(zhǔn)備:

      # load the input image, resize it, and convert it to grayscale image = cv2.imread(args["image"]) image = imutils.resize(image, width=800) gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # show the original input image and detect faces in the grayscale # image cv2.imshow("Input", image) rects = detector(gray, 2)

      1

      2

      3

      4

      5

      6

      7

      8

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

      處理輸入圖像中的人臉檢測(cè),我們?cè)谄渲袘?yīng)用了 dlib 的人臉檢測(cè)器。 此函數(shù)返回 rects ,這是我們檢測(cè)器發(fā)現(xiàn)的人臉周圍的邊界框列表。

      在下一個(gè)塊中,我們遍歷 rects ,對(duì)齊每個(gè)人臉,并顯示原始和對(duì)齊的圖像。

      # loop over the face detections for rect in rects: # extract the ROI of the *original* face, then align the face # using facial landmarks (x, y, w, h) = rect_to_bb(rect) faceOrig = imutils.resize(image[y:y + h, x:x + w], width=256) faceAligned = fa.align(image, gray, rect) # display the output images cv2.imshow("Original", faceOrig) cv2.imshow("Aligned", faceAligned) cv2.waitKey(0)

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      人臉檢測(cè)實(shí)戰(zhàn)終極:使用 OpenCV 和 Python 進(jìn)行人臉對(duì)齊

      開始循環(huán)。

      對(duì)于 dlib 預(yù)測(cè)的每個(gè)邊界框 rect,我們將其轉(zhuǎn)換為格式 (x, y, w, h)。

      隨后,將框的大小調(diào)整為 256 像素的寬度,保持縱橫比。將這個(gè)原始但調(diào)整大小的圖像存儲(chǔ)為 faceOrig 。

      對(duì)齊圖像,指定圖像、灰度圖像和矩形。

      最后,將原始和對(duì)應(yīng)的對(duì)齊人臉圖像顯示到各自窗口的屏幕上。

      在顯示下一個(gè)原始/對(duì)齊圖像對(duì)之前,等待用戶在任一窗口處于焦點(diǎn)時(shí)按下一個(gè)鍵。

      對(duì)所有檢測(cè)到的人臉重復(fù)上面的過(guò)程,然后腳本退出。

      展示結(jié)果

      輸入命令:

      python align_faces.py --shape-predictor shape_predictor_68_face_landmarks.dat --image 11.jpg

      1

      完整代碼:

      https://download.csdn.net/download/hhhhhhhhhhwwwwwwwwww/62250043

      OpenCV Python 人臉識(shí)別服務(wù) FRS

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請(qǐng)聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。

      上一篇:(更新時(shí)間)2021年4月8日 Django框架 ORM中查詢?cè)斀?/a>
      下一篇:[學(xué)習(xí)筆記][第二階段][04_Java面向?qū)ο笾蛢?nèi)部類]
      相關(guān)文章
      久久精品国产亚洲av水果派| 亚洲高清国产拍精品26U| 久久亚洲国产成人影院网站 | 亚洲av无码专区在线电影| 亚洲欧洲国产日韩精品| 亚洲午夜国产片在线观看| 日批日出水久久亚洲精品tv| 亚洲av色香蕉一区二区三区| 亚洲国产成人超福利久久精品| 久久久亚洲AV波多野结衣| 亚洲国产精品一区二区久久| 亚洲国产精品一区| 少妇中文字幕乱码亚洲影视| 亚洲AV日韩AV永久无码下载| 亚洲AV人无码综合在线观看| 亚洲今日精彩视频| 亚洲综合久久1区2区3区| 亚洲欧洲精品在线| 亚洲国产精品综合久久2007| 亚洲日本在线播放| 亚洲一区二区三区91| 亚洲色图激情文学| 亚洲国产成人久久精品软件| 毛片亚洲AV无码精品国产午夜| 国产精品亚洲天堂| 亚洲精品无码久久久久AV麻豆| 亚洲伊人久久综合影院| 亚洲一区二区三区AV无码| 亚洲成AV人片在线观看无码| 亚洲精品人成在线观看| 亚洲福利一区二区三区| 亚洲天堂2016| 久久亚洲精品无码av| 亚洲精品线路一在线观看| 自拍偷自拍亚洲精品情侣| 亚洲AV中文无码乱人伦下载 | 亚洲伊人精品综合在合线| 亚洲综合色婷婷在线观看| 亚洲avav天堂av在线网毛片| 伊在人亚洲香蕉精品区麻豆| 国产av无码专区亚洲国产精品|