You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

scikit-image中映射坐标时,为何反转相似变换的旋转才有效?

问题描述

我有一组点,其中包含一个45-45-90直角三角形的3个顶点,还有一组需映射到这些顶点的点a,具体定义如下:

import numpy as np

points = np.array([
    ( 90, 416),
    (398, 390),
    (374,  84)
])

a = np.array([
    (0, 1),  # 映射到 (90, 416)
    (1, 1),  # 映射到 (398, 390)
    (1, 0)   # 映射到 (374, 84)
])

我希望找到能将a正确映射到points的相似变换(similarity transformation),于是使用skimage.transform执行如下操作:

from skimage import transform

# 我认为合理的变换
T1 = transform.estimate_transform(
    ttype="similarity",
    src=a,
    dst=points
)

# 无理由反转旋转,仅为验证有效性
T2 = transform.SimilarityTransform(
    scale=T1.scale,
    rotation=-T1.rotation,
    translation=T1.translation
)

# 通过矩阵乘法应用变换
a_T1 = a @ T1.params[:2, :2] + T1.params[:2, 2]
a_T2 = a @ T2.params[:2, :2] + T2.params[:2, 2]

为何仅反转T1的旋转得到的T2能产生更优的映射效果?或是我的实现存在错误?相关效果可参考附图。

问题分析与解答

核心问题出在相似变换的矩阵乘法顺序上:

skimage.transform.SimilarityTransform的变换逻辑是列向量左乘矩阵,公式为:
$$\begin{bmatrix}x'\y'\1\end{bmatrix} = T.params \cdot \begin{bmatrix}x\y\1\end{bmatrix}$$
但你在代码中使用的是行向量右乘矩阵:a @ T1.params[:2, :2] + T1.params[:2, 2],这和Skimage内置的变换逻辑完全相反。

由于旋转矩阵是正交矩阵(转置等于逆矩阵),行向量右乘旋转矩阵$R$,等价于列向量左乘$R^T$,也就是反向旋转。这就导致:

  1. estimate_transform得到的T1是符合列向量左乘逻辑的正确变换;
  2. 你用行向量右乘的方式应用T1时,相当于做了反向旋转+缩放+平移,结果自然不符合预期;
  3. 手动反转T1的旋转得到T2后,再用行向量右乘,刚好抵消了矩阵乘法顺序的错误,得到了正确的映射效果。

修正方案

有两种方式可以得到正确结果:

  1. 遵循Skimage原生逻辑,直接调用变换对象的函数:
a_T1_correct = T1(a)
  1. 保持行向量右乘的方式,但对变换矩阵做转置:
a_T1_correct = a @ T1.params[:2, :2].T + T1.params[:2, 2]

这样就无需手动反转旋转角,就能得到和T2一致的正确映射结果。

内容的提问来源于stack exchange,提问作者lanery

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 20:57:46