我正在寻找使用我为相机计算的失真系数来取消图像,而不更改相机矩阵。这正是undistort()
的作用,但我想将输出绘制为更大的画布图像。
当我尝试这个时:
Mat drawtransform = getOptimalNewCameraMatrix(cameraMatrix, distCoeffs, size, 1.0, size * 2);
undistort(inputimage, undistorted, cameraMatrix, distCoeffs, drawtransform);
它仍然写出了相同大小的图像,但只有左上角四分之一的按比例放大的未失真结果。 Like the documentation says,undistort写入相同大小的目标图像。
很明显,我可以复制并重新实现undistort()
稍微调整过的版本,但我在理解它在做什么时遇到了一些麻烦。这是来源:
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 );
}
}
此处大约一半的行用于检查和初始化输入参数。我感到困惑的是map1
和map2
发生了什么。这些名称遗憾的是描述性不如大多数。我必须错过一些解释,也许它隐藏在一些介绍页面中,或者在另一个功能的doc下。
map1
是双通道有符号短整数矩阵,map2
是无符号短整数矩阵,两者都是维度(高度,最大值(4096 /宽度,1))。问题是,为什么?这些地图包含什么?这种条纹的意义和目的是什么?条纹奇怪维度的意义和目的是什么?
答案 0 :(得分:2)
您可能想要阅读函数remap的说明。该映射表示目标图像中每个像素的源图像中的像素X,Y位置。 Map1_part是源中的每个X位置,Map2_part是源中的每个Y位置。
如果不仔细阅读,条带化可能是加速转型过程的一种方法。
编辑:
此外,如果您只想将图像缩放到更大的尺寸,您可以重新调整输出图像的大小。
double scaleX = 2.0;
double scaleY = 2.0;
cv::Mat undistortedScaled;
cv::resize(undistorted, undistortedScaled, cv::Size(0,0), scaleX, scaleY);
答案 1 :(得分:2)
使用initUndistortRectifyMap获得所需比例的转换,然后将其输出(您提到的两个矩阵)应用于remap。
第一张地图用于计算每个像素位置的x坐标变换,第二张用于变换y坐标。