我们可以将pandas 数据帧转换为numpy 数组,估计仿射变换并应用估计的变换如下:
# randomly-generated sample datapoints
data1 = np.random.multivariate_normal(mean=np.zeros(2), cov=[[10,0],[0,1]], size=1000)
data2 = np.zeros_like(data1)
# apply an affine transform,
# e.g., apply rotation + translation
# to transform data1 into data2
# (could apply shear / scaling here too)
tx, ty, theta = 2, -2, np.pi/6
print(tx, ty, theta)
# 2 -2 0.5235987755982988
data2[:,0] = data1[:,0]*np.cos(theta)-data1[:,1]*np.sin(theta) + tx
data2[:,1] = data1[:,0]*np.sin(theta)+data1[:,1]*np.cos(theta) + ty
# visualize the datasets
现在使用skimage.tramsform 中的estimate_transform() 使用最小二乘法估计仿射变换:
from skimage.transform import estimate_transform
tform = estimate_transform('affine', data1, data2)
par = tform.params
print(par) # the estimated affine transformation matrix (in homogeneous coordinates)
# [[ 0.8660254 -0.5 2. ]
# [ 0.5 0.8660254 -2. ]
# [ 0. 0. 1. ]]
tx_, ty_ = par[0,-1], par[1,-1]
theta_ = np.arccos(par[0,0])
print(tx_, ty_, theta_)
# 1.9999999999999996 -1.9999999999999993 0.5235987755982978
从上面注意到,估计的参数非常接近原始仿射变换参数。
现在使用估计的参数将data1 转换为data2_ 并可视化。
data2_ = np.zeros_like(data1)
data2_[:,0] = data1[:,0]*np.cos(theta_)-data1[:,1]*np.sin(theta_) + tx_
data2_[:,1] = data1[:,0]*np.sin(theta_)+data1[:,1]*np.cos(theta_) + ty_
plt.scatter(data1[:,0], data1[:,1], alpha=0.2, label='data1')
plt.scatter(data2_[:,0], data2_[:,1], alpha=0.2, label='data2 estimated')
plt.legend()
np.allclose(data2, data2_)
# True
从上面我们可以看出,原始的data2和使用估计参数应用仿射变换得到的data2_几乎相同。