Understanding Unistort OpenCV Feature

I searched for an undistorted image using the distortion coefficients that I calculated for my camera, without changing the camera matrix. This is exactly what undistort() does, but I would like to draw a conclusion on a larger canvas image.

When I tried this:

 Mat drawtransform = getOptimalNewCameraMatrix(cameraMatrix, distCoeffs, size, 1.0, size * 2); undistort(inputimage, undistorted, cameraMatrix, distCoeffs, drawtransform); 

He still produced an image of the same size, but only the upper left quarter of the failed result. As in the documentation , an undistorted recording in the target image is the same size.

Obviously, I can simply copy and override a slightly modified version of undistort() , but I am having trouble understanding what it does. Here is the source:

 void cv::undistort( InputArray _src, OutputArray _dst, InputArray _cameraMatrix, InputArray _distCoeffs, InputArray _newCameraMatrix ) { Mat src = _src.getMat(), cameraMatrix = _cameraMatrix.getMat(); Mat distCoeffs = _distCoeffs.getMat(), newCameraMatrix = _newCameraMatrix.getMat(); _dst.create( src.size(), src.type() ); Mat dst = _dst.getMat(); CV_Assert( dst.data != src.data ); int stripe_size0 = std::min(std::max(1, (1 << 12) / std::max(src.cols, 1)), src.rows); Mat map1(stripe_size0, src.cols, CV_16SC2), map2(stripe_size0, src.cols, CV_16UC1); Mat_<double> A, Ar, I = Mat_<double>::eye(3,3); cameraMatrix.convertTo(A, CV_64F); if( distCoeffs.data ) distCoeffs = Mat_<double>(distCoeffs); else { distCoeffs.create(5, 1, CV_64F); distCoeffs = 0.; } if( newCameraMatrix.data ) newCameraMatrix.convertTo(Ar, CV_64F); else A.copyTo(Ar); double v0 = Ar(1, 2); for( int y = 0; y < src.rows; y += stripe_size0 ) { int stripe_size = std::min( stripe_size0, src.rows - y ); Ar(1, 2) = v0 - y; Mat map1_part = map1.rowRange(0, stripe_size), map2_part = map2.rowRange(0, stripe_size), dst_part = dst.rowRange(y, y + stripe_size); initUndistortRectifyMap( A, distCoeffs, I, Ar, Size(src.cols, stripe_size), map1_part.type(), map1_part, map2_part ); remap( src, dst_part, map1_part, map2_part, INTER_LINEAR, BORDER_CONSTANT ); } } 

About half of the lines here are designed to test the health and initialize the input parameters. What confuses me with what happens to map1 and map2 . These names, unfortunately, are less obvious than most. I must have missed some explanation, maybe this is hidden on some introduction page or under the document for another function.

map1 is a two-channel signed short integer matrix, and map2 is an unsigned short-chain matrix, dimension (height, max (4096 / width, 1)). The question is why? What will these cards contain? What is the meaning and purpose of this alternation? What is the meaning and purpose of the strange size of the stripes?

+6
source share
2 answers

Use initUndistortRectifyMap to get the conversion to the desired scale, then apply its output (the two matrices you mentioned) to remap .

The first map is used to calculate the transformation of the x coordinate at each pixel position, the second is used to convert the y coordinate.

+2
source

You might want to read the description of the remap function. The map represents the location of the X, Y pixel in the source image for each pixel of the target image. Map1_part is each location X in the source, and Map2_part is each location Y in the source.

Without going into it, alternation can be a method of speeding up the conversion process.

EDIT:

In addition, if you just want to scale your image to a larger size, you can simply resize the output image.

 double scaleX = 2.0; double scaleY = 2.0; cv::Mat undistortedScaled; cv::resize(undistorted, undistortedScaled, cv::Size(0,0), scaleX, scaleY); 
+2
source

Source: https://habr.com/ru/post/957797/


All Articles