计算和使用 OpenCV 失真参数的倒数

问题描述

所以基本上我想找出我所做的校准的反转失真参数是什么,如here所示。

注意:我知道我们可以执行不失真,然后使用重新映射来执行我在下面所做的操作,但我的目标是能够找出实际的反转失真参数并使用它们来扭曲其他图像,不仅仅是能够恢复 cv2.undistort() 所做的


概述:

我试过传入对失真参数的否定:

# _,mat,distortion,_,_ = cv2.calibrateCamera(...)
# undistorted_image = cv2.undistort(with distortion) 
# redistorted_image = cv2.undistort(with np.negative(distortion))

理论上,我在想,如果 redistorted_image 与原始图像相似,那么 np.negative(distortion) 参数就是我要找的,但结果是错误的。


我使用的实际方法

def save_undistorted_images(image,matrix,distortion):
    test_image_su = cv.imread(image)
    height,width = test_image_su.shape[:2]
    new_camera_mtx,roi = cv.getoptimalNewCameraMatrix(matrix,(width,height),1,height))

    distortion_u = np.negative(distortion)

    # unsure if this line helps
    new_camera_mtx_inv,distortion_u,height))

    # undistort the image
    undistorted_image = cv.undistort(test_image_su,None,new_camera_mtx)
    cv.imwrite('undistorted_frame.png',undistorted_image)

    # redistort trying to get something like original image (image_test_su) 
    distorted_image = cv.undistort(undistorted_image,new_camera_mtx_inv)
    cv.imwrite('redistorted_frame.png',distorted_image)

结果:

(左a:原始)(右b:未失真)

enter image description here

enter image description here

(左 c:使用 np.negative(distortion) 失真)(右 d:未失真图像re使用 np.negative(distortion) 失真))

enter image description here

enter image description here

这里的图像 d 基本上是在 b 上执行的 c,我预计它会类似于 a

为什么 b 在这里压倒了 c效果


我尝试过的其他计算逆的方法

以下是我对这个 paper 的 python 实现

    distortion_u = distortion

    k1 = distortion_u[0][0]
    k2 = distortion_u[0][1]
    k3 = distortion_u[0][4]

    b1 = -1 * k1
    b2 = 3 * (k1 * k1) - k2
    b3 = (8 * k1 * k2) + (-1 * (12 * (k1 * k1 * k1))) - k3
    
    # radial:
    distortion_u[0][0] = b1
    distortion_u[0][1] = b2
    distortion_u[0][4] = b3
   
    # tangential: 
    #distortion_u[0][2] = -1 * distortion_u[0][2]
    #distortion_u[0][3] = -1 * distortion_u[0][3]

使用上述失真参数对未失真图像应用失真的结果也不好,看起来与上面的结果非常相似。


所以,这让我们:

为什么正常失真的影响总是压倒 np.negative(失真) 或其他任何东西?

所有失真都这样吗? (负值不等于反效果

如何得到实际相反的失真参数?

解决方法

怕你做错了。您校准的 opencv distortion model 会根据失真坐标计算未失真和归一化的图像坐标。它是一个非线性模型,因此对其求逆涉及求解非线性(多项式)方程组。

AFAIK 仅在单参数纯径向畸变的情况下存在封闭形式(参数)解,即当唯一的非零畸变参数为 k1 时,r^2 的系数。在这种情况下,模型反演方程简化为 r 中的三次方程,然后您可以使用卡尔达诺的三次求解公式来表达反演模型。

在所有其他情况下,可以使用各种算法来求解非线性方程组,以数值方式反转模型。 OpenCV 使用迭代的“假位置”方法。

由于您想使用逆模型对一组图像进行不失真(这是他的正常用例),因此您应该使用 initUndistortRectifyMap 一劳永逸地计算图像的不失真解决方案,并且然后将每个图像的它传递给 remap 以实际使图像不失真。

如果您真的需要一个用于逆模型的参数模型,我的建议是研究用一对高阶多项式逼近 initUndistortRectifyMap 返回的映射,或薄板样条。