-
Notifications
You must be signed in to change notification settings - Fork 267
Description
Environment:
BoofApplications Version: Latest
OpenCV Version:4.11.0
Operating System:ubuntu 22.04
Description:
When calibrating a monocular camera using the latest BoofApplications, I captured calibration images using a chessboard pattern (9x12 array, 60mm square size). During calibration, distortion parameters k1-k6 and tangential parameters p1, p2 were enabled. The calibration achieved an average reprojection error of 0.068, indicating good accuracy.
However, after importing the calibrated camera intrinsic and distortion parameters into OpenCV for image undistortion, the resulting undistorted images significantly differ from those produced directly by BoofApplications. The discrepancy is visually evident, with OpenCV's undistorted output not matching the BoofApplications undistortion.
Steps to Reproduce:
Calibrate camera using BoofApplications with the provided chessboard pattern.
Export the obtained intrinsic and distortion parameters.
Import these parameters into an OpenCV application to perform image undistortion.
Compare OpenCV undistortion results with those produced by BoofApplications.
Expected Behavior:
The undistorted images from OpenCV should closely match the undistortion results produced by BoofApplications, assuming the same parameters and images are used.
Actual Behavior:
The undistorted images produced by OpenCV differ notably from BoofApplications' results.
Attachments:
#include <opencv2/opencv.hpp>
#include <iostream>
#include <vector>
#include <string>
#include <cmath>
#include <yaml-cpp/yaml.h>
// 使用 YAML-CPP 读取相机内参和畸变参数,并转换为 OpenCV 格式
// 输出:cameraMatrix 为 3x3 内参矩阵,distCoeffs 为 14x1 畸变参数矩阵
bool readCameraParametersUsingYamlCpp(const std::string &filename, cv::Mat &cameraMatrix, cv::Mat &distCoeffs)
{
try
{
// 加载 YAML 文件
YAML::Node config = YAML::LoadFile(filename);
// 读取相机内参
double fx = config["pinhole"]["fx"].as<double>();
double fy = config["pinhole"]["fy"].as<double>();
double cx = config["pinhole"]["cx"].as<double>();
double cy = config["pinhole"]["cy"].as<double>();
double skew = config["pinhole"]["skew"].as<double>();
// 构造 3x3 相机矩阵
// [ fx skew cx ]
// [ 0 fy cy ]
// [ 0 0 1 ]
cameraMatrix = (cv::Mat_<double>(3, 3) << fx, skew, cx, 0, fy, cy, 0, 0, 1);
// 读取畸变参数
YAML::Node radial_node = config["radial_tangential"]["radial"];
if (radial_node.size() < 6)
{
std::cerr << "径向畸变参数数量不足!" << std::endl;
return false;
}
double t1 = config["radial_tangential"]["t1"].as<double>();
double t2 = config["radial_tangential"]["t2"].as<double>();
// 构造 OpenCV 要求的 1x8 畸变系数矩阵
// 顺序:[k1, k2, p1, p2, k3, k4, k5, k6]
distCoeffs = cv::Mat::zeros(14, 1, CV_64F);
distCoeffs.at<double>(0) = radial_node[0].as<double>(); // k1
distCoeffs.at<double>(1) = radial_node[1].as<double>(); // k2
distCoeffs.at<double>(2) = t1; // p1
distCoeffs.at<double>(3) = t2; // p2
distCoeffs.at<double>(4) = radial_node[2].as<double>(); // k3
distCoeffs.at<double>(5) = radial_node[3].as<double>(); // k4
distCoeffs.at<double>(6) = radial_node[4].as<double>(); // k5
distCoeffs.at<double>(7) = radial_node[5].as<double>(); // k6
return true;
}
catch (const YAML::Exception &e)
{
std::cerr << "YAML 解析异常: " << e.what() << std::endl;
return false;
}
}
int main()
{
// 1. 假设已知的相机内参和畸变
cv::Mat cameraMatrix;
cv::Mat distCoeffs;
readCameraParametersUsingYamlCpp("/workspace/calibrate/data/intrinsics.yaml", cameraMatrix, distCoeffs);
std::cout << "Camera Matrix:\n"
<< cameraMatrix << std::endl;
std::cout << "Distortion Coefficients:\n"
<< distCoeffs << std::endl;
// 2. 棋盘参数
cv::Size boardSize(8, 11); // 6 列角点 x 9 行角点
float squareSize = 60.f; // 每格 20mm (示例)
// 3. 多张棋盘图片的路径(此处示例用空容器,实战中请填入实际路径)
std::vector<std::string> imageFiles;
for (size_t i = 1; i < 16; i++)
{
imageFiles.push_back(std::string("/workspace/calibrate/data/") + std::to_string(i) + ".bmp");
}
// 5. 遍历每一张图
for (const auto &filename : imageFiles)
{
cv::Mat image = cv::imread(filename, cv::IMREAD_COLOR);
if (image.empty())
{
std::cerr << "Failed to load image: " << filename << std::endl;
continue;
}
// ----------------------- 可视化去畸变效果 -----------------------
// 使用 getOptimalNewCameraMatrix 计算新的内参矩阵(可选)
cv::Mat newCameraMatrix = cv::getOptimalNewCameraMatrix(cameraMatrix, distCoeffs, image.size(), 1, image.size());
cv::Mat undistortedImage;
cv::undistort(image, undistortedImage, cameraMatrix, distCoeffs, newCameraMatrix);
// 显示原图和去畸变后的图像
cv::imshow("Original Image", image);
cv::imshow("Undistorted Image", undistortedImage);
cv::waitKey(0); // 按任意键继续
}
return 0;
}Could you please investigate this issue or advise on potential causes for the observed discrepancy?




