【问题标题】:How do I invert an affine transformation with translation, rotation, and scaling?如何通过平移、旋转和缩放来反转仿射变换?
【发布时间】:2015-05-29 18:46:44
【问题描述】:

我有一个 4x4 矩阵,其中包含平移、旋转和缩放组件,但没有剪切或其他转换。我如何找到它的倒数?我在 C++ 中使用 Eigen 库。

【问题讨论】:

    标签: c++ linear-algebra eigen


    【解决方案1】:

    这很难做到,因为操作需要以正确的顺序执行:

    template<class Derived>
    Matrix4f AffineInverse(const Eigen::MatrixBase<Derived>& mat)
    {
        Matrix3f RotSclInv = (
            mat.block<3, 3>(0, 0).array().rowwise()
            / mat.block<3, 3>(0, 0).colwise().squaredNorm().array() //scaling
            ).transpose(); //rotation
        return (Matrix4f(4,4) << RotSclInv
            , -RotSclInv * mat.block<3, 1>(0, 3) //translation
            , 0, 0, 0, 1).finished();
    }
    

    正如this answer所说,左上角3x3块的逆可以单独计算:

    inv ([ A b ]) = [inv(A)  -inv(A)*b]
        ([ 0 1 ])   [  0          1   ]
    

    左上块的关键见解是缩放和旋转等于正交(旋转)矩阵Q 乘以对角线(缩放)矩阵DQ*D。要反转它,请做一些线性代数:

      inv(Q*D)
    = transp(transp(inv(Q*D)))
    = transp(inv(transp(Q*D)))
    = transp(inv(transp(D)*transp(Q)))
    

    (参见this proof),因为D 是对角线,而Q 是正交线,

    = transp(inv(D*inv(Q)))
    = transp(Q*inv(D))).
    

    Q*inv(D) 很容易找到:因为在Q*D 中,每一列都是Q(这是一个单位向量)的一列乘以D(这是一个标量)的一个条目,这就足够了将每一列除以其范数的平方。这就是函数的前三行所做的。

    完全写成线性代数形式:

    inv ([ Q*D b ]) = [transp(Q*inv(D))  -transp(Q*inv(D))*b]
        ([ 0   1 ])   [       0                 1           ]
    

    【讨论】:

    • 你能解释一下你是如何从 transp(transp(inv(QD))) 到 transp(inv(transp(QD))) 的吗?我理解 transp(X) = inv(X) 如果 X 是正交矩阵,它只适用于旋转矩阵,但不适用于比例旋转矩阵。
    • @bysreg 对于任何可逆矩阵,该恒等式实际上都是正确的。见the proof here.
    • 谢谢。该链接证明了 transp(inv(M)) = inv(transp(M))。但是,为了清楚起见, transp(X) = inv(X) 仅适用于正交(不仅是正交,我在之前的评论中提到过)。但是,是的,这个证据回答了我的问题
    • 这是什么原因不能表示为具有inverse() 方法的特征变换?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-02-09
    • 2011-12-09
    • 2016-05-18
    • 2010-10-09
    • 2020-01-01
    • 1970-01-01
    • 2020-01-22
    相关资源
    最近更新 更多