SimilarityTransform 相似变换
源码及中文注释:
class SimilarityTransform(EuclideanTransform):
"""2d的相似变换
具有以下形式
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
s是缩放比例因子 and the 变换矩阵 is::
[[a0 b0 a1]
[b0 a0 b1]
[0 0 1]]
根据上面公式可以推出:
a0=s * cos(rotation),b0= s* sin(rotation),
The similarity transformation extends the Euclidean transformation with a
single scaling factor in addition to the rotation and translation
parameters.
Parameters输入参数:
----------
matrix : (3, 3)
3*3的变换矩阵
scale : 缩放因子 即S
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.
输出的 3*3的变换矩阵
"""
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:
#"不能同时指定params 和 变换矩阵"
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 # "若定义了变换矩阵,直接把变换矩阵赋给self.params"
elif params:
#若params不为空 any(param is not None
for param in (scale, rotation, translation))
#补全初始值
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.
"""
"""直接调_umeyama。。。"""
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
使用方法:
import numpy as np
from skimage import transform as trans
s = np.array([[54.796, 49.990], [60.771, 50.115], [76.673, 69.007],
[55.388, 89.702], [61.257, 89.050]],
dtype=np.float32)
d=np.array([[64.796, 69.990], [62.771, 20.115], [36.673, 69.007],
[5.38, 89.702], [31.27, 89.050]],
dtype=np.float32)
tform = trans.SimilarityTransform()
tform.estimate(s,d)
print(tform.params)
输出:
[[ 0.92445535 -0.91056038 46.4181614 ]
[ 0.91056038 0.92445535 -52.99583289]
[ 0. 0. 1. ]]