4mla1fn
4mla1fn

Reputation: 303

how to call UndistortPoints

i have an (x,y) point, a 3x3 camera matrix, and 4 distortion coefficients and i want to get the undistorted point. my code looks like this...

double distorted_point_x = 10;
double_distorted_point_y = 20;

Emgu.CV.Matrix<double> distorted_point = new Emgu.CV.Matrix<double>(new double[,] {{distorted_point_x,distorted_point_y}});
Emgu.CV.Matrix<double> undistorted_point = new Emgu.CV.Matrix<double>(new double[,] {{-1,-1}}); // init to -1
Emgu.CV.Matrix<double> distortion_coefficients = new Matrix<double>(new double[] {0,0,0,0});
Emgu.CV.Matrix<double> camera_matrix = new Matrix<double>(new double[,] {{0,0,0},{0,0,0},{0,0,0}});

// copy the stuff; there's probably a more elegant way to copy but this works
for (int row = 0; row < 3; row++) {
    for (int col = 0; col < 3; col++) {
        camera_matrix[row, col] = my_calibrated_camera_matrix[row, col];  
    }
}

CvInvoke.UndistortPoints(distorted_point, undistorted_point, camera_matrix, distortion_coefficients);

undistorted_point_x = undistorted_point[0, 0];
undistorted_point_y = undistorted_point[0, 1];

when i run (VS2010), i get this exception dumped out to exception log file:

UnhandledException: OpenCV: CV_IS_MAT(_src) && CV_IS_MAT(_dst) &&
(_src->rows == 1 || _src->cols == 1) && (_dst->rows == 1 || _dst->cols
== 1) && _src->cols + _src->rows - 1 == _dst->rows + _dst->cols - 1 &&
(CV_MAT_TYPE(_src->type) == CV_32FC2 || CV_MAT_TYPE(_src->type) ==
CV_64FC2) && (CV_MAT_TYPE(_dst->type) == CV_32FC2 ||
CV_MAT_TYPE(_dst->type) == CV_64FC2)

i have the undistort.cpp from opencv and i know that this is coming from a CV_ASSERT in cvUndistortPoints(). i wonder if it's bombing on the CV_MAT_TYPE() tests where it looks like it's expecting the matrix to have 2 channels. (why would this be needed when the input is not image data?) if it does need to be 2-channel, how do i specify that in the Matrix?? i tried using Mat, but i don't know how to initialize the content of a Mat. i'd really appreciate any pointers. thanks.

Upvotes: 0

Views: 1249

Answers (2)

B.Blue
B.Blue

Reputation: 1

I also reach this problems, and I take some time to research an finally understand. You see the formula above, in the open system, distort operation is before camera matrix, so the process order is: image_distorted ->camera_matrix -> un-distort function->camera_matrix->back to image_undistorted.

So you need a small fix to and camera1 again.

Mat eye3 = Mat::eye(3, 3, CV_64F); 
cvUndistortPoints(src, dst, &camera1, &distCoeffs1, &eye3,&camera1);

Otherwise, if the last two parameters is empty, It would be project to a Normalized image coordinate.

See codes: opencv-3.4.0-src\modules\imgproc\src\undistort.cpp :297 cvUndistortPointsInternal() Formula

The formula

Upvotes: 0

Bartosz Rachwal
Bartosz Rachwal

Reputation: 306

cvUndistortPoints method on OpenCV side requires matrix type of CV_32FC2 or CV_64FC2

You can create it using matrix constructor with explicit channels number

var rows = 1;
var cols = 1;
var channels = 2;

var distorted_point = new Matrix<double>(rows, cols, channels)
{
    Data =
    {
        [0, 0] = distorted_point_x,
        [0, 1] = distorted_point_y
    }
};

var undistorted_point = new Matrix<double>(rows, cols, channels)
{
    Data =
    {
        [0, 0] = -1,
        [0, 1] = -1
    }
};

Or if you don't need double precision you can use

var distorted_point = new VectorOfPointF(new[] { new PointF(10, 20) });
var undistorted_point = new VectorOfPointF(new[] { new PointF(-1, -1) });

finally camera matrix should be

var camera_matrix = new Matrix<double>(3, 3);

Upvotes: 1

Related Questions