添加4点标定页面,兼容2点标定
parent
6561a10e26
commit
4855167ea7
File diff suppressed because one or more lines are too long
Binary file not shown.
|
After Width: | Height: | Size: 1.6 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1020 B |
Binary file not shown.
|
After Width: | Height: | Size: 943 B |
@ -0,0 +1,49 @@
|
||||
#include "Algo.h"
|
||||
#include "QPolygon"
|
||||
#include <vector>
|
||||
|
||||
using namespace std;
|
||||
|
||||
Algo::Algo()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Algo::~Algo()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Algo::translate(QPolygonF srcPos,QPolygonF dstPos)
|
||||
{
|
||||
Point2f srcVec[4];
|
||||
Point2f dstTri[4];
|
||||
|
||||
srcVec[0].x = srcPos.at(0).x();
|
||||
srcVec[0].y = srcPos.at(0).y();
|
||||
|
||||
srcVec[1].x = srcPos.at(1).x();
|
||||
srcVec[1].y = srcPos.at(1).y();
|
||||
|
||||
srcVec[2].x = srcPos.at(2).x();
|
||||
srcVec[2].y = srcPos.at(2).y();
|
||||
|
||||
srcVec[3].x = srcPos.at(3).x();
|
||||
srcVec[3].y = srcPos.at(3).y();
|
||||
|
||||
dstTri[0].x = dstPos.at(0).x();
|
||||
dstTri[0].y = dstPos.at(0).y();
|
||||
|
||||
dstTri[1].x = dstPos.at(1).x();
|
||||
dstTri[1].y = dstPos.at(1).y();
|
||||
|
||||
dstTri[2].x = dstPos.at(2).x();
|
||||
dstTri[2].y = dstPos.at(2).y();
|
||||
|
||||
dstTri[3].x = dstPos.at(3).x();
|
||||
dstTri[3].y = dstPos.at(3).y();
|
||||
|
||||
/// ÇóµÃ·ÂÉä±ä»»
|
||||
Mat warp_mat = getAffineTransform(srcVec, dstTri);
|
||||
int a = 0;
|
||||
}
|
||||
@ -0,0 +1,17 @@
|
||||
#ifndef _ALGO_H_
|
||||
#define _ALGO_H_
|
||||
#include <opencv.hpp>
|
||||
#include "QPolygon"
|
||||
using namespace cv;
|
||||
class Algo
|
||||
{
|
||||
public:
|
||||
Algo();
|
||||
~Algo();
|
||||
|
||||
void translate(QPolygonF srcPos, QPolygonF dstPos);
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,446 @@
|
||||
#include "TestTransform.h"
|
||||
#include <QTransform>
|
||||
#include <QPainter>
|
||||
#include <opencv.hpp>
|
||||
#include <vector>
|
||||
|
||||
using namespace cv;
|
||||
using namespace std;
|
||||
|
||||
|
||||
#define M_LOW_TOLERANCE 0.000001
|
||||
void transPoints(vector<Point2d>& vec, const Matx33d& mat)
|
||||
{
|
||||
for (size_t i = 0; i < vec.size(); ++i)
|
||||
{
|
||||
Point2d p = vec[i];
|
||||
Point3d tp = mat * p;
|
||||
vec[i] = Point2d(tp.x / tp.z, tp.y / tp.z);
|
||||
}
|
||||
}
|
||||
|
||||
void transPoints(vector<Point2d>& vec, const Mat& mat)
|
||||
{
|
||||
Matx33d matx = Matx33d::eye();
|
||||
Mat matx_(3, 3, CV_64FC1, matx.val);
|
||||
|
||||
if (mat.rows == 2 && mat.cols == 3)
|
||||
{
|
||||
mat.copyTo(matx_.rowRange(0, 2));
|
||||
}
|
||||
else if (mat.rows == 3 && mat.cols == 3)
|
||||
{
|
||||
mat.copyTo(matx_);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "not supported transformation mat with its size as " \
|
||||
<< mat.rows << "x" << mat.cols << std::endl;
|
||||
return;
|
||||
}
|
||||
transPoints(vec, matx);
|
||||
}
|
||||
|
||||
Matx33d affineTrans(const vector<Point2d>& src, const vector<Point2d>& dst)
|
||||
{
|
||||
if (dst.empty() || src.empty()) {
|
||||
return Mat();
|
||||
}
|
||||
|
||||
Point2d pc, qc;
|
||||
int smallerSize = src.size() < dst.size() ? src.size() : dst.size();
|
||||
|
||||
for (int i = 0; i < smallerSize; i++) {
|
||||
pc += src[i];
|
||||
qc += dst[i];
|
||||
}
|
||||
pc.x /= smallerSize;
|
||||
pc.y /= smallerSize;
|
||||
qc.x /= smallerSize;
|
||||
qc.y /= smallerSize;
|
||||
|
||||
Matx21d pit;
|
||||
Matx12d pi;
|
||||
Matx12d qi;
|
||||
Matx22d spitpi = Matx22d::zeros();
|
||||
Matx22d pitpi;
|
||||
Matx22d pitqi;
|
||||
Matx22d spitqi = Matx22d::zeros();
|
||||
|
||||
for (int i = 0; i < src.size() && i < dst.size(); i++) {
|
||||
Point2d qpi = src[i] - pc;
|
||||
Point2d qqi = dst[i] - qc;
|
||||
|
||||
pit(0) = qpi.x;
|
||||
pit(1) = qpi.y;
|
||||
pi(0) = qpi.x;
|
||||
pi(1) = qpi.y;
|
||||
qi(0) = qqi.x;
|
||||
qi(1) = qqi.y;
|
||||
pitpi = pit * pi;
|
||||
spitpi = pitpi + spitpi;
|
||||
pitqi = pit * qi;
|
||||
spitqi = pitqi + spitqi;
|
||||
}
|
||||
Matx22d ispitpi;
|
||||
ispitpi = spitpi.inv();
|
||||
|
||||
Matx22d M = ispitpi * spitqi;
|
||||
|
||||
double m11 = M(0, 0);
|
||||
double m21 = M(0, 1);
|
||||
double m12 = M(1, 0);
|
||||
double m22 = M(1, 1);
|
||||
|
||||
Matx33d qm(m11, m12, 0, m21, m22, 0, 0, 0, 1);
|
||||
Matx33d pcm(1.0, 0, -pc.x, 0, 1.0, -pc.y, 0, 0, 1);
|
||||
Matx33d qcm(1.0, 0, qc.x, 0, 1.0, qc.y, 0, 0, 1);
|
||||
|
||||
Matx33d ret = qcm * qm*pcm;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
cv::Matx33d rigidTrans(const vector<Point2d>& src, const vector<Point2d>& dst,
|
||||
Mat* pCenRotScaleMat = NULL)
|
||||
{
|
||||
if (dst.empty() || src.empty()) {
|
||||
return Mat();
|
||||
}
|
||||
|
||||
vector<double> weights(src.size(), 1.0 / src.size());
|
||||
Point2d pc, qc;
|
||||
double wsum = 0;
|
||||
|
||||
for (int i = 0; i < src.size(); i++) {
|
||||
double w = 1.0 / src.size();
|
||||
weights[i] = w;
|
||||
pc += src[i] * w;
|
||||
qc += dst[i] * w;
|
||||
wsum += w;
|
||||
}
|
||||
pc.x /= wsum;
|
||||
pc.y /= wsum;
|
||||
qc.x /= wsum;
|
||||
qc.y /= wsum;
|
||||
|
||||
double u = 0;
|
||||
double u1, u2;
|
||||
u1 = 0;
|
||||
u2 = 0;
|
||||
for (int i = 0; i < src.size() && i < dst.size(); i++) {
|
||||
Point2d qpi = src[i] - pc;
|
||||
Point2d qqi = dst[i] - qc;
|
||||
Point2d pi(qpi.x, qpi.y);
|
||||
Point2d qi(qqi.x, qqi.y);
|
||||
u1 += pi.dot(qi)*weights[i];
|
||||
Point2d pi_(pi.y, -pi.x);
|
||||
u2 += qi.dot(pi_)*weights[i];
|
||||
}
|
||||
u = sqrt(u1*u1 + u2 * u2);
|
||||
if (u < M_LOW_TOLERANCE) {
|
||||
u = M_LOW_TOLERANCE;
|
||||
}
|
||||
|
||||
Matx22d R = Matx22d::zeros();
|
||||
Matx22d r = Matx22d::zeros();
|
||||
|
||||
for (int i = 0; i < src.size() && i < dst.size(); i++) {
|
||||
Point2d qpi = src[i] - pc;
|
||||
Point2d qqi = dst[i] - qc;
|
||||
Point2d pi(qpi.x, qpi.y);
|
||||
Point2d qi(qqi.x, qqi.y);
|
||||
Point2d pi_(pi.y, -pi.x);
|
||||
Point2d qi_(qi.y, -qi.x);
|
||||
|
||||
r(0, 0) = pi.dot(qi);
|
||||
r(0, 1) = pi.dot(qi_);
|
||||
r(1, 0) = pi_.dot(qi);
|
||||
r(1, 1) = pi_.dot(qi_);
|
||||
|
||||
R = R + r * (weights[i] / u);
|
||||
}
|
||||
|
||||
double m11 = R(0, 0);
|
||||
double m21 = R(0, 1);
|
||||
double m12 = R(1, 0);
|
||||
double m22 = R(1, 1);
|
||||
Matx33d qm(m11, m12, 0, m21, m22, 0, 0, 0, 1);
|
||||
Matx33d pcm(1.0, 0, -pc.x, 0, 1.0, -pc.y, 0, 0, 1);
|
||||
Matx33d qcm(1.0, 0, qc.x, 0, 1.0, qc.y, 0, 0, 1);
|
||||
Matx33d ret = qcm * qm*pcm;
|
||||
|
||||
if (pCenRotScaleMat)
|
||||
{
|
||||
*pCenRotScaleMat = Mat(qm);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool cmpPointVec(const vector<Point2d>& vec0, const vector<Point2d>& vec1, const Matx33d& mat, double tor)
|
||||
{
|
||||
int smallerSize = vec0.size() < vec1.size() ? vec0.size() : vec1.size();
|
||||
for (int i = 0; i < smallerSize; ++i)
|
||||
{
|
||||
Point2d p0, p1;
|
||||
p0 = vec0[i];
|
||||
p1 = vec1[i];
|
||||
Point3d tp0 = mat * p0;
|
||||
tp0.x /= tp0.z;
|
||||
tp0.y /= tp0.z;
|
||||
if (abs(p1.x - tp0.x) > tor || abs(p1.y - tp0.y) > tor)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void testTransSolver()
|
||||
{
|
||||
{
|
||||
//rotation only
|
||||
|
||||
vector<Point2d> vec0, vec1;
|
||||
vec0.push_back(Point2d());
|
||||
vec0.push_back(Point2d(1, 0));
|
||||
vec0.push_back(Point2d(1, 1));
|
||||
vec0.push_back(Point2d(0, 1));
|
||||
|
||||
vec1.push_back(Point2d());
|
||||
vec1.push_back(Point2d(0, 1));
|
||||
vec1.push_back(Point2d(-1, 1));
|
||||
vec1.push_back(Point2d(-1, 0));
|
||||
|
||||
Matx33d ret = affineTrans(vec0, vec1);
|
||||
_ASSERTE(cmpPointVec(vec0, vec1, ret, M_LOW_TOLERANCE));
|
||||
|
||||
ret = rigidTrans(vec0, vec1);
|
||||
_ASSERTE(cmpPointVec(vec0, vec1, ret, M_LOW_TOLERANCE));
|
||||
}
|
||||
{
|
||||
// rotation and scale
|
||||
|
||||
vector<Point2d> vec0, vec1;
|
||||
vec0.push_back(Point2d());
|
||||
vec0.push_back(Point2d(1, 0));
|
||||
vec0.push_back(Point2d(1, 1));
|
||||
vec0.push_back(Point2d(0, 1));
|
||||
|
||||
vec1.push_back(Point2d());
|
||||
vec1.push_back(Point2d(1, 1));
|
||||
vec1.push_back(Point2d(0, 2));
|
||||
vec1.push_back(Point2d(-1, 1));
|
||||
|
||||
Matx33d ret = affineTrans(vec0, vec1);
|
||||
_ASSERTE(cmpPointVec(vec0, vec1, ret, M_LOW_TOLERANCE));
|
||||
}
|
||||
{
|
||||
// scale only
|
||||
|
||||
vector<Point2d> vec0, vec1;
|
||||
vec0.push_back(Point2d());
|
||||
vec0.push_back(Point2d(1, 0));
|
||||
vec0.push_back(Point2d(1, 1));
|
||||
vec0.push_back(Point2d(0, 1));
|
||||
|
||||
vec1.push_back(Point2d());
|
||||
vec1.push_back(Point2d(2, 0));
|
||||
vec1.push_back(Point2d(2, 2));
|
||||
vec1.push_back(Point2d(0, 2));
|
||||
|
||||
Matx33d ret = affineTrans(vec0, vec1);
|
||||
_ASSERTE(cmpPointVec(vec0, vec1, ret, M_LOW_TOLERANCE));
|
||||
}
|
||||
{
|
||||
// translation only
|
||||
|
||||
vector<Point2d> vec0, vec1;
|
||||
vec0.push_back(Point2d());
|
||||
vec0.push_back(Point2d(1, 0));
|
||||
vec0.push_back(Point2d(1, 1));
|
||||
vec0.push_back(Point2d(0, 1));
|
||||
|
||||
vec1.push_back(Point2d(1, 1));
|
||||
vec1.push_back(Point2d(2, 1));
|
||||
vec1.push_back(Point2d(2, 2));
|
||||
vec1.push_back(Point2d(1, 2));
|
||||
|
||||
Matx33d ret = affineTrans(vec0, vec1);
|
||||
_ASSERTE(cmpPointVec(vec0, vec1, ret, M_LOW_TOLERANCE));
|
||||
|
||||
ret = rigidTrans(vec0, vec1);
|
||||
_ASSERTE(cmpPointVec(vec0, vec1, ret, M_LOW_TOLERANCE));
|
||||
}
|
||||
{
|
||||
for (int i = 0; i < 10000; ++i)
|
||||
{
|
||||
// random rotation and translation
|
||||
Mat mat23 = getRotationMatrix2D(Point2f(), rand() % 360, 1.0);
|
||||
mat23.at<double>(0, 2) = (rand() % 1000) / 1000.0;
|
||||
mat23.at<double>(1, 2) = (rand() % 1000) / 1000.0;
|
||||
Matx33d matx = Matx33d::eye();
|
||||
Mat mat(3, 3, CV_64FC1, matx.val);
|
||||
mat23.copyTo(mat.rowRange(0, 2));
|
||||
|
||||
vector<Point2d> vec0, vec1;
|
||||
vec0.push_back(Point2d());
|
||||
vec0.push_back(Point2d(1, 0));
|
||||
vec0.push_back(Point2d(1, 1));
|
||||
vec0.push_back(Point2d(0, 1));
|
||||
|
||||
vec1 = vec0;
|
||||
transPoints(vec1, matx);
|
||||
|
||||
Matx33d ret = affineTrans(vec0, vec1);
|
||||
_ASSERTE(cmpPointVec(vec0, vec1, ret, M_LOW_TOLERANCE));
|
||||
ret = rigidTrans(vec0, vec1);
|
||||
_ASSERTE(cmpPointVec(vec0, vec1, ret, M_LOW_TOLERANCE));
|
||||
}
|
||||
}
|
||||
{
|
||||
// skew only
|
||||
|
||||
vector<Point2d> vec0, vec1;
|
||||
vec0.push_back(Point2d());
|
||||
vec0.push_back(Point2d(1, 0));
|
||||
vec0.push_back(Point2d(1, 1));
|
||||
vec0.push_back(Point2d(0, 1));
|
||||
|
||||
vec1.push_back(Point2d());
|
||||
vec1.push_back(Point2d(1, 0));
|
||||
vec1.push_back(Point2d(2, 1));
|
||||
vec1.push_back(Point2d(1, 1));
|
||||
|
||||
Matx33d ret = affineTrans(vec0, vec1);
|
||||
_ASSERTE(cmpPointVec(vec0, vec1, ret, M_LOW_TOLERANCE));
|
||||
}
|
||||
{
|
||||
// random affine
|
||||
|
||||
for (int i = 0; i < 10000; ++i)
|
||||
{
|
||||
vector<Point2d> vec0, vec1;
|
||||
vec0.push_back(Point2d());
|
||||
vec0.push_back(Point2d(1, 0));
|
||||
vec0.push_back(Point2d(1, 1));
|
||||
vec0.push_back(Point2d(0, 1));
|
||||
|
||||
Matx33d trans = Matx33d::eye();
|
||||
Mat mat(3, 3, CV_64FC1, trans.val);
|
||||
randu(mat.rowRange(0, 2), 0, 1.0);
|
||||
|
||||
vec1 = vec0;
|
||||
transPoints(vec1, trans);
|
||||
|
||||
Matx33d ret = affineTrans(vec0, vec1);
|
||||
_ASSERTE(cmpPointVec(vec0, vec1, ret, M_LOW_TOLERANCE));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void translate(QPolygonF srcPos, QPolygonF dstPos)
|
||||
{
|
||||
|
||||
vector<Point2d> vec0, vec1;
|
||||
vec0.push_back(Point2d(srcPos.at(0).x(), srcPos.at(0).y()));
|
||||
vec0.push_back(Point2d(srcPos.at(1).x(), srcPos.at(1).y()));
|
||||
vec0.push_back(Point2d(srcPos.at(2).x(), srcPos.at(2).y()));
|
||||
vec0.push_back(Point2d(srcPos.at(3).x(), srcPos.at(3).y()));
|
||||
|
||||
vec1.push_back(Point2d(dstPos.at(0).x(), dstPos.at(0).y()));
|
||||
vec1.push_back(Point2d(dstPos.at(1).x(), dstPos.at(1).y()));
|
||||
vec1.push_back(Point2d(dstPos.at(2).x(), dstPos.at(2).y()));
|
||||
vec1.push_back(Point2d(dstPos.at(3).x(), dstPos.at(3).y()));
|
||||
Matx33d ret = affineTrans(vec0, vec1);
|
||||
Mat retMat = Mat(ret);
|
||||
|
||||
|
||||
|
||||
Point2f srcVec[4];
|
||||
Point2f dstTri[4];
|
||||
|
||||
srcVec[0].x = srcPos.at(0).x();
|
||||
srcVec[0].y = srcPos.at(0).y();
|
||||
|
||||
srcVec[1].x = srcPos.at(1).x();
|
||||
srcVec[1].y = srcPos.at(1).y();
|
||||
|
||||
srcVec[2].x = srcPos.at(2).x();
|
||||
srcVec[2].y = srcPos.at(2).y();
|
||||
|
||||
srcVec[3].x = srcPos.at(3).x();
|
||||
srcVec[3].y = srcPos.at(3).y();
|
||||
|
||||
dstTri[0].x = dstPos.at(0).x();
|
||||
dstTri[0].y = dstPos.at(0).y();
|
||||
|
||||
dstTri[1].x = dstPos.at(1).x();
|
||||
dstTri[1].y = dstPos.at(1).y();
|
||||
|
||||
dstTri[2].x = dstPos.at(2).x();
|
||||
dstTri[2].y = dstPos.at(2).y();
|
||||
|
||||
dstTri[3].x = dstPos.at(3).x();
|
||||
dstTri[3].y = dstPos.at(3).y();
|
||||
|
||||
|
||||
|
||||
|
||||
/// ÇóµÃ·ÂÉä±ä»»
|
||||
Mat warp_mat = getAffineTransform(srcVec, dstTri);
|
||||
double* pTransMat = (double*)(warp_mat.data);
|
||||
double m00=pTransMat[0];
|
||||
double m10=pTransMat[1];
|
||||
double m20=pTransMat[2];
|
||||
double m01=pTransMat[3];
|
||||
double m11=pTransMat[4];
|
||||
double m21=pTransMat[5];
|
||||
|
||||
int newX = 100;
|
||||
int newY = 100;
|
||||
|
||||
double temX = newX * m00 + newY * m10 + m20;
|
||||
double temY = newX * m01 + newY * m11 + m21;
|
||||
int a = 0;
|
||||
}
|
||||
|
||||
|
||||
TestTransform::TestTransform(QWidget *parent)
|
||||
: QMainWindow(parent)
|
||||
{
|
||||
ui.setupUi(this);
|
||||
connect(ui.pushButton, SIGNAL(clicked()), this, SLOT(onButtonClicked()));
|
||||
}
|
||||
|
||||
Q_SLOT void TestTransform::onButtonClicked()
|
||||
{
|
||||
//testTransSolver();
|
||||
QPolygonF srcP;
|
||||
srcP.append(QPointF(-105, -100));
|
||||
srcP.append(QPointF(-204, -100));
|
||||
srcP.append(QPointF(-300, -200));
|
||||
srcP.append(QPointF(-200, -200));
|
||||
|
||||
QPolygonF dstP;
|
||||
dstP.append(QPointF(-50, 50));
|
||||
dstP.append(QPointF(50, 50));
|
||||
dstP.append(QPointF(50, -50));
|
||||
dstP.append(QPointF(-50, -50));
|
||||
translate(srcP, dstP);
|
||||
|
||||
}
|
||||
|
||||
void TestTransform::paintEvent(QPaintEvent *event)
|
||||
{
|
||||
QPainter painter(this);
|
||||
QFont font("Courier", 24);
|
||||
painter.setFont(font);
|
||||
painter.drawText(100, 100, "Hello, world!");
|
||||
QTransform transform;
|
||||
transform.rotate(15.0);
|
||||
painter.setWorldTransform(transform);
|
||||
painter.drawText(100, 100, "Hello, world!");
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include <QtWidgets/QMainWindow>
|
||||
#include "ui_TestTransform.h"
|
||||
|
||||
class TestTransform : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
TestTransform(QWidget *parent = Q_NULLPTR);
|
||||
|
||||
Q_SLOT void onButtonClicked();
|
||||
protected:
|
||||
virtual void paintEvent(QPaintEvent *event);
|
||||
private:
|
||||
Ui::TestTransformClass ui;
|
||||
};
|
||||
@ -0,0 +1,4 @@
|
||||
<RCC>
|
||||
<qresource prefix="TestTransform">
|
||||
</qresource>
|
||||
</RCC>
|
||||
@ -0,0 +1,56 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>TestTransformClass</class>
|
||||
<widget class="QMainWindow" name="TestTransformClass">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>600</width>
|
||||
<height>400</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>TestTransform</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralWidget">
|
||||
<widget class="QPushButton" name="pushButton">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>360</x>
|
||||
<y>20</y>
|
||||
<width>75</width>
|
||||
<height>23</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<widget class="QMenuBar" name="menuBar">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>600</width>
|
||||
<height>23</height>
|
||||
</rect>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QToolBar" name="mainToolBar">
|
||||
<attribute name="toolBarArea">
|
||||
<enum>TopToolBarArea</enum>
|
||||
</attribute>
|
||||
<attribute name="toolBarBreak">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
</widget>
|
||||
<widget class="QStatusBar" name="statusBar"/>
|
||||
</widget>
|
||||
<layoutdefault spacing="6" margin="11"/>
|
||||
<resources>
|
||||
<include location="TestTransform.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
@ -0,0 +1,63 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{D9D6E242-F8AF-46E4-B9FD-80ECBC20BA3E}</UniqueIdentifier>
|
||||
<Extensions>qrc;*</Extensions>
|
||||
<ParseFiles>false</ParseFiles>
|
||||
</Filter>
|
||||
<Filter Include="Form Files">
|
||||
<UniqueIdentifier>{99349809-55BA-4b9d-BF79-8FDBB0286EB3}</UniqueIdentifier>
|
||||
<Extensions>ui</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{D9D6E242-F8AF-46E4-B9FD-80ECBC20BA3E}</UniqueIdentifier>
|
||||
<Extensions>qrc;*</Extensions>
|
||||
<ParseFiles>false</ParseFiles>
|
||||
</Filter>
|
||||
<Filter Include="Generated Files">
|
||||
<UniqueIdentifier>{71ED8ED8-ACB9-4CE9-BBE1-E00B30144E11}</UniqueIdentifier>
|
||||
<Extensions>moc;h;cpp</Extensions>
|
||||
<SourceControlFiles>False</SourceControlFiles>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="main.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="TestTransform.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Algo.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<QtMoc Include="TestTransform.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</QtMoc>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<QtUic Include="TestTransform.ui">
|
||||
<Filter>Form Files</Filter>
|
||||
</QtUic>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<QtRcc Include="TestTransform.qrc">
|
||||
<Filter>Resource Files</Filter>
|
||||
</QtRcc>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Algo.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@ -0,0 +1,10 @@
|
||||
#include "TestTransform.h"
|
||||
#include <QtWidgets/QApplication>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QApplication a(argc, argv);
|
||||
TestTransform w;
|
||||
w.show();
|
||||
return a.exec();
|
||||
}
|
||||
@ -0,0 +1,323 @@
|
||||
#include "lpImageCaliUI4P.h"
|
||||
#include <QFileDialog>
|
||||
#include "lpGlobalConfig.h"
|
||||
#include <QSettings>
|
||||
#include <QApplication>
|
||||
#pragma execution_character_set("utf-8")
|
||||
|
||||
lpImageCaliUI4P::lpImageCaliUI4P(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
ui.setupUi(this);
|
||||
m_srcImgView = replaceWidget<AwesomeImgViewer>(ui.widget);
|
||||
connect(m_srcImgView, SIGNAL(filterroiChanged(const AwesomeRoiInfo&, QString)), this, SLOT(onROIChange(const AwesomeRoiInfo&, QString)));
|
||||
connect(m_srcImgView, SIGNAL(pixelClicked(QPoint)), this, SLOT(onPixelClicked(QPoint)));
|
||||
connect(m_srcImgView, SIGNAL(roiLockIng(QString)), this, SLOT(onRoiLockIng(QString)));
|
||||
connect(m_srcImgView, SIGNAL(sgImageScale(qreal)), this, SLOT(onImageScale(qreal)));
|
||||
|
||||
connect(ui.m_pbLoadImg, SIGNAL(clicked()), this, SLOT(onButtonClicked()));
|
||||
connect(ui.m_pbApply, SIGNAL(clicked()), this, SLOT(onButtonClicked()));
|
||||
connect(ui.m_pbExit, SIGNAL(clicked()), this, SLOT(onButtonClicked()));
|
||||
connect(ui.m_pbLock, SIGNAL(clicked()), this, SLOT(onButtonClicked()));
|
||||
|
||||
QString strPath = QApplication::applicationDirPath() + "/showImg.ini";//图像展示比例的参数
|
||||
QSettings setting(strPath, QSettings::IniFormat);
|
||||
double nScale = setting.value("ShowImg/Scale_Standard", 0.53).toDouble();
|
||||
m_srcImgView->setInitScale(nScale);
|
||||
}
|
||||
|
||||
lpImageCaliUI4P::~lpImageCaliUI4P()
|
||||
{
|
||||
if (m_srcImgView) {
|
||||
delete m_srcImgView;
|
||||
m_srcImgView = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename _Widget>
|
||||
_Widget* lpImageCaliUI4P::replaceWidget(QWidget* pSrcWidget)
|
||||
{
|
||||
if (!pSrcWidget) {
|
||||
return nullptr;
|
||||
}
|
||||
QWidget* pParent = qobject_cast<QWidget*>(pSrcWidget->parent());
|
||||
if (!pParent) {
|
||||
return nullptr;
|
||||
}
|
||||
_Widget* pDstWidget = new _Widget;
|
||||
auto *pFrom = pParent->layout()->replaceWidget(pSrcWidget, pDstWidget);
|
||||
delete pFrom;
|
||||
delete pSrcWidget;
|
||||
return pDstWidget;
|
||||
}
|
||||
|
||||
void lpImageCaliUI4P::showEvent(QShowEvent *event)
|
||||
{
|
||||
ui.checkBox->setChecked(lpGlobalConfig::instance()->bTransPos_4P);
|
||||
ui.m_lineEdit_P1X->setText(QString("%1").arg(lpGlobalConfig::instance()->point1_4P.x()));
|
||||
ui.m_lineEdit_P1Y->setText(QString("%1").arg(lpGlobalConfig::instance()->point1_4P.y()));
|
||||
ui.m_lineEdit_P2X->setText(QString("%1").arg(lpGlobalConfig::instance()->point2_4P.x()));
|
||||
ui.m_lineEdit_P2Y->setText(QString("%1").arg(lpGlobalConfig::instance()->point2_4P.y()));
|
||||
ui.m_lineEdit_P3X->setText(QString("%1").arg(lpGlobalConfig::instance()->point3_4P.x()));
|
||||
ui.m_lineEdit_P3Y->setText(QString("%1").arg(lpGlobalConfig::instance()->point3_4P.y()));
|
||||
ui.m_lineEdit_P4X->setText(QString("%1").arg(lpGlobalConfig::instance()->point4_4P.x()));
|
||||
ui.m_lineEdit_P4Y->setText(QString("%1").arg(lpGlobalConfig::instance()->point4_4P.y()));
|
||||
|
||||
ui.m_lineEdit_P1X_P->setText(QString("%1").arg(lpGlobalConfig::instance()->real_point1_4P.x()));
|
||||
ui.m_lineEdit_P1Y_P->setText(QString("%1").arg(lpGlobalConfig::instance()->real_point1_4P.y()));
|
||||
ui.m_lineEdit_P2X_P->setText(QString("%1").arg(lpGlobalConfig::instance()->real_point2_4P.x()));
|
||||
ui.m_lineEdit_P2Y_P->setText(QString("%1").arg(lpGlobalConfig::instance()->real_point2_4P.y()));
|
||||
ui.m_lineEdit_P3X_P->setText(QString("%1").arg(lpGlobalConfig::instance()->real_point3_4P.x()));
|
||||
ui.m_lineEdit_P3Y_P->setText(QString("%1").arg(lpGlobalConfig::instance()->real_point3_4P.y()));
|
||||
ui.m_lineEdit_P4X_P->setText(QString("%1").arg(lpGlobalConfig::instance()->real_point4_4P.x()));
|
||||
ui.m_lineEdit_P4Y_P->setText(QString("%1").arg(lpGlobalConfig::instance()->real_point4_4P.y()));
|
||||
|
||||
ui.m_lineEdit_Xoffset->setText(QString("%1").arg(lpGlobalConfig::instance()->pointXOffset_4P));
|
||||
ui.m_lineEdit_Yoffset->setText(QString("%1").arg(lpGlobalConfig::instance()->pointYOffset_4P));
|
||||
|
||||
m_point1 = lpGlobalConfig::instance()->point1_4P;
|
||||
m_point2 = lpGlobalConfig::instance()->point2_4P;
|
||||
m_point3 = lpGlobalConfig::instance()->point3_4P;
|
||||
m_point4 = lpGlobalConfig::instance()->point4_4P;
|
||||
testPoint = lpGlobalConfig::instance()->testPoint;
|
||||
QPointF tmpTestPoint = transWorldPoint(testPoint,lpGlobalConfig::instance()->matxParam_4P);
|
||||
ui.label_testSrc->setText(QString("(%1,%2)").arg(testPoint.x()).arg(testPoint.y()));
|
||||
ui.label_testDst->setText(QString("(%1,%2)").arg(tmpTestPoint.x()).arg(tmpTestPoint.y()));
|
||||
if (m_srcImgView)
|
||||
{
|
||||
m_srcImgView->onClearAllROI();
|
||||
QString DstPath = QApplication::applicationDirPath() + "\\user\\StandImage.png";
|
||||
QImage img;
|
||||
img.load(DstPath);
|
||||
|
||||
m_imageH = img.height();
|
||||
m_imageW = img.width();
|
||||
m_srcImgView->setImg(img);
|
||||
|
||||
AddPoint(m_point1, "P1");
|
||||
AddPoint(m_point2, "P2");
|
||||
AddPoint(m_point3, "P3");
|
||||
AddPoint(m_point4, "P4");
|
||||
AddPoint(testPoint, "TEST",QColor(255,170,0));
|
||||
m_srcImgView->setLabelVisible(true);
|
||||
m_srcImgView->setLockAll(true);
|
||||
|
||||
}
|
||||
ui.m_pbLock->setText(tr("解锁"));
|
||||
}
|
||||
|
||||
void lpImageCaliUI4P::changeEvent(QEvent *event)
|
||||
{
|
||||
if (event->type() == QEvent::LanguageChange)
|
||||
{
|
||||
ui.retranslateUi(this);
|
||||
}
|
||||
}
|
||||
|
||||
Q_SLOT void lpImageCaliUI4P::onButtonClicked()
|
||||
{
|
||||
QString strObj = sender()->objectName();
|
||||
if (strObj == "m_pbLoadImg")
|
||||
{
|
||||
QString fileName = QFileDialog::getOpenFileName(this, tr("选择标定图"), "/home/jana", tr("Image Files (*.png *.jpg *.bmp)"));
|
||||
if (!fileName.isEmpty())
|
||||
{
|
||||
QString DstPath = QApplication::applicationDirPath() + "\\user\\StandImage.png";
|
||||
QString sourcePath = fileName;
|
||||
DstPath.replace("\\", "/");
|
||||
if (sourcePath == DstPath) {
|
||||
}
|
||||
if (!QFile::exists(sourcePath)) {
|
||||
}
|
||||
QDir *createfile = new QDir;
|
||||
bool exist = createfile->exists(DstPath);
|
||||
if (exist) {
|
||||
createfile->remove(DstPath);
|
||||
}
|
||||
if (!QFile::copy(sourcePath, DstPath)) {
|
||||
}
|
||||
QImage img;
|
||||
img.load(fileName);
|
||||
if (m_srcImgView) {
|
||||
m_srcImgView->setImg(img);
|
||||
}
|
||||
delete createfile;
|
||||
createfile = nullptr;
|
||||
}
|
||||
}
|
||||
else if ("m_pbApply" == strObj)
|
||||
{
|
||||
double realx1 = ui.m_lineEdit_P1X_P->text().toDouble();
|
||||
double realy1 = ui.m_lineEdit_P1Y_P->text().toDouble();
|
||||
double realx2 = ui.m_lineEdit_P2X_P->text().toDouble();
|
||||
double realy2 = ui.m_lineEdit_P2Y_P->text().toDouble();
|
||||
double realx3 = ui.m_lineEdit_P3X_P->text().toDouble();
|
||||
double realy3 = ui.m_lineEdit_P3Y_P->text().toDouble();
|
||||
double realx4 = ui.m_lineEdit_P4X_P->text().toDouble();
|
||||
double realy4 = ui.m_lineEdit_P4Y_P->text().toDouble();
|
||||
|
||||
QPointF realPoint1 = QPointF(realx1, realy1);
|
||||
QPointF realPoint2 = QPointF(realx2, realy2);
|
||||
QPointF realPoint3 = QPointF(realx3, realy3);
|
||||
QPointF realPoint4 = QPointF(realx4, realy4);
|
||||
|
||||
lpGlobalConfig::instance()->real_point1_4P = realPoint1;
|
||||
lpGlobalConfig::instance()->real_point2_4P = realPoint2;
|
||||
lpGlobalConfig::instance()->real_point3_4P = realPoint3;
|
||||
lpGlobalConfig::instance()->real_point4_4P = realPoint4;
|
||||
|
||||
lpGlobalConfig::instance()->pointXOffset_4P = ui.m_lineEdit_Xoffset->text().toDouble();
|
||||
lpGlobalConfig::instance()->pointYOffset_4P = ui.m_lineEdit_Yoffset->text().toDouble();
|
||||
lpGlobalConfig::instance()->point1_4P = m_point1;
|
||||
lpGlobalConfig::instance()->point2_4P = m_point2;
|
||||
lpGlobalConfig::instance()->point3_4P = m_point3;
|
||||
lpGlobalConfig::instance()->point4_4P = m_point4;
|
||||
lpGlobalConfig::instance()->bTransPos_4P = ui.checkBox->isChecked();
|
||||
|
||||
lpGlobalConfig::instance()->testPoint = testPoint;
|
||||
QPolygonF srcPoly;
|
||||
QPolygonF dstPoly;
|
||||
srcPoly << m_point1 << m_point2 << m_point3 << m_point4;
|
||||
dstPoly << realPoint1 << realPoint2 << realPoint3 << realPoint4;
|
||||
lpGlobalConfig::instance()->matxParam_4P = gentransform(srcPoly, dstPoly);
|
||||
|
||||
QPointF tmpTestPoint = transWorldPoint(testPoint, lpGlobalConfig::instance()->matxParam_4P);
|
||||
ui.label_testSrc->setText(QString("(%1,%2)").arg(testPoint.x()).arg(testPoint.y()));
|
||||
ui.label_testDst->setText(QString("(%1,%2)").arg(tmpTestPoint.x()).arg(tmpTestPoint.y()));
|
||||
|
||||
lpGlobalConfig::instance()->saveStandParam();
|
||||
|
||||
ui.label_info->setText("参数已生效");
|
||||
ui.label_info->setStyleSheet("background-color: rgb(250, 168, 55);");
|
||||
if (m_timerID == 0)
|
||||
{
|
||||
m_timerID = startTimer(1000);
|
||||
}
|
||||
}
|
||||
else if ("m_pbExit" == strObj)
|
||||
{
|
||||
close();
|
||||
}
|
||||
else if ("m_pbLock" == strObj)
|
||||
{
|
||||
QString str = ui.m_pbLock->text();
|
||||
if (str == "解锁") {
|
||||
ui.m_pbLock->setText(tr("上锁"));
|
||||
if (m_srcImgView)
|
||||
{
|
||||
m_srcImgView->setLockAll(false);
|
||||
}
|
||||
ui.label_info->setText("已解锁");
|
||||
ui.label_info->setStyleSheet("background-color: rgb(255, 68, 55);");
|
||||
if (m_timerID == 0)
|
||||
{
|
||||
m_timerID = startTimer(1000);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (m_srcImgView)
|
||||
{
|
||||
m_srcImgView->setLockAll(true);
|
||||
}
|
||||
ui.m_pbLock->setText(tr("解锁"));
|
||||
ui.label_info->setText("已上锁");
|
||||
ui.label_info->setStyleSheet("background-color: rgb(255, 68, 55);");
|
||||
if (m_timerID == 0)
|
||||
{
|
||||
m_timerID = startTimer(1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Q_SLOT void lpImageCaliUI4P::onROIChange(const AwesomeRoiInfo& roiInfo, QString strID)
|
||||
{
|
||||
if (strID == "P1")
|
||||
{
|
||||
QPointF p = roiInfo.vertex.at(0);
|
||||
m_point1.setX(p.x());
|
||||
m_point1.setY(p.y());
|
||||
ui.m_lineEdit_P1X->setText(QString("%1").arg(m_point1.x()));
|
||||
ui.m_lineEdit_P1Y->setText(QString("%1").arg(m_point1.y()));
|
||||
}
|
||||
else if (strID == "P2")
|
||||
{
|
||||
QPointF p = roiInfo.vertex.at(0);
|
||||
m_point2.setX(p.x());
|
||||
m_point2.setY(p.y());
|
||||
ui.m_lineEdit_P2X->setText(QString("%1").arg(m_point2.x()));
|
||||
ui.m_lineEdit_P2Y->setText(QString("%1").arg(m_point2.y()));
|
||||
}
|
||||
else if (strID == "P3")
|
||||
{
|
||||
QPointF p = roiInfo.vertex.at(0);
|
||||
m_point3.setX(p.x());
|
||||
m_point3.setY(p.y());
|
||||
ui.m_lineEdit_P3X->setText(QString("%1").arg(m_point3.x()));
|
||||
ui.m_lineEdit_P3Y->setText(QString("%1").arg(m_point3.y()));
|
||||
}
|
||||
else if (strID == "P4")
|
||||
{
|
||||
QPointF p = roiInfo.vertex.at(0);
|
||||
m_point4.setX(p.x());
|
||||
m_point4.setY(p.y());
|
||||
ui.m_lineEdit_P4X->setText(QString("%1").arg(m_point4.x()));
|
||||
ui.m_lineEdit_P4Y->setText(QString("%1").arg(m_point4.y()));
|
||||
}
|
||||
else if (strID == "TEST")
|
||||
{
|
||||
QPointF p = roiInfo.vertex.at(0);
|
||||
testPoint.setX(p.x());
|
||||
testPoint.setY(p.y());
|
||||
QPointF tmpTestPoint = transWorldPoint(testPoint, lpGlobalConfig::instance()->matxParam_4P);
|
||||
ui.label_testSrc->setText(QString("(%1,%2)").arg(testPoint.x()).arg(testPoint.y()));
|
||||
ui.label_testDst->setText(QString("(%1,%2)").arg(tmpTestPoint.x()).arg(tmpTestPoint.y()));
|
||||
}
|
||||
}
|
||||
|
||||
Q_SLOT void lpImageCaliUI4P::onPixelClicked(QPoint point)
|
||||
{
|
||||
int a = 0;
|
||||
}
|
||||
|
||||
Q_SLOT void lpImageCaliUI4P::onImageScale(qreal value)
|
||||
{
|
||||
QString strPath = QApplication::applicationDirPath() + "/showImg.ini";
|
||||
QSettings setting(strPath, QSettings::IniFormat);
|
||||
QObject *obj = sender();
|
||||
setting.setValue("ShowImg/Scale_Standard", value);
|
||||
}
|
||||
|
||||
void lpImageCaliUI4P::AddPoint(QPoint &p, QString strName,QColor color)
|
||||
{
|
||||
if (m_srcImgView)
|
||||
{
|
||||
int x = p.x();
|
||||
int y = p.y();
|
||||
int xp = (x - m_imageW / 2);
|
||||
int yp = (y - m_imageH / 2);
|
||||
m_srcImgView->addPointRoi(QPointF(xp, yp), lpGlobalConfig::instance()->pointCircle, 0, strName, color, QColor(255, 0, 255));
|
||||
}
|
||||
}
|
||||
|
||||
Q_SLOT void lpImageCaliUI4P::onRoiLockIng(QString strName)
|
||||
{
|
||||
ui.label_info->setText("不能操作,请解锁");
|
||||
ui.label_info->setStyleSheet("background-color: rgb(255, 68, 55);");
|
||||
if (m_timerID == 0)
|
||||
{
|
||||
m_timerID = startTimer(1000);
|
||||
}
|
||||
}
|
||||
|
||||
void lpImageCaliUI4P::timerEvent(QTimerEvent *event)
|
||||
{
|
||||
if (m_timerID == event->timerId())
|
||||
{
|
||||
killTimer(m_timerID);
|
||||
m_timerID = 0;
|
||||
ui.label_info->setText("");
|
||||
ui.label_info->setStyleSheet("");
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,48 @@
|
||||
#ifndef _LPIMAGECALIUI4P_H_
|
||||
#define _LPIMAGECALIUI4P_H_
|
||||
|
||||
#include <QWidget>
|
||||
#include "ui_lpImageCaliUI4P.h"
|
||||
#include "AwesomeImgViewer.h"
|
||||
class lpImageCaliUI4P : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
lpImageCaliUI4P(QWidget *parent = Q_NULLPTR);
|
||||
~lpImageCaliUI4P();
|
||||
|
||||
template<typename _Widget>
|
||||
_Widget* replaceWidget(QWidget* pSrcWidget);
|
||||
|
||||
protected:
|
||||
void AddPoint(QPoint &p, QString strName, QColor color = QColor(0, 255, 0));
|
||||
Q_SLOT void onButtonClicked();
|
||||
Q_SLOT void onROIChange(const AwesomeRoiInfo& roiInfo, QString strID);
|
||||
Q_SLOT void onPixelClicked(QPoint point);
|
||||
Q_SLOT void onImageScale(qreal scale);
|
||||
Q_SLOT void onRoiLockIng(QString strName);
|
||||
protected:
|
||||
virtual void showEvent(QShowEvent *event);
|
||||
virtual void changeEvent(QEvent *event);
|
||||
virtual void timerEvent(QTimerEvent *event);
|
||||
private:
|
||||
Ui::lpImageCaliUI4P ui;
|
||||
AwesomeImgViewer *m_srcImgView{ nullptr };
|
||||
int m_imageH{ 0 };
|
||||
int m_imageW{ 0 };
|
||||
|
||||
QPoint m_point1;
|
||||
QPoint m_point2;
|
||||
QPoint m_point3;
|
||||
QPoint m_point4;
|
||||
|
||||
QPoint testPoint;
|
||||
|
||||
double m_length;
|
||||
double m_scale;
|
||||
|
||||
int m_timerID{ 0 };
|
||||
};
|
||||
|
||||
#endif
|
||||
Binary file not shown.
Loading…
Reference in New Issue