环境:VS2019+OpenCV4.4+Qt5.12.3【三维成像|相机标定与图像校正助手(VS+OpenCV+Qt实现)】界面实现
软件打包软件:Inno Setup Compiler
链接库搜索软件:Everything
实现功能:相机标定;图像校正
界面分布:标定区;校正区;控制台;操作反馈;参数显示
作者联系方式:936874728
文章图片
软件功能实现
文章图片
告警提示,鲁棒性增强
文章图片
文章图片
文章图片
文章图片
工程
文章图片
核心代码展示:
#联系方式:936874728
#include "CamCali.h"
#pragma execution_character_set("utf-8") // 解决汉字乱码问题
#include
#include // 提示信息
#include
#include //文件流操作的头文件
#include
#include
#include
#include
#include
#include CamCali::CamCali(QWidget* parent)
: QWidget(parent)
{
ui.setupUi(this);
// 标定板尺寸提示字样
ui.lineEdit_brd_x->setPlaceholderText("宽:8");
...
ui.lineEdit_brd_size->setPlaceholderText("尺寸:5");
// 添加槽链接,链接按键与按键函数
QObject::connect(ui.in_btn_sel, SIGNAL(clicked()), this, SLOT(in_btn_sel()));
// 选择标定图片
...
QObject::connect(ui.save_btn_adjust, SIGNAL(clicked()), this, SLOT(save_btn_adjust()));
// 保存矫正图
}// convertAbsolutePathToRelative()函数具体实现如下
QString convertAbsolutePathToRelative(const QString& absolute_path)
{
QString current_path = QDir::currentPath();
// 当前路径,如 C:\windows的形式
QString tmp_str = absolute_path;
// 绝对路径,如 C:\windows\system32\cmd.exe的形式
...
return tmp_str;
// 返回相对路径
}// 按键功能实现// 选择标定图片
void CamCali::in_btn_sel() {
//QString strs;
//QStringList file_list, output_name;
QStringList str_path_list = QFileDialog::getOpenFileNames(this, tr("选择标定文件"), tr("./"), tr("图片文件(*.jpg *.bmp *png);
;
所有文件(*.*);
;
"));
if (str_path_list.empty()) {
ui.opera_edit->append("没有选定标定文件");
return;
}
...
file.close();
}// 相机标定按键功能实现
void CamCali::out_btn_cali() { // 输出相机标定图片 // 读取标定板尺寸信息
int x = ui.lineEdit_brd_x->text().toInt();
... // 判断是否输入标定板尺寸信息
if (ui.lineEdit_brd_x->text().isEmpty() && ui.lineEdit_brd_y->text().isEmpty() && ui.lineEdit_brd_size->text().isEmpty())
{
QMessageBox::warning(this, tr("warning!"), tr("请输入棋盘格的宽度x,长度y,尺寸length"), QMessageBox::Yes);
return;
}
else
{
// 读取图像文件的路径
ifstream inImgPath("cali.txt");
//ifstream读操作(输入)标定所用图像文件的路径
...// 标定板角点提取
ui.opera_edit->append("开始提取角点......");
ui.opera_edit->append("遍历每一幅图片......");
...
if (findChessboardCorners(imageInput, pattern_size, corner_points_buf) == 0) //寻找图片中的角点
{
//找不到角点
ui.opera_edit->append("提取不到角点");
QMessageBox::warning(this, tr("warning!"), tr("找不到角点"), QMessageBox::Yes);
return;
}
else
{
...
}
}
int total = corner_points_of_all_imgs.size();
int cornerNum = pattern_size.width * pattern_size.height;
//每张图片上的总的角点数
...
ui.opera_edit->append("角点提取完成");
// 摄像机标定
ui.opera_edit->append("开始摄像机标定......");
/*为标定参数分配内存*/
cameraMatrix = cv::Mat(3, 3, CV_32FC1, cv::Scalar::all(0));
//内外参矩阵,H--单应性矩阵
distCoefficients = cv::Mat(1, 5, CV_32FC1, cv::Scalar::all(0));
//摄像机的5个畸变系数:k1,k2,p1,p2,k3vectortvecsMat;
//每幅图像的平移向量,t
vectorrvecsMat;
//每幅图像的旋转向量(罗德里格旋转向量)
vector> objectPoints;
//保存所有图片的角点的三维坐标,初始化每一张图片中标定板上角点的三维坐标...
ui.opera_edit->append("标定完成");
// 开始保存标定结果
ui.opera_edit->append("开始保存标定结果");
//相机内外参数
fout << "相机相关参数:" << endl;
fout << "1.内外参矩阵:" << endl;
fout << "大小:" << cameraMatrix.size() << endl;
fout << cameraMatrix << endl;
//相机畸变系数
fout << "2.畸变系数:" << endl;
fout << "大小:" << distCoefficients.size() << endl;
fout << distCoefficients << endl;
//图像相关参数
fout << endl << "图像相关参数:" << endl;
cv::Mat rotation_Matrix = cv::Mat(3, 3, CV_32FC1, cv::Scalar::all(0));
//旋转矩阵
for (i = 0;
i < image_num;
i++)
{
//旋转矩阵
fout << "第" << i + 1 << "幅图像的旋转向量:" << endl;
fout << rvecsMat[i] << endl;
fout << "第" << i + 1 << "幅图像的旋转矩阵:" << endl;
cv::Rodrigues(rvecsMat[i], rotation_Matrix);
//将旋转向量转换位相对应的旋转矩阵
//平移向量
fout << rotation_Matrix << endl;
fout << "第" << i + 1 << "幅图像的平移向量:" << endl;
fout << tvecsMat[i] << endl;
}ui.opera_edit->append("结果保存完毕");
// 对标定结果进行评价
ui.opera_edit->append("开始评价标定结果......");
//计算每幅图像中的角点数量,假设全部角点都检测到了
int corner_points_counts;
/*角点总数*/
corner_points_counts = pattern_size.width * pattern_size.height;
fout << "每幅图像的标定误差:" << endl;
...
ui.opera_edit->append("评价完成");
fout.close();
// 矫正图像
cv::Mat mapx = cv::Mat(image_size, CV_32FC1);
cv::Mat mapy = cv::Mat(image_size, CV_32FC1);
cv::Mat R = cv::Mat::eye(3, 3, CV_32F);
ui.opera_edit->append("保存矫正图像");
...
ui.opera_edit->append("保存结束");
cv::waitKey(0);
} // 显示标定参数
QString displayString;
QFile file("caliberation_result.txt");
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
{
ui.opera_edit->append("没有找到参数文件");
}
while (!file.atEnd())
{
QByteArray line = file.readLine();
QString str(line);
//ui.opera_edit->append(str);
displayString.append(str);
}
ui.para_edit->clear();
ui.para_edit->setPlainText(displayString);
}// 图像校正功能实现
void CamCali::out_btn_adjust() { // 输出校正图像 if (cameraMatrix.empty()) {
ui.opera_edit->append("没有相机内参,请标定");
return;
}
if (distCoefficients.empty()) {
ui.opera_edit->append("没有相机畸变参数,请标定");
return;
} ...
//
cv::Mat mapx = cv::Mat(image_size, CV_32FC1);
cv::Mat mapy = cv::Mat(image_size, CV_32FC1);
cv::Mat R = cv::Mat::eye(3, 3, CV_32F);
ui.opera_edit->append("保存矫正图像");
string imageFileName;
std::stringstream StrStm;
cv::initUndistortRectifyMap(cameraMatrix, distCoefficients, R, cameraMatrix, image_size, CV_32FC1, mapx, mapy);
...
ui.show_outadjustpic->setPixmap(QPixmap::fromImage(Qtemp));
ui.show_outadjustpic->setScaledContents(true);
ui.show_outadjustpic->show();
adjustPic = new_image;
}
else {
ui.opera_edit->append("畸变图像打开失败");
}}// 保存校正图像
void CamCali::save_btn_adjust() { ...}
推荐阅读
- PHP array_diff()函数用法示例介绍
- Java中的length vs length()的差别和对比
- C++中的string find函数用法示例
- 算法设计(使用XOR和表查找计算数字的奇偶校验)
- Scala StringContext介绍和详细用法
- Python在list中的替代元素求和
- 算法设计(查找给定总和的子数组|S1(非负实数))
- 算法设计(查找插入0的两个数组的最大点积)
- JavaScript日期用法介绍和示例