N点标定-坐标系变换

这篇具有很好参考价值的文章主要介绍了N点标定-坐标系变换。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。



1:标定算法

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

n点标定,视觉,算法,矩阵

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

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

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

n点标定,视觉,算法,矩阵
n点标定,视觉,算法,矩阵
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++;
            }


        }

    }

}

n点标定,视觉,算法,矩阵

2:外部链接

最小二乘法
仿射变换
克拉默法则
行列式计算方法
2D坐标系下的点的转换矩阵文章来源地址https://www.toymoban.com/news/detail-586905.html

到了这里,关于N点标定-坐标系变换的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • MATLAB 相机标定中标定板角点像素坐标系到世界坐标系的转换

    matlab 做相机标定后,想将第一张(任意一张都行)标定板角点所对应的像素坐标转换到世界坐标系下,标定板角点的像素坐标真值与世界坐标真值都非常容易获得,但是我通过内外参矩阵将像素坐标转换到世界坐标有很大的误差,如下 像素坐标到世界坐标之间的转换可参考

    2024年02月10日
    浏览(36)
  • 双相机坐标系标定

    在工业应用中,常常会遇到双相机定位的项目,下面就介绍双相机如何标定才能做到精准定位。 1,产品  如上图所示,玻璃上对角有两个mark点,由于mark点的间距太远只能用两个相机去拍。 2,相机布局  两个相机分别拍产品的对角。 3,标定流程   1,根据n点标的规则获取

    2024年02月12日
    浏览(36)
  • 激光雷达标定(坐标系转换)

    由于激光雷达获取的点云数据的坐标是相对于激光雷达坐标系的,为了使车最终得到的点云数据坐标是在车坐标系下的,我们需要对点云中每一个点的坐标进行坐标转换。 首先是需要对坐标系进行旋转变换,先以二维平面的单位向量坐标转换为例,假设两坐标系中的旋转矩阵

    2023年04月16日
    浏览(30)
  • 相机标定 >> 坐标系转换@内参、外参

    为了更好的理解标定,首先应熟悉各个坐标系。(坐标系图均取自百度百科) 该坐标系是以图像左上角为原点建立以像素为单位的二维坐标系u-v。(相对坐标系) 图像坐标系是以 O1 (是图像的主点,也即光轴与像平面的交点,一般就是像素坐标系的中点)为原点的二维坐标

    2024年02月12日
    浏览(37)
  • 【导弹四种坐标系及坐标系之间的变换】

    本文参考钱杏芳等编著的《导弹飞行力学》 坐标系是为描述导弹位置和运动规律而选取的参考基准。为了准确,简洁和清晰的描述导弹的运动方程,我们需要选取合适的坐标系并熟练掌握坐标系之间的转换。本文介绍了地面坐标系、弹体坐标系、弹道坐标系和速度坐标系四种

    2023年04月09日
    浏览(42)
  • 激光雷达坐标系和相机坐标系相互变换(易懂不详细)

    码字不易,路过的朋友动动小手点点赞吧 传感器融合少不了的就是联合标定,最近大火的激光雷达和相机传感器融合算法,让很多工程师学者投入精力学习,本文简单介绍一下激光雷达和相机传感器坐标系转换的原理。         传感器安装位置不同,而且每个传感器都有

    2024年02月11日
    浏览(33)
  • 坐标系之间的变换

    本文来自 《Fundamentals of Computer Graphic》 7.5 Coordinate Transform 在图 7.19 中,右上图是保持坐标系不变,移动点的位置;右下图是保持点的位置不变,移动坐标系。在这两种移动方法之后,点在坐标系上的坐标都是 ( 1 , 1 ) (1,1) ( 1 , 1 ) 。 改变坐标系的想法与编程中的类型转换类似

    2024年02月08日
    浏览(45)
  • 怎样通过Python和齐次坐标变换方法实现坐标系之间的转换?

    齐次坐标变换是一种用于实现坐标系之间变换的数学技术。它通常用于计算机图形学、计算机视觉和机器人技术。在齐次坐标系中,3D点/顶点由4D向量(x,y,z,w)表示,其中w是比例因子。齐次表示允许有效的矩阵运算并简化变换过程。坐标系之间的变换可以通过使用齐次变

    2024年02月05日
    浏览(37)
  • 齐次坐标变换的理解以及在无人机相机定位坐标系转换中的应用

    4*4矩阵的右边三个数表示平移,如果原来的向量u的w=0,那么就是u+(ai+bj+ck) 对应xyz三个轴的循环变换,注意负号的位置 用描述空间一点的变换方法来描述物体在空间的位置和方向。 先变换的矩阵乘在右边。 A p = B p + A p B o {}^{A}p={}^{B}p+{}^{A}p_{B_{o}} A p = B p + A p B o ​ ​ 从

    2024年04月15日
    浏览(48)
  • 机器人TF坐标系变换与一些可视化工具的应用

    TF坐标 在ROS中是一个非常重要的概念,因为机器人在做日常操作任务的时候,对于其所在 位置 和 朝向 是需要时刻知道的,而机器人是由很多 节点 组成的协同任务,对于每个部件,我们需要知道它的 位姿(位置和朝向) ,这使得坐标系就成为了一个很重要的问题。 TF的功能就

    2024年02月12日
    浏览(34)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包