如图所示,上面尺寸250*250,进行人脸对齐后为下图尺寸112*112
相关代码:
在deploy/face_model.py中的类FaceModel里加入如下函数:
在delopy/test.py中执行代码:
对齐方法为相似变换:
trans.SimilarityTransform用最小二乘法估计出最优变换矩阵的参数
tform = trans.SimilarityTransform()
tform.estimate(dst, src)
M = tform.params[0:2,:]
warped = cv2.warpAffine(img,M,image_size[1],image_size[0]), borderValue = 0.0)
参考face_process.py中的函数preprocess
相似变换:
共有三组参数:缩放scale s, 旋转rotation theta, 平移translation tx ty
更多变换参考https://blog.csdn.net/fengziyihang/article/details/81811185
相似变换类定义如下,其中说明了相似变换矩阵的形式和参数:
class SimilarityTransform(EuclideanTransform):
"""2D similarity transformation.
Has the following form::
X = a0 * x - b0 * y + a1 =
= s * x * cos(rotation) - s * y * sin(rotation) + a1
Y = b0 * x + a0 * y + b1 =
= s * x * sin(rotation) + s * y * cos(rotation) + b1
where ``s`` is a scale factor and the homogeneous transformation matrix is::
[[a0 b0 a1]
[b0 a0 b1]
[0 0 1]]
The similarity transformation extends the Euclidean transformation with a
single scaling factor in addition to the rotation and translation
parameters.
Parameters
----------
matrix : (3, 3) array, optional
Homogeneous transformation matrix.
scale : float, optional
Scale factor.
rotation : float, optional
Rotation angle in counter-clockwise direction as radians.
translation : (tx, ty) as array, list or tuple, optional
x, y translation parameters.
Attributes
----------
params : (3, 3) array
Homogeneous transformation matrix.
"""
def __init__(self, matrix=None, scale=None, rotation=None,
translation=None):
params = any(param is not None
for param in (scale, rotation, translation))
if params and matrix is not None:
raise ValueError("You cannot specify the transformation matrix and"
" the implicit parameters at the same time.")
elif matrix is not None:
if matrix.shape != (3, 3):
raise ValueError("Invalid shape of transformation matrix.")
self.params = matrix
elif params:
if scale is None:
scale = 1
if rotation is None:
rotation = 0
if translation is None:
translation = (0, 0)
self.params = np.array([
[math.cos(rotation), - math.sin(rotation), 0],
[math.sin(rotation), math.cos(rotation), 0],
[ 0, 0, 1]
])
self.params[0:2, 0:2] *= scale
self.params[0:2, 2] = translation
else:
# default to an identity transform
self.params = np.eye(3)
def estimate(self, src, dst):
"""Estimate the transformation from a set of corresponding points.
You can determine the over-, well- and under-determined parameters
with the total least-squares method.
Number of source and destination coordinates must match.
Parameters
----------
src : (N, 2) array
Source coordinates.
dst : (N, 2) array
Destination coordinates.
Returns
-------
success : bool
True, if model estimation succeeds.
"""
self.params = _umeyama(src, dst, True)
return True
@property
def scale(self):
if abs(math.cos(self.rotation)) < np.spacing(1):
# sin(self.rotation) == 1
scale = self.params[1, 0]
else:
scale = self.params[0, 0] / math.cos(self.rotation)
return scale