如何使用 OpenCV 或任何其他库对图像应用变形?

问题描述 投票:0回答:2

我正在执行校准,如此处所示,但使用 cv.CALIB_RATIONAL_MODEL。

我使用了大约 40 张图像,我的平均重投影误差(由 cv2.calibrateCamera 计算)始终小于 0.5。

现在,我希望能够拍摄任何其他图像并应用我从校准中获得的失真。

我知道我可以使用校准期间保存的角点来计算和重新扭曲校准图像,但我想仅使用我可以保存和使用的内在和/或外在参数在完全不同的图像上应用扭曲。

可以吗?

我尝试将

np.negative(distortion)
传递给
cv.undistort()
希望它不会因负值而失真,因此它实际上会失真,但它不起作用并给了我完全混乱的结果。

我尝试将其他(onetwo Three)线程上的答案从c++翻译成Python,并通过研究失真背后的理论来创建我自己的函数,但它不起作用。

我可以利用其他库或理论来解决这个问题吗?

python computer-vision camera-calibration opencv
2个回答
3
投票

OpenCV不提供图像扭曲功能,但您可以自己实现一个。您所需要的只是:

  • 内在参数(相机矩阵和畸变系数)和畸变图像的大小。
    表示为
    cam_mtx
    dis_cef
    image_size
  • 内在参数(相机矩阵)和未失真图像的大小。
    表示为
    cam_mtx_ud
    image_size_ud
  • 扭曲和未扭曲图像之间的校正变换(旋转矩阵)。
    表示为
    R

校正变换矩阵

R
可以通过
stereoRectify()
计算,但在单相机系统中,它通常是恒等的(可以只使用空
Mat
)。


回想一下图像去畸变的过程,需要两个步骤:

  1. 计算校正图:
    initUndistortRectifyMap(cam_mtx, dis_cef, R, cam_mtx_ud, image_size_ud, CV_32FC1, map_x, map_y)
  2. 重新映射图像以消除扭曲:
    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++编写了代码。抱歉,但我认为代码并不难读。


0
投票

反转实值索引网格

© www.soinside.com 2019 - 2024. All rights reserved.