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?