N点校正 - 座標系変換



1: キャリブレーションアルゴリズム

ここでのVector_to_hom_mat2d(Px, Py, Qx, Qy, HomMat2D)
ここに画像の説明を挿入
は、最小二乗法を使用して HomMat2D 行列を見つける halcon 演算子ブロックの公式ドキュメントを参照しています。-9 点キャリブレーションは、2 つの座標系の座標変換を見つけるために一般的に使用されます。
以下の個人的な実装原則、結果は上記のオペレーターによって計算された結果と一致しており、知識は限られており、学習とコミュニケーションのみを目的としています。
1: まず図を見てみましょう。図の行列は 2 行 3 列で、最後の列は 0, 0, 1 です。同次行列を使用しているため、展開は省略されています。このような行列形式になっている具体的な理由は、実際には一連の変換、つまり平面の 2 次元アフィン変換です。

ここに画像の説明を挿入

2: 次に、最小二乗法を使用して項目をリストし(最小二乗法)、ここに画像の説明を挿入各未知量の偏導関数を計算します。図には未知量が 2 つあります。つまり、方程式が 2 つリストされています。未知数が 3 つの場合は、未知数が 3 つあります。つまり、3 つの方程式と
ここに画像の説明を挿入
3 つの未知の量が導出され、その結果が対応する行列の未知の量になります。

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;
}

完全なコードは xxx.h を実装します。

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

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

xxx.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QTableWidgetItem>
#include <QMessageBox>
#include <QTableWidgetItem>
#include <QFileDialog>
#include <QDebug>
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++;
            }


        }

    }

}

ここに画像の説明を挿入

2: 外部リンク

最小二乗法
アフィン変換
クラマー則
行列式計算法
2次元座標系の点の変換行列

おすすめ

転載: blog.csdn.net/weixin_43763292/article/details/126881396