如何编写Qt的过程中出现问题可以参见
#pragma once
#include
#include
#include "ui_oneImageCalibration.h"
#include "opencv2/opencv.hpp"
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include
#include
#include
#include
#include
using namespace cv;
class InnerOuterParam
{
public:
//摄像机内参数矩阵 3x3矩阵
Mat cameraMatrix;
//摄像机的5个畸变系数:k1,k2,p1,p2,k3 1x5矩阵
Mat distCoeffs;
//每幅图像的旋转向量
std::vector<Mat> rvecsMat;
//每幅图像的平移向量
std::vector<Mat> tvecsMat;
InnerOuterParam(Mat cameraMatrix, Mat distCoeffs, std::vector<Mat> rvecsMat, std::vector<Mat> tvecsMat);
~InnerOuterParam();
};
#include "InnerOuterParam.h"
#include
#include
using namespace std;
/*
构造函数
*/
InnerOuterParam::InnerOuterParam(Mat cameraMatrix, Mat distCoeffs, vector<Mat> tvecsMat, vector<Mat> rvecsMat)
{
this->cameraMatrix = cameraMatrix;
this->distCoeffs = distCoeffs;
this->tvecsMat = tvecsMat;
this->rvecsMat = rvecsMat;
}
/*
析构函数
*/
InnerOuterParam::~InnerOuterParam()
{
}
#pragma once
#include "InnerOuterParam.h"
#include
#include
#include "ui_oneImageCalibration.h"
#include "opencv2/opencv.hpp"
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include
#include
#include
#include
#include
using namespace cv;
class oneImageCalibration : public QMainWindow
{
Q_OBJECT
public:
oneImageCalibration(QWidget* parent = Q_NULLPTR);
~oneImageCalibration();
QImage MatImageToQt(const Mat& src);
//在“原始画面”显示拍照画面
void takePhotoShow();
//世界坐标系,获取物体点坐标(单位mm)
std::vector<std::vector<Point3f>> getObjectPoints();
//像素坐标系,提取角点坐标(单位pixel)并展示
std::vector<std::vector<Point2f>> extractConers();
//标定,世界坐标系-物体点坐标(单位mm)》像素坐标系-角点坐标(单位pixel)
InnerOuterParam* calibrateObjectPointsConers(std::vector<std::vector<Point3f>> objectPoints, std::vector<std::vector<Point2f>> cornersList);
//校正,校正并存储校正图像
void undistortImageStore(InnerOuterParam* innerOuterParam);
//展示内参外参
void showParams(InnerOuterParam* innerOuterParam);
private slots:
void on_label_linkActivated(const QString& link);
//点击“打开相机”按钮》打开摄像头
void on_pushButton_camera_clicked();
//点击“标定”按钮》进行标定
void on_pushButton_calibration_clicked();
//点击“显示矫正画面”按钮》展示矫正画面
void on_pushButton_show_calibration_clicked();
//读取当前帧信息
void readFarme();
private:
Ui::oneImageCalibrationClass* ui;
//视频捕获
VideoCapture cap;
Mat src_image;
QTimer* timer;
QImage* image;
};
#include "oneImageCalibration.h"
#include "InnerOuterParam.h"
#include
#include
using namespace std;
/*
构造函数
*/
oneImageCalibration::oneImageCalibration(QWidget* parent)
: QMainWindow(parent)
, ui(new Ui::oneImageCalibrationClass)
{
ui->setupUi(this);
timer = new QTimer(this);
image = new QImage();
//信号和槽
//时间到,读取当前摄像头信息
connect(timer, SIGNAL(timeout()), this, SLOT(readFarme()));
}
/*
析构函数
*/
oneImageCalibration::~oneImageCalibration()
{
delete ui;
}
void oneImageCalibration::on_label_linkActivated(const QString& link)
{
}
/*
打开摄像头
*/
void oneImageCalibration::on_pushButton_camera_clicked()
{
cout << "打开摄像头";
cap.open(0);
timer->start(33);
}
/*
进行标定
*/
void oneImageCalibration::on_pushButton_calibration_clicked()
{
this->takePhotoShow();
if (src_image.empty()) {
cout << "读取图像失败" << endl;
exit(1);
}
vector<vector<Point3f>> objectPoints = this->getObjectPoints();
vector<vector<Point2f>> cornersList = this->extractConers();
InnerOuterParam* innerOuterParam = this->calibrateObjectPointsConers(objectPoints, cornersList);
this->undistortImageStore(innerOuterParam);
this->showParams(innerOuterParam);
//释放堆区的innerOuterParam对象
delete innerOuterParam;
}
/*
在“原始画面”显示拍照画面
*/
void oneImageCalibration::takePhotoShow()
{
QImage imag = MatImageToQt(src_image);
//ui对象就是*.ui
ui->origin_label->setPixmap(QPixmap::fromImage(imag));
//关闭摄像头
timer->stop();
cap.release();
}
/*
世界坐标系,获取物体点坐标(单位mm)
*/
vector<vector<Point3f>> oneImageCalibration::getObjectPoints()
{
//保存每个标定板上角点的三维坐标 ,真实世界坐标
vector<vector<Point3f>> objectPoints;
//初始化标定板上角点的三维坐标,真实世界坐标
vector<Point3f> tempPointSet;
//实际测量得到的标定板上每个棋盘格的大小,单位mm
Size squareSize = Size(28, 28);
//标定板上每行、列的角点数,简单理解为去掉最外面一圈图块,注意宽=8和高=6的顺序
Size patternSize = Size(8, 6);
//patternSize宽=8和高=6
for (int i = 0; i < patternSize.height; i++)
{
for (int j = 0; j < patternSize.width; j++)
{
//真实世界坐标
Point3f realPoint;
//假设标定板放在世界坐标系中z=0的平面上 squareSize.width=28mm squareSize.height=28mm
realPoint.x = j * squareSize.width;
realPoint.y = i * squareSize.height;
realPoint.z = 0;
tempPointSet.push_back(realPoint);
}
}
objectPoints.push_back(tempPointSet);
return objectPoints;
}
/*
像素坐标系,提取角点坐标(单位pixel)并展示
*/
vector<vector<Point2f>> oneImageCalibration::extractConers()
{
/*
角点:提取角点并展示到origin_label
extractConersShow
*/
//保存每张标定图上检测到的所有角点,保存每张标定图上检测到的所有亚像素精确化角点
vector<vector<Point2f>> cornersList;
//标定板上每行、列的角点数,简单理解为去掉最外面一圈图块,注意宽=8和高=6的顺序
Size patternSize = Size(8, 6);
//缓存每幅图像上检测到的角点
vector<Point2f> corners;
string filename;
//存储所有文件名
vector<string> filenameList;
//提取角点
if (findChessboardCorners(src_image, patternSize, corners) == 0) {
cout << "找不到角点" << endl;
exit(1);
}
//亚像素精确化
else
{
Mat gray;
cvtColor(src_image, gray, COLOR_BGR2GRAY);
//对粗提取的角点进行精确化
find4QuadCornerSubpix(gray, corners, Size(5, 5));
//对粗提取的角点进行精确化,保存亚像素角点
cornersList.push_back(corners);
cout << "角点数量: " << corners.size() << endl;
//在图像上显示角点位置,并展示在origin_label中
drawChessboardCorners(src_image, patternSize, corners, true);
QImage imag = MatImageToQt(src_image);
ui->origin_label->clear();
ui->origin_label->setPixmap(QPixmap::fromImage(imag));
}
return cornersList;
}
/*
标定,世界坐标系-物体点坐标(单位mm)》像素坐标系-角点坐标(单位pixel)
*/
InnerOuterParam* oneImageCalibration::calibrateObjectPointsConers(vector<vector<Point3f>> objectPoints, vector<vector<Point2f>> cornersList)
{
//图像整体像素大小
Size imageSize;
imageSize.height = src_image.rows;
imageSize.width = src_image.cols;
//摄像机内参数矩阵 3x3矩阵
Mat cameraMatrix = Mat(3, 3, CV_32FC1, Scalar::all(0));
//摄像机的5个畸变系数:k1,k2,p1,p2,k3 1x5矩阵
Mat distCoeffs = Mat(1, 5, CV_32FC1, Scalar::all(0));
//每幅图像的平移向量
vector<Mat> tvecsMat;
//每幅图像的旋转向量
vector<Mat> rvecsMat;
/*
标定:真实世界坐标点+像素坐标点》内参+外参
*/
calibrateCamera(objectPoints, cornersList, imageSize, cameraMatrix, distCoeffs, rvecsMat, tvecsMat, 0);
//new 堆区创建对象必须手动销毁
InnerOuterParam* innerOuterParam = new InnerOuterParam(cameraMatrix, distCoeffs, rvecsMat, tvecsMat);
return innerOuterParam;
}
/*
校正,校正并存储校正图像
*/
void oneImageCalibration::undistortImageStore(InnerOuterParam* innerOuterParam)
{
/*
矫正
*/
Mat dst_image = src_image.clone();
undistort(src_image, dst_image, innerOuterParam->cameraMatrix, innerOuterParam->distCoeffs);
/*
存储标定结果
*/
QImage imag_dst = MatImageToQt(dst_image);
imag_dst.save("calibdata.BMP", "BMP", 100);
}
/*
展示内参外参
*/
void oneImageCalibration::showParams(InnerOuterParam* innerOuterParam)
{
//将旋转向量转换为相对应的旋转矩阵
Mat rotationMatrix = Mat(3, 3, CV_32FC1, Scalar::all(0));
Rodrigues(innerOuterParam->rvecsMat[0], rotationMatrix);
//将平移向量转化为相对应的平移矩阵
Mat translationMatrix = Mat(innerOuterParam->tvecsMat[0]);
/*
展示内参外参
*/
ui->text_inner->document()->setMaximumBlockCount(100);
ui->text_outer->document()->setMaximumBlockCount(100);
stringstream stream;
QString str;
stream << innerOuterParam->cameraMatrix;
str = QString::fromStdString(stream.str());
ui->text_inner->append("cameraMatrix: " + str);
stream.clear();
stream << innerOuterParam->distCoeffs;
str = QString::fromStdString(stream.str());
ui->text_inner->append("distCoeffs: " + str);
stream.clear();
stream << rotationMatrix;
str = QString::fromStdString(stream.str());
ui->text_outer->append("rotationMatrix: " + str);
stream.clear();
stream << translationMatrix;
str = QString::fromStdString(stream.str());
ui->text_outer->append("translationMatrix: " + str);
}
/*
展示矫正画面
*/
void oneImageCalibration::on_pushButton_show_calibration_clicked()
{
Mat srcImage = imread("calibdata.BMP");
QImage imag = MatImageToQt(srcImage);
ui->fix_label->setPixmap(QPixmap::fromImage(imag));
}
/*
原始画面
*/
void oneImageCalibration::readFarme()
{
//将相机画面读取到src_image中
cap.read(src_image);
QImage imag = MatImageToQt(src_image);
//ui对象就是*.ui
ui->origin_label->setPixmap(QPixmap::fromImage(imag));
}
/*
Mat转成QImage
*/
QImage oneImageCalibration::MatImageToQt(const Mat& src)
{
if (src.type() == CV_8UC1)
{
QImage qImage(src.cols, src.rows, QImage::Format_Indexed8);
qImage.setColorCount(256);
for (int i = 0; i < 256; i++)
{
qImage.setColor(i, qRgb(i, i, i));
}
uchar* pSrc = src.data;
for (int row = 0; row < src.rows; row++)
{
uchar* pDest = qImage.scanLine(row);
memcmp(pDest, pSrc, src.cols);
pSrc += src.step;
}
return qImage;
}
else if (src.type() == CV_8UC3)
{
const uchar* pSrc = (const uchar*)src.data;
QImage qImage(pSrc, src.cols, src.rows, src.step, QImage::Format_RGB888);
return qImage.rgbSwapped();
}
else if (src.type() == CV_8UC4)
{
const uchar* pSrc = (const uchar*)src.data;
QImage qImage(pSrc, src.cols, src.rows, src.step, QImage::Format_ARGB32);
return qImage.copy();
}
else
{
return QImage();
}
}
#include "oneImageCalibration.h"
#include
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
oneImageCalibration w;
w.show();
return a.exec();
}
参见下面文章中 章节“打包发布Qt和*.exe”