三维仿射变换与七参数计算

三维七参数转换模型

三维仿射变换的一般形式

[ X Y Z ] = [ Δ X Δ Y Δ Z ] + ( 1 + m ) [ 1 θ z − θ y − θ z 1 θ x θ y − θ x 1 ] [ X 0 Y 0 Z 0 ] \begin{bmatrix} {X}\\ {Y}\\ {Z} \end{bmatrix}=\begin{bmatrix} {\Delta X}\\ {\Delta Y}\\ {\Delta Z} \end{bmatrix}+(1+m)\begin{bmatrix} {1}&{\theta_z}&{-\theta_y} \\ {-\theta_z}&{1}&{\theta_x} \\ {\theta_y}&{-\theta_x}&{1} \end{bmatrix} \begin{bmatrix} {X_0}\\ {Y_0}\\ {Z_0} \end{bmatrix} XYZ=ΔXΔYΔZ+(1+m)1θzθyθz1θxθyθx1X0Y0Z0

变换方程

[ X Y Z ] = [ 1 0 0 0 − Z 0 Y 0 X 0 0 1 0 ( Z 0 0 − X 0 Y 0 0 0 1 − Y 0 X 0 0 Z 0 ] [ Δ X Δ Y Δ Z ( 1 + m ) θ x ( 1 + m ) θ y ( 1 + m ) θ z ( 1 + m ) ] \begin{bmatrix} {X }\\ {Y }\\ {Z } \end{bmatrix} = \begin{bmatrix} {1}&{0}&{0}&{0}&{-Z_0}&{Y_0}&{X_0} \\ {0}&{1}&{0}&{(Z_0}&{0}&{-X_0}&{Y_0} \\ {0}&{0}&{1}&{-Y_0}&{X_0}&{0}&{Z_0} \end{bmatrix} \begin{bmatrix} {\Delta X}\\ {\Delta Y}\\ {\Delta Z}\\ {(1+m)\theta_x}\\ {(1+m)\theta_y}\\ {(1+m)\theta_z}\\ {(1+m)} \end{bmatrix} XYZ=1000100010(Z0Y0Z00X0Y0X00X0Y0Z0ΔXΔYΔZ(1+m)θx(1+m)θy(1+m)θz(1+m)

间接平差求解

B = [ 1 0 0 0 − Z 0 Y 0 X 0 0 1 0 Z 0 0 − X 0 Y 0 0 0 1 − Y 0 X 0 0 Z 0 ] B=\begin{bmatrix} {1}&{0}&{0}&{0}&{-Z_0}&{Y_0}&{X_0} \\ {0}&{1}&{0}&{Z_0}&{0}&{-X_0}&{Y_0} \\ {0}&{0}&{1}&{-Y_0}&{X_0}&{0}&{Z_0} \end{bmatrix} B=1000100010Z0Y0Z00X0Y0X00X0Y0Z0
l = [ x d e s t − x s r c y d e s t − y s r c . . . . . . . . . ] l=\begin{bmatrix} x_{dest}-x_{src}\\ y_{dest}-y_{src} \\ ... \\ ... \\ ... \end{bmatrix}\\ l=xdestxsrcydestysrc.........
求解的参数:
X = [ Δ X Δ Y Δ Z ( 1 + m ) θ x ( 1 + m ) θ y ( 1 + m ) θ z ( 1 + m ) ] X=\begin{bmatrix} {\Delta X}\\ {\Delta Y}\\ {\Delta Z}\\ {(1+m)\theta_x}\\ {(1+m)\theta_y}\\ {(1+m)\theta_z}\\ {(1+m)} \end{bmatrix} X=ΔXΔYΔZ(1+m)θx(1+m)θy(1+m)θz(1+m)

最小二乘原理:
V T P V = m i n V^TPV=min VTPV=min
得:
W = B T P l X = ( B T P B ) − 1 W σ 2 = V T P V σ = V T P V n − t W=B^TPl\\ X=(B^TPB)^{-1}W \\ \sigma ^2 =V^TPV\\ \sigma =\sqrt{\frac{V^TPV}{n-t}} W=BTPlX=(BTPB)1Wσ2=VTPVσ=ntVTPV

Eigen3代码实现

#define SEC_TO_RAD 4.84813681109535993589914102357e-6

struct Data {
    double X;
    double Y;
    double Z;
};

void calculate(const QList<Data> &srcData, const QList<Data> &destData)
{
    if(srcData.count()!=destData.count())
        return;
    if(srcData.count()<3)
        return;
    int  n=srcData.count()*3;

    MatrixXd B = MatrixXd::Zero(n, 7);
    MatrixXd l = MatrixXd::Zero(n, 1);

    for (int i = 0; i < n; i++)
    {
        if (i % 3 == 0)
        {
            B(i, 0) = 1;
            B(i, 1) = 0;
            B(i, 2) = 0;
            B(i, 3) = 0;
            B(i, 4) = -srcData[i / 3].Z;
            B(i, 5) = srcData[i / 3].Y;
            B(i, 6) = srcData[i / 3].X;
            l(i, 0) = destData[i / 3].X - srcData[i / 3].X;
        }
        else if (i % 3 == 1)
        {
            B(i, 0) = 0;
            B(i, 1) = 1;
            B(i, 2) = 0;
            B(i, 3) = srcData[i / 3].Z;
            B(i, 4) = 0;
            B(i, 5) = -srcData[i / 3].X;
            B(i, 6) = srcData[i / 3].Y;
            l(i, 0) = destData[i / 3].Y - srcData[i / 3].Y;
        }
        else
        {
            B(i, 0) = 0;
            B(i, 1) = 0;
            B(i, 2) = 1;
            B(i, 3) = -srcData[i / 3].Y;
            B(i, 4) = srcData[i / 3].X;
            B(i, 5) = 0;
            B(i, 6) = srcData[i / 3].Z;
            l(i, 0) = destData[i / 3].Z - srcData[i / 3].Z;
        }
    }
    MatrixXd BTB = B.transpose()*B;
    MatrixXd W = B.transpose()*l;
    MatrixXd Para = BTB.inverse()*W;
    MatrixXd V = B * Para - l;
    MatrixXd sigma2 = V.transpose()*V;
    //转化为 proj4 + towgs参数
    _dx=Para(0, 0);
    _dy=Para(1, 0);
    _dz=Para(2, 0);
    
    _rotationX= -Para(3, 0)/SEC_TO_RAD;
    _rotationY= -Para(4, 0)/SEC_TO_RAD;
    _rotationZ= -Para(5, 0)/SEC_TO_RAD;

    _scale=Para(6, 0)*1000000.0;
    //误差
    _sigma2=sqrt(sigma2(0,0)/(n-7));

}

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个示例程序,该程序演示了如何使用Eigen库进行三维仿射变换: ```cpp #include <iostream> #include <Eigen/Dense> using namespace Eigen; int main() { // 创建一个3x3的旋转矩阵 Matrix3f rotation; float angle = M_PI / 4; //旋转角度为45度 rotation << cos(angle), -sin(angle), 0, sin(angle), cos(angle), 0, 0, 0, 1; // 创建一个3x1的平移向量 Vector3f translation(1, 2, 3); // 创建一个4x4的仿射变换矩阵 Matrix4f transform; transform.setIdentity(); // 初始化为单位矩阵 transform.block(0, 0, 3, 3) = rotation; // 将旋转矩阵赋值给变换矩阵的前三行前三列 transform.block(0, 3, 3, 1) = translation; // 将平移向量赋值给变换矩阵的前三行最后一列 // 创建一个3x1的向量作为待变换向量 Vector3f v(1, 0, 0); // 进行仿射变换 Vector4f v_transformed = transform * v.homogeneous(); // 先将向量转换为齐次坐标形式(添加一维为1的分量),再进行矩阵乘法 // 输出变换后的向量 std::cout << "变换前向量:" << v.transpose() << std::endl; std::cout << "变换后向量:" << v_transformed.head<3>().transpose() << std::endl; // 齐次坐标形式下,变换后向量的前三个分量为变换后的向量 return 0; } ``` 在上面的示例代码中,我们使用Eigen库创建了一个3x3的旋转矩阵和一个3x1的平移向量,并将它们合并为一个4x4的仿射变换矩阵。然后,我们创建了一个3x1的向量,并使用变换矩阵对其进行仿射变换。最后,我们输出了变换前后的向量。 需要注意的是,在进行仿射变换时,需要将向量转换为齐次坐标形式(添加一维为1的分量),再进行矩阵乘法。变换后的向量也需要再次转换为非齐次坐标形式(去掉最后一维分量)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值