在过去的几个月里,我每天都在拍摄我的脸部照片,结果是从同一地点拍摄了一系列图像,但我的脸部方向略有不同。我已经尝试了几种方法来使用 Python 和 OpenCV 稳定这个序列,成功率各不相同。我的问题是:“我现在的流程是解决这个问题的最佳方法,还是有更好的技术/顺序来执行事情?”
到目前为止,我的过程如下所示:
- 收集图像,保留原始图像,缩小版和缩小版灰度
- 在灰度图像上使用
dlib.get_frontal_face_detector()
,得到一个face
包含我的脸的矩形。 - 使用
dlib
shape-predictor68_face_landmarks.dat
,获取68 个面部标志的坐标,并提取眼睛、鼻子、下巴和嘴巴的位置(具体为标志 8、30、36、45、48 和 54) - 使用我的脸的 3D 表示(即
numpy
包含在任意参考框架中我真实实际脸上的这些地标的近似值的 3D 坐标的数组),并cv2.solvePnP
计算透视变换矩阵M1
以将脸与我的 3D 表示对齐 - 使用变换后的面部标志(即)
cv2.projectPoints(face_points_3D, rvec, tvec, ...)
,_, rvec, tvec = cv2.solvePnP(...)
计算垂直对齐眼睛所需的 2D 旋转和平移,将它们水平居中并将它们放置在彼此固定的距离上,并获得变换矩阵M2
。 - 使用
M = np.matmul(M2, M1)
和cv2.warpPerspective
,扭曲图像。
使用这种方法,我得到了不错的结果,但似乎 68 个地标预测远非完美,导致不稳定的稳定性和有时非常倾斜的图像(因为我不记得有这么大的前额......)。例如,一个眼角的地标预测并不总是与实际眼睛对齐,导致实际眼睛向下倾斜 20px 的透视变换。
为了解决这个问题,我尝试使用SIFT
在两张不同的照片中查找特征(使用上述方法对齐)并获得另一个透视变换。然后我强制特征位于我检测到的面部标志周围的某个位置,以免与背景对齐(使用 中的蒙版cv2.SIFT_create().detectAndCompute(...)
),但这有时会导致仅(或主要)仅在一只眼睛周围找到特征,或者不在眼睛周围找到特征。嘴,再次导致图像极度歪斜。
什么是获得平稳图像序列并稳定在我脸上的好方法?作为参考,这个视频(不是我的,它在眼睛周围稳定)。