• N点标定-坐标系变换




    1:标定算法

    vector_to_hom_mat2d(Px, Py, Qx, Qy, HomMat2D)
    在这里插入图片描述
    这里参考了halcon算子块的官方文档,使用的是最小二乘法,求HomMat2D矩阵。 -常用九点标定,求两个坐标系的坐标转换。。
    下面个人实现原理,结果和上面算子算出来的结果一致,知识有限,仅供学习交流。
    1:先来看一张图,图中矩阵为2行3列,最后一列为0,0,1;因为用到是齐次矩阵,所以展开就省略了。具体为什么是这样的矩阵形式,其实是一系列的变换,也就是平面二维仿射变换。

    在这里插入图片描述

    2:然后使用最小二乘法列出项(最小平方法)在这里插入图片描述其次在对每个未知量进行求偏导,图中是两个未知量,就是列出两个方程组,如果是三个未知量,那就是三个方程组
    在这里插入图片描述
    三个未知量进行求导,得出来的结果就是对应矩阵里的未知量。。

    3:上面方法都是笔记上演示,如果放在程序里怎么做呢?用上面这种怎么求未知量呢?下面会有个人实现的源代码,这里求方程组使用克拉默法则,列出行列式进行求解,放在代码里,方便求解。

    正确的做法就是求各个未知量的系数,比如:

    在这里插入图片描述
    在这里插入图片描述
    4:核心代码演示

    //保存从界面获取的坐标数据
    struct _coordList{
        QList<QPair<double,double>> pixPoines;//保存像素坐标
        QList<QPair<double,double>> physicsPoines;//保存物理坐标
    };
    
    //保存最小二乘法三个未知量(a,b,c)的结果
    struct _squareLaw{
        double aa=0;
        double bb=0;
        double cc=0;
        double ab=0;
        double ac=0;
        double bc=0;
        double _a=0;
        double _b=0;
        double _c=0;
    };
    //导数3x4
    struct _differentialCoefficient{
        QList<double> diff_a;
        QList<double> diff_b;
        QList<double> diff_c;
    };
    
    //矩阵3X3
    struct _mat{
        double a=0;
        double b=0;
        double c=0;
        double d=0;
        double e=0;
        double f=0;
        double g=0;
        double h=0;
        double i=0;
    };
    
    //标定
    _mat MainWindow::calibration(_coordList coordL)
    {
        //保存未知量(a,b,c)的系数
        _squareLaw squareLaw_x;
        _squareLaw squareLaw_y;
        for(int i=0;i<coordL.pixPoines.count();i++) {
            squareLaw_x.aa += pow(coordL.pixPoines.at(i).first,2)*2;
            squareLaw_x.bb += pow(coordL.pixPoines.at(i).second,2)*2;
            squareLaw_x.cc += 1*2;
            squareLaw_x.ab += coordL.pixPoines.at(i).first*coordL.pixPoines.at(i).second*2;
            squareLaw_x.ac += coordL.pixPoines.at(i).first*2;
            squareLaw_x.bc += coordL.pixPoines.at(i).second*2;
            squareLaw_x._a += coordL.pixPoines.at(i).first*coordL.physicsPoines.at(i).first*2;
            squareLaw_x._b += coordL.pixPoines.at(i).second*coordL.physicsPoines.at(i).first*2;
            squareLaw_x._c += coordL.physicsPoines.at(i).first*2;
        }
    
        for(int i=0;i<coordL.pixPoines.count();i++) {
            squareLaw_y.aa += pow(coordL.pixPoines.at(i).first,2)*2;
            squareLaw_y.bb += pow(coordL.pixPoines.at(i).second,2)*2;
            squareLaw_y.cc += 1*2;
            squareLaw_y.ab += coordL.pixPoines.at(i).first*coordL.pixPoines.at(i).second*2;
            squareLaw_y.ac += coordL.pixPoines.at(i).first*2;
            squareLaw_y.bc += coordL.pixPoines.at(i).second*2;
            squareLaw_y._a += coordL.pixPoines.at(i).first*coordL.physicsPoines.at(i).second*2;
            squareLaw_y._b += coordL.pixPoines.at(i).second*coordL.physicsPoines.at(i).second*2;
            squareLaw_y._c += coordL.physicsPoines.at(i).second*2;
        }
    
        //求导数  3元方程组系数
        _differentialCoefficient diff_x;
        _differentialCoefficient diff_y;
        diff_x.diff_a.append(squareLaw_x.aa);
        diff_x.diff_a.append(squareLaw_x.ab);
        diff_x.diff_a.append(squareLaw_x.ac);
        diff_x.diff_a.append(squareLaw_x._a);
        diff_x.diff_b.append(squareLaw_x.ab);
        diff_x.diff_b.append(squareLaw_x.bb);
        diff_x.diff_b.append(squareLaw_x.bc);
        diff_x.diff_b.append(squareLaw_x._b);
        diff_x.diff_c.append(squareLaw_x.ac);
        diff_x.diff_c.append(squareLaw_x.bc);
        diff_x.diff_c.append(squareLaw_x.cc);
        diff_x.diff_c.append(squareLaw_x._c);
    
        diff_y.diff_a.append(squareLaw_y.aa);
        diff_y.diff_a.append(squareLaw_y.ab);
        diff_y.diff_a.append(squareLaw_y.ac);
        diff_y.diff_a.append(squareLaw_y._a);
        diff_y.diff_b.append(squareLaw_y.ab);
        diff_y.diff_b.append(squareLaw_y.bb);
        diff_y.diff_b.append(squareLaw_y.bc);
        diff_y.diff_b.append(squareLaw_y._b);
        diff_y.diff_c.append(squareLaw_y.ac);
        diff_y.diff_c.append(squareLaw_y.bc);
        diff_y.diff_c.append(squareLaw_y.cc);
        diff_y.diff_c.append(squareLaw_y._c);
    
        //解方程 使用克莱默法则解方程
        //a11​a22​a33​+a12​a23​a31​+a13​a21​a32​ −a13​a22​a31​−a11​a23​a32​−a12​a21​a33​
    
        double D_x,Da,Db,Dc, D_y,Dd,De,Df;
        D_x = diff_x.diff_a.at(0)*diff_x.diff_b.at(1)*diff_x.diff_c.at(2) + diff_x.diff_a.at(1)*diff_x.diff_b.at(2)*diff_x.diff_c.at(0) +diff_x.diff_a.at(2)*diff_x.diff_b.at(0)*diff_x.diff_c.at(1)
                -diff_x.diff_a.at(2)*diff_x.diff_b.at(1)*diff_x.diff_c.at(0) - diff_x.diff_a.at(0)*diff_x.diff_b.at(2)*diff_x.diff_c.at(1) -diff_x.diff_a.at(1)*diff_x.diff_b.at(0)*diff_x.diff_c.at(2);
        Da = diff_x.diff_a.at(3)*diff_x.diff_b.at(1)*diff_x.diff_c.at(2) + diff_x.diff_a.at(1)*diff_x.diff_b.at(2)*diff_x.diff_c.at(3) +diff_x.diff_a.at(2)*diff_x.diff_b.at(3)*diff_x.diff_c.at(1)
                -diff_x.diff_a.at(2)*diff_x.diff_b.at(1)*diff_x.diff_c.at(3) - diff_x.diff_a.at(3)*diff_x.diff_b.at(2)*diff_x.diff_c.at(1) -diff_x.diff_a.at(1)*diff_x.diff_b.at(3)*diff_x.diff_c.at(2);
        Db = diff_x.diff_a.at(0)*diff_x.diff_b.at(3)*diff_x.diff_c.at(2) + diff_x.diff_a.at(3)*diff_x.diff_b.at(2)*diff_x.diff_c.at(0) +diff_x.diff_a.at(2)*diff_x.diff_b.at(0)*diff_x.diff_c.at(3)
                -diff_x.diff_a.at(2)*diff_x.diff_b.at(3)*diff_x.diff_c.at(0) - diff_x.diff_a.at(0)*diff_x.diff_b.at(2)*diff_x.diff_c.at(3) -diff_x.diff_a.at(3)*diff_x.diff_b.at(0)*diff_x.diff_c.at(2);
        Dc = diff_x.diff_a.at(0)*diff_x.diff_b.at(1)*diff_x.diff_c.at(3) + diff_x.diff_a.at(1)*diff_x.diff_b.at(3)*diff_x.diff_c.at(0) +diff_x.diff_a.at(3)*diff_x.diff_b.at(0)*diff_x.diff_c.at(1)
                -diff_x.diff_a.at(3)*diff_x.diff_b.at(1)*diff_x.diff_c.at(0) - diff_x.diff_a.at(0)*diff_x.diff_b.at(3)*diff_x.diff_c.at(1) -diff_x.diff_a.at(1)*diff_x.diff_b.at(0)*diff_x.diff_c.at(3);
        D_y = diff_y.diff_a.at(0)*diff_y.diff_b.at(1)*diff_y.diff_c.at(2) + diff_y.diff_a.at(1)*diff_y.diff_b.at(2)*diff_y.diff_c.at(0) +diff_y.diff_a.at(2)*diff_y.diff_b.at(0)*diff_y.diff_c.at(1)
                -diff_y.diff_a.at(2)*diff_y.diff_b.at(1)*diff_y.diff_c.at(0) - diff_y.diff_a.at(0)*diff_y.diff_b.at(2)*diff_y.diff_c.at(1) -diff_y.diff_a.at(1)*diff_y.diff_b.at(0)*diff_y.diff_c.at(2);
        Dd = diff_y.diff_a.at(3)*diff_y.diff_b.at(1)*diff_y.diff_c.at(2) + diff_y.diff_a.at(1)*diff_y.diff_b.at(2)*diff_y.diff_c.at(3) +diff_y.diff_a.at(2)*diff_y.diff_b.at(3)*diff_y.diff_c.at(1)
                -diff_y.diff_a.at(2)*diff_y.diff_b.at(1)*diff_y.diff_c.at(3) - diff_y.diff_a.at(3)*diff_y.diff_b.at(2)*diff_y.diff_c.at(1) -diff_y.diff_a.at(1)*diff_y.diff_b.at(3)*diff_y.diff_c.at(2);
        De = diff_y.diff_a.at(0)*diff_y.diff_b.at(3)*diff_y.diff_c.at(2) + diff_y.diff_a.at(3)*diff_y.diff_b.at(2)*diff_y.diff_c.at(0) +diff_y.diff_a.at(2)*diff_y.diff_b.at(0)*diff_y.diff_c.at(3)
                -diff_y.diff_a.at(2)*diff_y.diff_b.at(3)*diff_y.diff_c.at(0) - diff_y.diff_a.at(0)*diff_y.diff_b.at(2)*diff_y.diff_c.at(3) -diff_y.diff_a.at(3)*diff_y.diff_b.at(0)*diff_y.diff_c.at(2);
        Df = diff_y.diff_a.at(0)*diff_y.diff_b.at(1)*diff_y.diff_c.at(3) + diff_y.diff_a.at(1)*diff_y.diff_b.at(3)*diff_y.diff_c.at(0) +diff_y.diff_a.at(3)*diff_y.diff_b.at(0)*diff_y.diff_c.at(1)
                -diff_y.diff_a.at(3)*diff_y.diff_b.at(1)*diff_y.diff_c.at(0) - diff_y.diff_a.at(0)*diff_y.diff_b.at(3)*diff_y.diff_c.at(1) -diff_y.diff_a.at(1)*diff_y.diff_b.at(0)*diff_y.diff_c.at(3);
    
        _mat mat;
        mat.a = Da/D_x;
        mat.b = Db/D_x;
        mat.c = Dc/D_x;
        mat.d = Dd/D_y;
        mat.e = De/D_y;
        mat.f = Df/D_y;
        mat.g = 0;
        mat.h = 0;
        mat.i = 1;
        return mat;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130

    完整代码实现xxx.h

    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    
    #include 
    
    class QTableWidgetItem;
    QT_BEGIN_NAMESPACE
    namespace Ui { class MainWindow; }
    QT_END_NAMESPACE
    
    //保存从界面获取的坐标数据
    struct _coordList{
        QList<QPair<double,double>> pixPoines;//保存像素坐标
        QList<QPair<double,double>> physicsPoines;//保存物理坐标
    };
    
    //保存最小二乘法三个未知量(a,b,c)的结果
    struct _squareLaw{
        double aa=0;
        double bb=0;
        double cc=0;
        double ab=0;
        double ac=0;
        double bc=0;
        double _a=0;
        double _b=0;
        double _c=0;
    };
    //导数3x4
    struct _differentialCoefficient{
        QList<double> diff_a;
        QList<double> diff_b;
        QList<double> diff_c;
    };
    
    //矩阵3X3
    struct _mat{
        double a=0;
        double b=0;
        double c=0;
        double d=0;
        double e=0;
        double f=0;
        double g=0;
        double h=0;
        double i=0;
    };
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        MainWindow(QWidget *parent = nullptr);
        ~MainWindow();
    
        _mat calibration(_coordList);//标定
    
    private slots:
    
        void on_pushButton_clicked();
    
        void on_pushButton_2_clicked();
    
        void on_tableWidget_itemChanged(QTableWidgetItem *item);
    
        //void on_tableWidget_itemDoubleClicked(QTableWidgetItem *item);
    
        void on_pushButton_3_clicked();
    
    private:
        Ui::MainWindow *ui;
    
        QString old_text;
    
    };
    #endif // MAINWINDOW_H
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78

    xxx.cpp

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    
    #include 
    #include 
    #include 
    #include 
    #include 
    MainWindow::MainWindow(QWidget *parent)
        : QMainWindow(parent)
        , ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
    
        //设置列数
        ui->tableWidget->setColumnCount(4);
        //设置标题
        //表头标题用QStringList来表示
        QStringList headerText;
        headerText<<"像素X坐标"<<"像素Y坐标"<<"物理X坐标"<<"物理Y坐标";
        ui->tableWidget->setHorizontalHeaderLabels(headerText);
        old_text = "";
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    //设置n点标定
    void MainWindow::on_pushButton_clicked()
    {
        //获取标定的个数
        quint32 transitionCount = ui->spinBox->value();
    
        int oldRow = ui->tableWidget->rowCount();
        //设置行数
        ui->tableWidget->setRowCount(transitionCount);
    
        int newRow = ui->tableWidget->rowCount();
        //生成表格,默认值为0
        if(newRow>oldRow) {
            for(int i = oldRow;i<newRow;i++) {
                for (int j=0;j<4;j++) {
                    ui->tableWidget->setItem(i,j,new QTableWidgetItem("0"));
                }
            }
        }
    
    }
    //标定
    _mat MainWindow::calibration(_coordList coordL)
    {
        //保存未知量(a,b,c)的系数
        _squareLaw squareLaw_x;
        _squareLaw squareLaw_y;
        for(int i=0;i<coordL.pixPoines.count();i++) {
            squareLaw_x.aa += pow(coordL.pixPoines.at(i).first,2)*2;
            squareLaw_x.bb += pow(coordL.pixPoines.at(i).second,2)*2;
            squareLaw_x.cc += 1*2;
            squareLaw_x.ab += coordL.pixPoines.at(i).first*coordL.pixPoines.at(i).second*2;
            squareLaw_x.ac += coordL.pixPoines.at(i).first*2;
            squareLaw_x.bc += coordL.pixPoines.at(i).second*2;
            squareLaw_x._a += coordL.pixPoines.at(i).first*coordL.physicsPoines.at(i).first*2;
            squareLaw_x._b += coordL.pixPoines.at(i).second*coordL.physicsPoines.at(i).first*2;
            squareLaw_x._c += coordL.physicsPoines.at(i).first*2;
        }
    
        for(int i=0;i<coordL.pixPoines.count();i++) {
            squareLaw_y.aa += pow(coordL.pixPoines.at(i).first,2)*2;
            squareLaw_y.bb += pow(coordL.pixPoines.at(i).second,2)*2;
            squareLaw_y.cc += 1*2;
            squareLaw_y.ab += coordL.pixPoines.at(i).first*coordL.pixPoines.at(i).second*2;
            squareLaw_y.ac += coordL.pixPoines.at(i).first*2;
            squareLaw_y.bc += coordL.pixPoines.at(i).second*2;
            squareLaw_y._a += coordL.pixPoines.at(i).first*coordL.physicsPoines.at(i).second*2;
            squareLaw_y._b += coordL.pixPoines.at(i).second*coordL.physicsPoines.at(i).second*2;
            squareLaw_y._c += coordL.physicsPoines.at(i).second*2;
        }
    
        //求导数  3元方程组系数
        _differentialCoefficient diff_x;
        _differentialCoefficient diff_y;
        diff_x.diff_a.append(squareLaw_x.aa);
        diff_x.diff_a.append(squareLaw_x.ab);
        diff_x.diff_a.append(squareLaw_x.ac);
        diff_x.diff_a.append(squareLaw_x._a);
        diff_x.diff_b.append(squareLaw_x.ab);
        diff_x.diff_b.append(squareLaw_x.bb);
        diff_x.diff_b.append(squareLaw_x.bc);
        diff_x.diff_b.append(squareLaw_x._b);
        diff_x.diff_c.append(squareLaw_x.ac);
        diff_x.diff_c.append(squareLaw_x.bc);
        diff_x.diff_c.append(squareLaw_x.cc);
        diff_x.diff_c.append(squareLaw_x._c);
    
        diff_y.diff_a.append(squareLaw_y.aa);
        diff_y.diff_a.append(squareLaw_y.ab);
        diff_y.diff_a.append(squareLaw_y.ac);
        diff_y.diff_a.append(squareLaw_y._a);
        diff_y.diff_b.append(squareLaw_y.ab);
        diff_y.diff_b.append(squareLaw_y.bb);
        diff_y.diff_b.append(squareLaw_y.bc);
        diff_y.diff_b.append(squareLaw_y._b);
        diff_y.diff_c.append(squareLaw_y.ac);
        diff_y.diff_c.append(squareLaw_y.bc);
        diff_y.diff_c.append(squareLaw_y.cc);
        diff_y.diff_c.append(squareLaw_y._c);
    
        //解方程 使用克莱默法则解方程
        //a11​a22​a33​+a12​a23​a31​+a13​a21​a32​ −a13​a22​a31​−a11​a23​a32​−a12​a21​a33​
    
        double D_x,Da,Db,Dc, D_y,Dd,De,Df;
        D_x = diff_x.diff_a.at(0)*diff_x.diff_b.at(1)*diff_x.diff_c.at(2) + diff_x.diff_a.at(1)*diff_x.diff_b.at(2)*diff_x.diff_c.at(0) +diff_x.diff_a.at(2)*diff_x.diff_b.at(0)*diff_x.diff_c.at(1)
                -diff_x.diff_a.at(2)*diff_x.diff_b.at(1)*diff_x.diff_c.at(0) - diff_x.diff_a.at(0)*diff_x.diff_b.at(2)*diff_x.diff_c.at(1) -diff_x.diff_a.at(1)*diff_x.diff_b.at(0)*diff_x.diff_c.at(2);
        Da = diff_x.diff_a.at(3)*diff_x.diff_b.at(1)*diff_x.diff_c.at(2) + diff_x.diff_a.at(1)*diff_x.diff_b.at(2)*diff_x.diff_c.at(3) +diff_x.diff_a.at(2)*diff_x.diff_b.at(3)*diff_x.diff_c.at(1)
                -diff_x.diff_a.at(2)*diff_x.diff_b.at(1)*diff_x.diff_c.at(3) - diff_x.diff_a.at(3)*diff_x.diff_b.at(2)*diff_x.diff_c.at(1) -diff_x.diff_a.at(1)*diff_x.diff_b.at(3)*diff_x.diff_c.at(2);
        Db = diff_x.diff_a.at(0)*diff_x.diff_b.at(3)*diff_x.diff_c.at(2) + diff_x.diff_a.at(3)*diff_x.diff_b.at(2)*diff_x.diff_c.at(0) +diff_x.diff_a.at(2)*diff_x.diff_b.at(0)*diff_x.diff_c.at(3)
                -diff_x.diff_a.at(2)*diff_x.diff_b.at(3)*diff_x.diff_c.at(0) - diff_x.diff_a.at(0)*diff_x.diff_b.at(2)*diff_x.diff_c.at(3) -diff_x.diff_a.at(3)*diff_x.diff_b.at(0)*diff_x.diff_c.at(2);
        Dc = diff_x.diff_a.at(0)*diff_x.diff_b.at(1)*diff_x.diff_c.at(3) + diff_x.diff_a.at(1)*diff_x.diff_b.at(3)*diff_x.diff_c.at(0) +diff_x.diff_a.at(3)*diff_x.diff_b.at(0)*diff_x.diff_c.at(1)
                -diff_x.diff_a.at(3)*diff_x.diff_b.at(1)*diff_x.diff_c.at(0) - diff_x.diff_a.at(0)*diff_x.diff_b.at(3)*diff_x.diff_c.at(1) -diff_x.diff_a.at(1)*diff_x.diff_b.at(0)*diff_x.diff_c.at(3);
        D_y = diff_y.diff_a.at(0)*diff_y.diff_b.at(1)*diff_y.diff_c.at(2) + diff_y.diff_a.at(1)*diff_y.diff_b.at(2)*diff_y.diff_c.at(0) +diff_y.diff_a.at(2)*diff_y.diff_b.at(0)*diff_y.diff_c.at(1)
                -diff_y.diff_a.at(2)*diff_y.diff_b.at(1)*diff_y.diff_c.at(0) - diff_y.diff_a.at(0)*diff_y.diff_b.at(2)*diff_y.diff_c.at(1) -diff_y.diff_a.at(1)*diff_y.diff_b.at(0)*diff_y.diff_c.at(2);
        Dd = diff_y.diff_a.at(3)*diff_y.diff_b.at(1)*diff_y.diff_c.at(2) + diff_y.diff_a.at(1)*diff_y.diff_b.at(2)*diff_y.diff_c.at(3) +diff_y.diff_a.at(2)*diff_y.diff_b.at(3)*diff_y.diff_c.at(1)
                -diff_y.diff_a.at(2)*diff_y.diff_b.at(1)*diff_y.diff_c.at(3) - diff_y.diff_a.at(3)*diff_y.diff_b.at(2)*diff_y.diff_c.at(1) -diff_y.diff_a.at(1)*diff_y.diff_b.at(3)*diff_y.diff_c.at(2);
        De = diff_y.diff_a.at(0)*diff_y.diff_b.at(3)*diff_y.diff_c.at(2) + diff_y.diff_a.at(3)*diff_y.diff_b.at(2)*diff_y.diff_c.at(0) +diff_y.diff_a.at(2)*diff_y.diff_b.at(0)*diff_y.diff_c.at(3)
                -diff_y.diff_a.at(2)*diff_y.diff_b.at(3)*diff_y.diff_c.at(0) - diff_y.diff_a.at(0)*diff_y.diff_b.at(2)*diff_y.diff_c.at(3) -diff_y.diff_a.at(3)*diff_y.diff_b.at(0)*diff_y.diff_c.at(2);
        Df = diff_y.diff_a.at(0)*diff_y.diff_b.at(1)*diff_y.diff_c.at(3) + diff_y.diff_a.at(1)*diff_y.diff_b.at(3)*diff_y.diff_c.at(0) +diff_y.diff_a.at(3)*diff_y.diff_b.at(0)*diff_y.diff_c.at(1)
                -diff_y.diff_a.at(3)*diff_y.diff_b.at(1)*diff_y.diff_c.at(0) - diff_y.diff_a.at(0)*diff_y.diff_b.at(3)*diff_y.diff_c.at(1) -diff_y.diff_a.at(1)*diff_y.diff_b.at(0)*diff_y.diff_c.at(3);
    
        _mat mat;
        mat.a = Da/D_x;
        mat.b = Db/D_x;
        mat.c = Dc/D_x;
        mat.d = Dd/D_y;
        mat.e = De/D_y;
        mat.f = Df/D_y;
        mat.g = 0;
        mat.h = 0;
        mat.i = 1;
        return mat;
    }
    //执行标定
    void MainWindow::on_pushButton_2_clicked()
    {
        _coordList coordL;
        //获取界面坐标数据
        for(int i=0;i<ui->tableWidget->rowCount();i++) {
            QPair<double,double> pairPix;
            QPair<double,double> pairPhy;
    
            for(int j=0;j<4;j++) {
                switch (j) {
                case 0:
                    pairPix.first = ui->tableWidget->item(i,j)->text().toDouble();
                    break;
                case 1:
                    pairPix.second = ui->tableWidget->item(i,j)->text().toDouble();
                    break;
                case 2:
                    pairPhy.first = ui->tableWidget->item(i,j)->text().toDouble();
                    break;
                case 3:
                    pairPhy.second = ui->tableWidget->item(i,j)->text().toDouble();
                    break;
                default:
                    break;
    
                }
            }
            coordL.pixPoines.append(pairPix);
            coordL.physicsPoines.append(pairPhy);
        }
        //执行标定,获取结果
        _mat mat = calibration(coordL);
    
    
        //显示标定结果
        ui->textEdit->append(QString::number(mat.a,'e',15)+" , "+QString::number(mat.b,'e',15)+" , "+QString::number(mat.c,'e',15));
        ui->textEdit->append(QString::number(mat.d,'e',15)+" , "+QString::number(mat.e,'e',15)+" , "+QString::number(mat.f,'e',15));
        ui->textEdit->append(QString::number(mat.g)+" , "+QString::number(mat.h)+" , "+QString::number(mat.i));
        ui->textEdit->append("\r\n");
    
    }
    
    //item没有字符时,双击触发
    void MainWindow::on_tableWidget_itemChanged(QTableWidgetItem *item)
    {
    
        //2、匹配正负整数、正负浮点数
        QString Pattern("(-?[1-9][0-9]+)|(-?[0-9])|(-?[1-9]\\d+\\.\\d+)|(-?[0-9]\\.\\d+)");
        QRegExp  reg(Pattern);
    
        //3.获取修改的新的单元格内容
        QString str=item->text();
    
        if(str.isEmpty()) {
            return;
        }
        //匹配失败,返回原来的字符
        if(!reg.exactMatch(str)){
            QMessageBox::information(this,"匹配失败","请输入小数和整数!");
            item->setText("0");  //更换之前的内容
        }
        //1、记录旧的单元格内容
        old_text = item->text();
    
    }
    
    
    
    //打开文件-》从文件读取坐标
    void MainWindow::on_pushButton_3_clicked()
    {
        QString fileName = QFileDialog::getOpenFileName(this,tr("文件对话框!"), "",tr("文件(*.csv *.txt)"));
        if(!fileName.isEmpty()) {
            QFile file(fileName);
            quint32 line=0;
            if(file.open(QIODevice::ReadOnly|QIODevice::Text)) {
                for (;;) {
                    QString data = file.readLine();
                    if(data.isEmpty()) {
                        QMessageBox::information(this,"完成","数据读取完成!");
                        return;
                    }
                    QStringList sL = data.split(",");
                    if(sL.count()!=4) {
                        QMessageBox::information(this,"错误","请确定每行数据为4个并且以,分割!");
                        return;
                    }
                    for(int i=0;i<sL.count();i++) {
                        bool isOk;
                        sL.at(i).toDouble(&isOk);
                        sL.at(i).toULongLong(&isOk);
                        if(isOk) {
                            //设置行数
                            ui->tableWidget->setRowCount(line+1);
                            ui->tableWidget->setItem(line,i,new QTableWidgetItem(sL.at(i)));
                        }else {
                            QMessageBox::information(this,"错误","数据转换double失败!");
                        }
                    }
    
                    line++;
                }
    
    
            }
    
        }
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252

    在这里插入图片描述

    2:外部链接

    最小二乘法
    仿射变换
    克拉默法则
    行列式计算方法
    2D坐标系下的点的转换矩阵

    在这里插入图片描述

  • 相关阅读:
    机器人地面站-[QGroundControl源码解析]-[2]
    sql server导入表格出现错误
    【方向盘】认为:开发者已无理由再用Java EE
    ISP pipeline的锐化
    【Mac使用技巧】Mac和iPhone间接力功能失效解决总结
    Flask 学习-13.Flask-SQLAlchemy 新建模型和字段
    SpringMVC的方法形参注解(Restful风格)
    Cannot find a valid baseurl for repo: HDP-3.1-repo-1
    windows server 2012 R2的C盘空间满了,但是找不到大文件的两种原因
    推荐系统-召回-概述(五):一切为了业务
  • 原文地址:https://blog.csdn.net/weixin_43763292/article/details/126881396