iT邦幫忙

2021 iThome 鐵人賽

DAY 25
0

有了前兩天的人臉關鍵點偵測後,我們今天終於要談到人臉對齊 (Facial Alignment)這個工作了!

在前面系列或多或少都有提到人臉對齊是很重要的,因為

  • 人臉識別 (特徵臉方法局部二值方法等)功能,如果人臉是正面臉會大大提高辨識的準確率
  • 人臉的特徵對電腦來說就是數值,而對齊可以看成數值的正規化

人臉對齊的精神很簡單:

透過縮放、移動、旋轉等操作,讓不同人臉的相對位置盡可能相同

作法大概可以分為兩種

  • 透過事先定義的3D模型,將輸入的人臉圖片關鍵點轉換成對應3D模型的位置
  • 直接透過辨識的人臉關鍵點,做相對位置的轉換

我們今天要使用的做法就是第二種。

本文開始

  1. 開啟專案,新增目錄facial_landmark
  2. 在上述目錄下新增dlib_with_imutils.py檔案
  3. 程式碼與說明:
    import ntpath
    import sys
    
    # resolve module import error in PyCharm
    sys.path.append(ntpath.dirname(ntpath.dirname(ntpath.abspath(__file__))))
    
    import argparse
    import os
    from bz2 import decompress
    from urllib.request import urlretrieve
    
    import cv2
    import dlib
    import numpy as np
    from imutils.face_utils import rect_to_bb
    from imutils.face_utils.facealigner import FaceAligner
    
    from face_detection.dlib_mmod import detect
    
    
    def main():
        # 初始化arguments
        ap = argparse.ArgumentParser()
        ap.add_argument("-i", "--image", required=True, help="path to input image")
        args = vars(ap.parse_args())
    
        # 初始化68-points facial landmark模型
        model_url = f"https://github.com/davisking/dlib-models/raw/master/shape_predictor_68_face_landmarks_GTX.dat.bz2"
        model_name = "shape_predictor_68_face_landmarks_GTX.dat"
        if not os.path.exists(model_name):
            urlretrieve(model_url, model_name + ".bz2")
            with open(model_name, "wb") as new_file, open(model_name + ".bz2", "rb") as file:
                data = decompress(file.read())
                new_file.write(data)
            os.remove(model_name + ".bz2")
        predictor = dlib.shape_predictor(model_name)
    
        # 初始化Face Aligner
        aligner = FaceAligner(predictor, desiredFaceWidth=256)
    
        # 載入圖片並偵測人臉
        image = cv2.imread(args["image"])
        gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
        rects = detect(image, return_ori_result=True)
    
        for rect in rects:
            (x, y, w, h) = rect_to_bb(rect)
            orign_face = cv2.resize(image[y:y + h, x:x + w], (256, 256))
            # 注意:如果此方法丟出getRotationMatrix2D()的型別錯誤,請將opencv-contrib-python的版本降版到4.1
            align_face = aligner.align(image, gray, rect)
    
            # 顯示結果
            result = np.hstack([orign_face, align_face])
            cv2.imshow("Result", result)
            cv2.waitKey(0)
    
    
    if __name__ == '__main__':
        main()
    
    
  4. 在terminal輸入python facial_alignment/dlib_with_imutils.py -i {你要辨識的照片.jpg},範例輸出為 (左側為原始圖片中的人臉ROI,右側為對齊後的人臉):

alignment_1

alignment_2

結論

  1. 透過人臉關鍵點來做人臉對齊,我們這次使用的主要是透過imutils套件裡的FaceAligner.align()方法
    • 這個方法主要是把兩眼的中心點當作是旋轉中心、兩眼間與水平線之間的角度當作是旋轉角度,來達到人臉對齊的工作。
  2. 上述的範例結果可以看到不同的照片對齊後的人臉,基本都達到相對五官位置的對齊
  3. 上述範例的第二個結果,刻意找一個人臉不是完全面對鏡頭的照片,比較結果你可以發現:使用人臉關鍵點做人臉對齊實際上只是"2D平面的對齊";側面臉對齊後還是側面臉
    • 一個解法是使用開頭說到的3D模型對齊方法
    • 另一個在後續實際應用會提到一種預估臉部面對方向的方法,也可以用來做人臉對齊

Let's All, 今日程式碼參考在這


上一篇
[Day 24] Facial Landmark: MTCNN
下一篇
[Day 26] 應用一:威利在哪裡?
系列文
[Computer Vision] 電腦視覺下的人臉30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
ssbin
iT邦新手 5 級 ‧ 2022-07-23 14:44:39

回報執行狀況喔。我使用Python 3.10.5 + imutils 0.5.4,在使用 FaceAligner.align()時會報錯:
File "\imutils\face_utils\facealigner.py", line 68, in align
M = cv2.getRotationMatrix2D(eyesCenter, angle, scale)
TypeError: Can't parse 'center'. Sequence item with index 0 has a wrong type

直接進到facealigner.py,修改64行,把eyesCenter都補上int,就可以正常執行了。竟然是函式庫的型態出錯。

感謝回報~

通常我不太建議去修改package的原始程式碼...這個問題在imutils的github有相關issue (還未resolved),可能要等他們修正,或是參考我在程式碼註解的解法:

# 注意:如果此方法丟出getRotationMatrix2D()的型別錯誤,請將opencv-contrib-python的版本降版到4.1
align_face = aligner.align(image, gray, rect)

我要留言

立即登入留言