C#代码实现九点标定

在不通过Halcon、OpenCV、MATLAB等算法库的情况下完成九点标定


结果:计算结果与Halcon计算结果完全一致


一、九点标定算法原理

基本原理参考以下文章

九点标定基本原理


二、九点坐标情况下的最小二乘拟合

当输入有 n 个坐标时,我们的矩阵可以写成以下形式
[ x 1 y 1 1 x 2 y 2 1 : : : : : : x 9 y 9 1 ] [ a 1 b 1 c 1 ] = [ X 1 X 2 : : X 9 ] \left[ \begin{matrix} x1 & y1& 1 \\ x2 & y2& 1 \\ :& :& :& \\ :& :& :& \\ x9 & y9& 1 \\ \end{matrix} \right] \left[ \begin{matrix} a1 \\ b1 \\ c1 \\ \end{matrix} \right] = \left[ \begin{matrix} X1 \\ X2 \\ : \\ : \\ X9 \\ \end{matrix} \right] x1x2::x9y1y2::y911::1 a1b1c1 = X1X2::X9
[ x 1 y 1 1 x 2 y 2 1 : : : : : : x 9 y 9 1 ] [ a 2 b 2 c 2 ] = [ Y 1 Y 2 : : Y 9 ] \left[ \begin{matrix} x1 & y1& 1 \\ x2 & y2& 1 \\ :& :& :& \\ :& :& :& \\ x9 & y9& 1 \\ \end{matrix} \right] \left[ \begin{matrix} a2 \\ b2 \\ c2 \\ \end{matrix} \right] = \left[ \begin{matrix} Y1 \\ Y2 \\ : \\ : \\ Y9 \\ \end{matrix} \right] x1x2::x9y1y2::y911::1 a2b2c2 = Y1Y2::Y9

算法中间过程:最小二乘算法详解

化简结果:
[ a b c ] = ( X T X ) − 1 X T Y \left[ \begin{matrix} a \\ b \\ c \\ \end{matrix} \right] = (X^{T}X)^{-1}X^{T}Y\\ abc =(XTX)1XTY
X = a 1 × x + b 1 × y + c 1 Y = a 2 × x + b 2 × y + c 2 X=a1\times x+ b1\times y+c1\\ Y=a2\times x+ b2\times y+c2\\ X=a1×x+b1×y+c1Y=a2×x+b2×y+c2


三、C#算法的实现

1.首先求出矩阵X的转置,参考往期博文

C#实现矩阵求转置

2.求出转置后的矩阵X’与原矩阵X的乘积

已知原矩阵为3×9的矩阵,因此转置后可得到一个9×3的矩阵,两者进行相乘运算得到一个

3×3的矩阵

矩阵相乘代码:

public static double[,] MatMul(double[,] input1, double[,] input2)
{
      int y = input1.GetLength(0);
      int x = input2.GetLength(1);
      int len = input2.GetLength(0);
      double[,] ansxtx = new double[y, x];

      for (int i = 0; i < y; i++)           //矩阵xt的行数
      {
          for (int j = 0; j < x; j++)        //矩阵x的列数
           {
              double a = 0;                  //单个元素的乘积
              for (int k = 0; k < len; k++)
              {
                 a = a + input1[i, k] * input2[k, j];   //矩阵xt的第i行k列与矩阵x的第k行j列的乘积
              }
               ansxtx[i, j] = a;            //将矩阵xt的i行与矩阵x的j列的乘积放入新矩阵的i行j列
           }
       }
       return ansxtx;
}

3.求出矩阵X的转置与矩阵X的乘积XTX的逆

C#实现矩阵求逆

4.求出逆后再次与矩阵X的转置进行相乘

5.最后将上述结果与Y矩阵相乘

完整代码如下

           int length = listView1.Items.Count;
            double[,] orgp = new double[length, 3];
            for (int i = 0; i < length; i++)
            {
                orgp[i, 0] = double.Parse(listView1.Items[i].SubItems[1].Text);  //添加像素坐标
                orgp[i, 1] = double.Parse(listView1.Items[i].SubItems[2].Text);
                orgp[i, 2] = 1;
            }
          
            double[,] rx = new double[length, 1];
            double[,] ry = new double[length, 1];
            for (int i = 0; i < length; i++)
            {
                rx[i, 0] = double.Parse(listView1.Items[i].SubItems[3].Text);  //添加机器坐标
                ry[i, 0] = double.Parse(listView1.Items[i].SubItems[4].Text);
            }
    
            double[,] MatT = Matrix.MatrixT(orgp);      //进
            double[,] xtx = Matrix.MatMul(MatT, orgp);  //行
            double[,] inv = Matrix.inv3(xtx);           //矩
            double[,] invxt = Matrix.MatMul(inv, MatT); //阵
            double[,] QX = Matrix.MatMul(invxt, rx);    //运
            double[,] QY = Matrix.MatMul(invxt, ry);    //算

            textBox5.Text = "Qx = " + QX[0,0].ToString("f5")
                     + "X+" + QX[1,0].ToString("f5")
                     + "Y+" + QX[2,0].ToString("f5") + "\r\n" +
                    "Qy = " + QY[0,0].ToString("f5")
                     + "X+" + QY[1,0].ToString("f5")
                     + "Y+" + QY[2,0].ToString("f5");

            prx.Add(QX[0, 0]);
            prx.Add(QX[1, 0]);
            prx.Add(QX[2, 0]);

            pry.Add(QY[0, 0]);
            pry.Add(QY[1, 0]);
            pry.Add(QY[2, 0]);

最终得到相应的两个平面坐标系的转换关系

Qx、Qy为被求平面的坐标,x、y为已知平面的坐标
Q x = Q x [ 0 ] × x + Q x [ 1 ] × y + Q x [ 2 ] Q y = Q y [ 0 ] × x + Q y [ 1 ] × y + Q y [ 2 ] Qx=Qx[0] \times x+ Qx[1]\times y+Qx[2]\\ Qy=Qy[0] \times x+ Qy[1]\times y+Qy[2] Qx=Qx[0]×x+Qx[1]×y+Qx[2]Qy=Qy[0]×x+Qy[1]×y+Qy[2]

  • 14
    点赞
  • 104
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 17
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 17
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

未来超低端科技研究所

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值