c++ - 如何通过平移、旋转和缩放反转仿射变换?

标签 c++ linear-algebra eigen

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

最佳答案

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

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 block 的逆可以单独计算:

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

左上角 block 的关键见解是缩放和旋转等于正交(旋转)矩阵 Q 乘以对角线(缩放)矩阵 D: Q*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 的列(这是单位 vector )乘以 D 的条目(这是一个标量),足以将每一列除以其范数的平方。这就是函数的前三行所做的。

完全以线性代数形式写出:

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

关于c++ - 如何通过平移、旋转和缩放反转仿射变换?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30536920/

相关文章:

C++ 模板和 OpenBLAS

c++ - 如何从预处理程序#if指令调用constexpr函数?

c++ - 这个递归函数在 C++ 中是如何工作的?

c++ - 当鼠标移出窗口时 SFML 窗口自行关闭

c++ - Heap/C++ 标准库使用 Under Green Hills INTEGRITY

python - 找出两个对称矩阵是否相同直到行/列的排列

创建基于矢量的拼图的算法

数学 - 映射数字

c++ - 为 Eigen 类型特化一个函数

c++ - Eigen 复制构造函数 vs. operator= 性能