OpenCV 不提供图像扭曲功能,但您可以自己实现。您只需要:
- 固有参数(相机矩阵和失真系数)和失真图像的大小。
表示为cam_mtx、dis_cef和image_size。
- 内在参数(相机矩阵)和未失真图像的大小。
表示为cam_mtx_ud 和image_size_ud。
- 失真和未失真图像之间的校正变换(旋转矩阵)。
记为R。
校正变换矩阵R可以通过stereoRectify()计算,但在单机系统中,它通常是恒等式(你可以使用空的Mat)。
回想一下当你对图像进行去扭曲时的过程,它需要两个步骤:
- 计算校正图:
initUndistortRectifyMap(cam_mtx, dis_cef, R, cam_mtx_ud, image_size_ud, CV_32FC1, map_x, map_y)
- 重新映射图像以不失真:
remap(image, image_ud, map_x, map_y, INTER_LINEAR);
校正图(map_x 和map_y)描述了从未失真图像到失真图像的像素坐标图。有了它们,未失真图像上的每个像素都可以在失真图像上找到它的位置,然后通过插值检索像素值。这就是remap 的工作原理。
因此,要生成不失真的校正图,您需要循环目标(不失真)图像的像素并失真点。
现在,对图像应用失真与不失真类似。
您需要通过循环目标(失真)图像的像素和不失真点来生成“失真贴图”。然后,使用remap 应用失真。
代码如下:
Mat map_x = Mat(image_size, CV_32FC1);
Mat map_y = Mat(image_size, CV_32FC1);
vector<Point2f> pts_ud, pts_distort;
for (int y = 0; y < image_size.height; ++y)
for (int x = 0; x < image_size.width; ++x)
pts_distort.emplace_back(x, y);
undistortPoints(pts_distort, pts_ud, cam_mtx, dis_cef, R, cam_mtx_ud);
for (int y = 0; y < image_size.height; ++y) {
float* ptr1 = map_x.ptr<float>(y);
float* ptr2 = map_y.ptr<float>(y);
for (int x = 0; x < image_size.width; ++x) {
const auto& pt = pts_ud[y * image_size.width + x];
ptr1[x] = pt.x;
ptr2[x] = pt.y;
}
}
Mat image_distort;
remap(image_ud, image_distort, map_x, map_y, INTER_LINEAR);
我不擅长python,所以我用C++编写了代码。很抱歉,但我认为代码不难阅读。