如何在摄像机拍摄坐标中取消失真并获得相应的未失真图像坐标?

ser*_*gtk 6 opencv computer-vision

在摄像机校准后,我使用OpenCV来解除一组点.代码如下.

const int npoints = 2; // number of point specified 

// Points initialization. 
// Only 2 ponts in this example, in real code they are read from file.
float input_points[npoints][2] = {{0,0}, {2560, 1920}}; 

CvMat * src = cvCreateMat(1, npoints, CV_32FC2);
CvMat * dst = cvCreateMat(1, npoints, CV_32FC2);

// fill src matrix
float * src_ptr = (float*)src->data.ptr;
for (int pi = 0; pi < npoints; ++pi) {
    for (int ci = 0; ci < 2; ++ci) {
        *(src_ptr + pi * 2 + ci) = input_points[pi][ci];
    }
}

cvUndistortPoints(src, dst, &camera1, &distCoeffs1);
Run Code Online (Sandbox Code Playgroud)

上面的代码dst包含以下数字后:

-8.82689655e-001 -7.05507338e-001 4.16228324e-001 3.04863811e-001
Run Code Online (Sandbox Code Playgroud)

与数字相比,它们太小了src.

同时,如果我通过电话取消图像:

cvUndistort2( srcImage, dstImage, &camera1, &dist_coeffs1 );
Run Code Online (Sandbox Code Playgroud)

我收到良好的无失真图像,这意味着与单独的点相比,像素坐标不会如此大幅度地修改.

如何获得与图像相同的特定点的不失真?谢谢.

ser*_*gtk 12

这些点应使用相机矩阵"非标准化".

更具体地说,cvUndistortPoints还应该在调用以下转换之后添加:

double fx = CV_MAT_ELEM(camera1, double, 0, 0);
double fy = CV_MAT_ELEM(camera1, double, 1, 1);
double cx = CV_MAT_ELEM(camera1, double, 0, 2);
double cy = CV_MAT_ELEM(camera1, double, 1, 2);

float * dst_ptr = (float*)dst->data.ptr;
for (int pi = 0; pi < npoints; ++pi) {
    float& px = *(dst_ptr + pi * 2);
    float& py = *(dst_ptr + pi * 2 + 1);
    // perform transformation. 
    // In fact this is equivalent to multiplication to camera matrix
    px = px * fx + cx;
    py = py * fy + cy;
}
Run Code Online (Sandbox Code Playgroud)

有关OpenCV "相机校准和3D重建"相机矩阵的更多信息

更新:

以下C++函数调用也应该工作:

std::vector<cv::Point2f> inputDistortedPoints = ...
std::vector<cv::Point2f> outputUndistortedPoints;
cv::Mat cameraMatrix = ...
cv::Mat distCoeffs = ...

cv::undistortPoints(inputDistortedPoints, outputUndistortedPoints, cameraMatrix, distCoeffs, cv::noArray(), cameraMatrix);
Run Code Online (Sandbox Code Playgroud)