Merge pull request #29910 from vrabaud:k4

Only optimize upon 4 distortion parameters when the input has dim==4
This commit is contained in:
Alexander Smorkalov
2026-09-10 08:01:34 +03:00
committed by GitHub
2 changed files with 60 additions and 4 deletions
+13 -4
View File
@@ -2861,9 +2861,10 @@ static Mat prepareDistCoeffs(Mat& distCoeffs0, int rtype, int outputSize)
int n = sz.area();
if (n > 0)
CV_Assert(sz.width == 1 || sz.height == 1);
CV_Assert(n == 0 || n == 4 || n == 5 || n == 8 || n == 12 || n == 14);
CV_Assert((int)distCoeffs0.total() <= outputSize);
Mat distCoeffs = Mat::zeros(sz.width == 1 ? Size(1, outputSize) : Size(outputSize, 1), rtype);
if( n == 4 || n == 5 || n == 8 || n == 12 || n == 14 )
if( n > 0 )
{
distCoeffs0.convertTo(distCoeffs(Rect(Point(), sz)), rtype);
}
@@ -2932,6 +2933,7 @@ double calibrateCameraRO(InputArrayOfArrays _objectPoints,
Mat cameraMatrix = _cameraMatrix.getMat();
cameraMatrix = prepareCameraMatrix(cameraMatrix, rtype, flags);
Mat distCoeffs = _distCoeffs.getMat();
int dist_total = distCoeffs.total();
distCoeffs =
(flags & CALIB_THIN_PRISM_MODEL) &&
!(flags & CALIB_TILTED_MODEL) ?
@@ -2940,7 +2942,10 @@ double calibrateCameraRO(InputArrayOfArrays _objectPoints,
if( !(flags & CALIB_RATIONAL_MODEL) &&
(!(flags & CALIB_THIN_PRISM_MODEL)) &&
(!(flags & CALIB_TILTED_MODEL)))
distCoeffs = distCoeffs.rows == 1 ? distCoeffs.colRange(0, 5) : distCoeffs.rowRange(0, 5);
{
int out_size = (dist_total == 0) ? 5 : std::min(5, dist_total);
distCoeffs = distCoeffs.rows == 1 ? distCoeffs.colRange(0, out_size) : distCoeffs.rowRange(0, out_size);
}
int nimages = int(_objectPoints.total());
CV_Assert( nimages > 0 );
@@ -3115,6 +3120,8 @@ double stereoCalibrate( InputArrayOfArrays _objectPoints,
Mat cameraMatrix2 = _cameraMatrix2.getMat();
Mat distCoeffs1 = _distCoeffs1.getMat();
Mat distCoeffs2 = _distCoeffs2.getMat();
int dist1_total = distCoeffs1.total();
int dist2_total = distCoeffs2.total();
cameraMatrix1 = prepareCameraMatrix(cameraMatrix1, rtype, flags);
cameraMatrix2 = prepareCameraMatrix(cameraMatrix2, rtype, flags);
distCoeffs1 = prepareDistCoeffs(distCoeffs1, rtype, 14);
@@ -3124,8 +3131,10 @@ double stereoCalibrate( InputArrayOfArrays _objectPoints,
(!(flags & CALIB_THIN_PRISM_MODEL)) &&
(!(flags & CALIB_TILTED_MODEL)))
{
distCoeffs1 = distCoeffs1.rows == 1 ? distCoeffs1.colRange(0, 5) : distCoeffs1.rowRange(0, 5);
distCoeffs2 = distCoeffs2.rows == 1 ? distCoeffs2.colRange(0, 5) : distCoeffs2.rowRange(0, 5);
int out_size1 = (dist1_total == 0) ? 5 : std::min(5, dist1_total);
int out_size2 = (dist2_total == 0) ? 5 : std::min(5, dist2_total);
distCoeffs1 = distCoeffs1.rows == 1 ? distCoeffs1.colRange(0, out_size1) : distCoeffs1.rowRange(0, out_size1);
distCoeffs2 = distCoeffs2.rows == 1 ? distCoeffs2.colRange(0, out_size2) : distCoeffs2.rowRange(0, out_size2);
}
if((flags & CALIB_USE_EXTRINSIC_GUESS) == 0)
@@ -1898,4 +1898,51 @@ TEST(Calib_StereoCalibrate, regression_22421)
EXPECT_LE(terr, 0.0000001);
}
TEST(Calib_CalibrateCamera, size4DistortionCoeffs)
{
std::vector<std::vector<cv::Point3f>> objectPoints(3);
std::vector<std::vector<cv::Point2f>> imagePoints(3);
cv::Size boardSize(9, 6);
for (int i = 0; i < 3; i++) {
for (int y = 0; y < boardSize.height; y++) {
for (int x = 0; x < boardSize.width; x++) {
objectPoints[i].push_back(cv::Point3f(x * 0.1f, y * 0.1f, 0.f));
}
}
}
cv::Matx33d cameraMatrix(800, 0, 320, 0, 800, 240, 0, 0, 1);
cv::Vec4d distCoeffs(0.1, -0.05, 0.001, -0.002);
for (int i = 0; i < 3; i++) {
cv::Vec3d rvec(0.1 * i, -0.2 * i, 0.05 * i);
cv::Vec3d tvec(-0.1 * i, 0.05 * i, 1.0 + 0.1 * i);
cv::projectPoints(objectPoints[i], rvec, tvec, cameraMatrix, distCoeffs, imagePoints[i]);
}
// 1. Test calibrateCamera
cv::Matx33d cameraMatrix_est = cameraMatrix;
cv::Mat1d distCoeffs_est = cv::Mat1d::zeros(1, 4);
std::vector<cv::Mat> rvecs, tvecs;
double rms = cv::calibrateCamera(objectPoints, imagePoints, cv::Size(640, 480),
cameraMatrix_est, distCoeffs_est, rvecs, tvecs,
cv::CALIB_USE_INTRINSIC_GUESS);
EXPECT_LT(rms, 1e-4);
EXPECT_LE(cv::norm(cv::Vec4d(distCoeffs_est), distCoeffs, NORM_INF), 1e-4);
// 2. Test stereoCalibrate
cv::Matx33d K1 = cameraMatrix;
cv::Matx33d K2 = cameraMatrix;
cv::Mat1d D1 = cv::Mat1d::zeros(1, 4);
cv::Mat1d D2 = cv::Mat1d::zeros(1, 4);
cv::Mat R, T, E, F;
double stereo_rms = cv::stereoCalibrate(objectPoints, imagePoints, imagePoints,
K1, D1, K2, D2, cv::Size(640, 480),
R, T, E, F, cv::CALIB_USE_INTRINSIC_GUESS);
EXPECT_LT(stereo_rms, 1e-4);
EXPECT_LE(cv::norm(cv::Vec4d(D1), distCoeffs, NORM_INF), 1e-4);
EXPECT_LE(cv::norm(cv::Vec4d(D2), distCoeffs, NORM_INF), 1e-4);
}
}} // namespace