三维成像|相机标定与图像校正助手(VS+OpenCV+Qt实现)

环境:VS2019+OpenCV4.4+Qt5.12.3
软件打包软件:Inno Setup Compiler
链接库搜索软件:Everything
实现功能:相机标定;图像校正
界面分布:标定区;校正区;控制台;操作反馈;参数显示
作者联系方式:936874728
【三维成像|相机标定与图像校正助手(VS+OpenCV+Qt实现)】界面实现
三维成像|相机标定与图像校正助手(VS+OpenCV+Qt实现)
文章图片

软件功能实现
三维成像|相机标定与图像校正助手(VS+OpenCV+Qt实现)
文章图片

告警提示,鲁棒性增强
三维成像|相机标定与图像校正助手(VS+OpenCV+Qt实现)
文章图片

三维成像|相机标定与图像校正助手(VS+OpenCV+Qt实现)
文章图片

三维成像|相机标定与图像校正助手(VS+OpenCV+Qt实现)
文章图片

三维成像|相机标定与图像校正助手(VS+OpenCV+Qt实现)
文章图片

工程
三维成像|相机标定与图像校正助手(VS+OpenCV+Qt实现)
文章图片

核心代码展示:
#联系方式: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() { ...}

    推荐阅读