有了前兩天的人臉關鍵點偵測後,我們今天終於要談到人臉對齊 (Facial Alignment)這個工作了!
在前面系列或多或少都有提到人臉對齊是很重要的,因為
人臉對齊的精神很簡單:
透過縮放、移動、旋轉等操作,讓不同人臉的相對位置盡可能相同
作法大概可以分為兩種
我們今天要使用的做法就是第二種。
facial_landmark
dlib_with_imutils.py
檔案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()
python facial_alignment/dlib_with_imutils.py -i {你要辨識的照片.jpg}
,範例輸出為 (左側為原始圖片中的人臉ROI,右側為對齊後的人臉):imutils
套件裡的FaceAligner.align()
方法
Let's All, 今日程式碼參考在這
回報執行狀況喔。我使用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)