Merge pull request #25943 from asmorkalov:as/fisheye_distrort_newk

Added fisheye::distortPoints with non-identity projection matrix
This commit is contained in:
Alexander Smorkalov 2024-08-05 19:33:18 +03:00 committed by GitHub
commit 333054e05e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 147 additions and 2 deletions

View File

@ -3835,10 +3835,25 @@ namespace fisheye
@param distorted Output array of image points, 1xN/Nx1 2-channel, or vector\<Point2f\> .
Note that the function assumes the camera intrinsic matrix of the undistorted points to be identity.
This means if you want to distort image points you have to multiply them with \f$K^{-1}\f$.
This means if you want to distort image points you have to multiply them with \f$K^{-1}\f$ or
use another function overload.
*/
CV_EXPORTS_W void distortPoints(InputArray undistorted, OutputArray distorted, InputArray K, InputArray D, double alpha = 0);
/** @overload
Overload of distortPoints function to handle cases when undistorted points are got with non-identity
camera matrix, e.g. output of #estimateNewCameraMatrixForUndistortRectify.
@param undistorted Array of object points, 1xN/Nx1 2-channel (or vector\<Point2f\> ), where N is
the number of points in the view.
@param Kundistorted Camera intrinsic matrix used as new camera matrix for undistortion.
@param K Camera intrinsic matrix \f$cameramatrix{K}\f$.
@param D Input vector of distortion coefficients \f$\distcoeffsfisheye\f$.
@param alpha The skew coefficient.
@param distorted Output array of image points, 1xN/Nx1 2-channel, or vector\<Point2f\> .
@sa estimateNewCameraMatrixForUndistortRectify
*/
CV_EXPORTS_W void distortPoints(InputArray undistorted, OutputArray distorted, InputArray Kundistorted, InputArray K, InputArray D, double alpha = 0);
/** @brief Undistorts 2D points using fisheye model
@param distorted Array of object points, 1xN/Nx1 2-channel (or vector\<Point2f\> ), where N is the

View File

@ -315,6 +315,48 @@ void cv::fisheye::distortPoints(InputArray undistorted, OutputArray distorted, I
}
}
void cv::fisheye::distortPoints(InputArray _undistorted, OutputArray distorted, InputArray Kundistorted, InputArray K, InputArray D, double alpha)
{
CV_INSTRUMENT_REGION();
CV_Assert(_undistorted.type() == CV_32FC2 || _undistorted.type() == CV_64FC2);
CV_Assert(Kundistorted.size() == Size(3,3) && (Kundistorted.type() == CV_32F || Kundistorted.type() == CV_64F));
cv::Mat undistorted = _undistorted.getMat();
cv::Mat normalized(undistorted.size(), CV_64FC2);
Mat Knew = Kundistorted.getMat();
double cx, cy, fx, fy;
if (Knew.depth() == CV_32F)
{
fx = (double)Knew.at<float>(0, 0);
fy = (double)Knew.at<float>(1, 1);
cx = (double)Knew.at<float>(0, 2);
cy = (double)Knew.at<float>(1, 2);
}
else
{
fx = Knew.at<double>(0, 0);
fy = Knew.at<double>(1, 1);
cx = Knew.at<double>(0, 2);
cy = Knew.at<double>(1, 2);
}
size_t n = undistorted.total();
const Vec2f* Xf = undistorted.ptr<Vec2f>();
const Vec2d* Xd = undistorted.ptr<Vec2d>();
Vec2d* normXd = normalized.ptr<Vec2d>();
for (size_t i = 0; i < n; i++)
{
Vec2d p = undistorted.depth() == CV_32F ? (Vec2d)Xf[i] : Xd[i];
normXd[i][0] = (p[0] - cx) / fx;
normXd[i][1] = (p[1] - cy) / fy;
}
cv::fisheye::distortPoints(normalized, distorted, K, D, alpha);
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// cv::fisheye::undistortPoints

View File

@ -107,7 +107,6 @@ TEST_F(fisheyeTest, distortUndistortPoints)
int height = imageSize.height;
/* Create test points */
std::vector<cv::Point2d> points0Vector;
cv::Mat principalPoints = (cv::Mat_<double>(5, 2) << K(0, 2), K(1, 2), // (cx, cy)
/* Image corners */
0, 0,
@ -150,6 +149,95 @@ TEST_F(fisheyeTest, distortUndistortPoints)
}
}
TEST_F(fisheyeTest, distortUndistortPointsNewCameraFixed)
{
int width = imageSize.width;
int height = imageSize.height;
/* Random points inside image */
cv::Mat xy[2] = {};
xy[0].create(100, 1, CV_64F);
theRNG().fill(xy[0], cv::RNG::UNIFORM, 0, width); // x
xy[1].create(100, 1, CV_64F);
theRNG().fill(xy[1], cv::RNG::UNIFORM, 0, height); // y
cv::Mat randomPoints;
merge(xy, 2, randomPoints);
cv::Mat points0 = randomPoints;
cv::Mat Reye = cv::Mat::eye(3, 3, CV_64FC1);
cv::Mat Knew;
cv::fisheye::estimateNewCameraMatrixForUndistortRectify(K, D, imageSize, Reye, Knew);
/* Distort -> Undistort */
cv::Mat distortedPoints;
cv::fisheye::distortPoints(points0, distortedPoints, Knew, K, D);
cv::Mat undistortedPoints;
cv::fisheye::undistortPoints(distortedPoints, undistortedPoints, K, D, Reye, Knew);
EXPECT_MAT_NEAR(points0, undistortedPoints, 1e-8);
/* Undistort -> Distort */
cv::fisheye::undistortPoints(points0, undistortedPoints, K, D, Reye, Knew);
cv::fisheye::distortPoints(undistortedPoints, distortedPoints, Knew, K, D);
EXPECT_MAT_NEAR(points0, distortedPoints, 1e-8);
}
TEST_F(fisheyeTest, distortUndistortPointsNewCameraRandom)
{
int width = imageSize.width;
int height = imageSize.height;
/* Create test points */
std::vector<cv::Point2d> points0Vector;
cv::Mat principalPoints = (cv::Mat_<double>(5, 2) << K(0, 2), K(1, 2), // (cx, cy)
/* Image corners */
0, 0,
0, height,
width, 0,
width, height
);
/* Random points inside image */
cv::Mat xy[2] = {};
xy[0].create(100, 1, CV_64F);
theRNG().fill(xy[0], cv::RNG::UNIFORM, 0, width); // x
xy[1].create(100, 1, CV_64F);
theRNG().fill(xy[1], cv::RNG::UNIFORM, 0, height); // y
cv::Mat randomPoints;
merge(xy, 2, randomPoints);
cv::Mat points0;
cv::Mat Reye = cv::Mat::eye(3, 3, CV_64FC1);
cv::vconcat(principalPoints.reshape(2), randomPoints, points0);
/* Test with random D set */
for (size_t i = 0; i < 10; ++i) {
cv::Mat distortion(1, 4, CV_64F);
theRNG().fill(distortion, cv::RNG::UNIFORM, -0.001, 0.001);
cv::Mat Knew;
cv::fisheye::estimateNewCameraMatrixForUndistortRectify(K, distortion, imageSize, Reye, Knew);
/* Distort -> Undistort */
cv::Mat distortedPoints;
cv::fisheye::distortPoints(points0, distortedPoints, Knew, K, distortion);
cv::Mat undistortedPoints;
cv::fisheye::undistortPoints(distortedPoints, undistortedPoints, K, distortion, Reye, Knew);
EXPECT_MAT_NEAR(points0, undistortedPoints, 1e-8);
/* Undistort -> Distort */
cv::fisheye::undistortPoints(points0, undistortedPoints, K, distortion, Reye, Knew);
cv::fisheye::distortPoints(undistortedPoints, distortedPoints, Knew, K, distortion);
EXPECT_MAT_NEAR(points0, distortedPoints, 1e-8);
}
}
TEST_F(fisheyeTest, solvePnP)
{
const int n = 16;