如何使用python中的opencv-fisheye模块在正常图像上应用鱼眼效果

pinkon5k  于 2023-10-24  发布在  Python
关注(0)|答案(1)|浏览(475)

我试图应用鱼眼效果对正常的图像使用opencv鱼眼模块。
要将鱼眼图像转换为正常图像,可以使用“cv2.fisheye.undistortimage”API。我不知道如何使用“cv2.fisheye.distortPoints”函数获得鱼眼图像。任何工作示例代码/算法都非常受欢迎。

mm9b1k5b

mm9b1k5b1#

使用cv2.fisheye.distortPoints(),我们可以从源图像的坐标中获得目标(失真)图像的坐标。
here和这里所述,“注意,该函数假设未失真点的相机矩阵是恒等的。这意味着如果你想用undistortPoints()变换回未失真的点,你必须将它们乘以P−1”。
函数cv2.fisheye.undistortPoints()接受 * 标准化 * 坐标作为输入,因此我们需要将原始索引乘以相机内部矩阵的逆,如下所示。
需要通过 * 摄像机标定 * 得到矩阵摄像机本征值K和畸变系数d
输入鹦鹉图像可以从here获得。

import matplotlib.pylab as plt
import cv2

K = np.array( [[338.37324094,0,319.5],[0,339.059099,239.5],[0,0,1]], dtype=np.float32)   # camera intrinsic parameters
d = np.array([0.17149, -0.27191, 0.25787, -0.08054], dtype=np.float32) # k1, k2, k3, k4 - distortion coefficients

def apply_fisheye_effect(img, K, d):

   indices = np.array(np.meshgrid(range(img.shape[0]), range(img.shape[1]))).T \
            .reshape(np.prod(img.shape[:2]), -1).astype(np.float32)

   Kinv = np.linalg.inv(K)
   indices1 = np.zeros_like(indices, dtype=np.float32)
   for i in range(len(indices)):
      x, y = indices[i]
      indices1[i] = (Kinv @ np.array([[x], [y], [1]])).squeeze()[:2]
   indices1 = indices1[np.newaxis, :, :]

   in_indices = cv2.fisheye.distortPoints(indices1, K, d)
   indices, in_indices = indices.squeeze(), in_indices.squeeze()

   distorted_img = np.zeros_like(img)
   for i in range(len(indices)):
      x, y = indices[i]
      ix, iy = in_indices[i]
      if (ix < img.shape[0]) and (iy < img.shape[1]):
         distorted_img[int(ix),int(iy)] = img[int(x),int(y)]

   return distorted_img

K = np.array( [[338.37324094,0,319.5],[0,339.059099,239.5],[0,0,1]],dtype=np.float32) # camera intrinsic params
d = np.array([0.17149, -0.27191, 0.25787, -0.08054],dtype=np.float32) # k1, k2, k3, k4 - distortion coefficients

img = plt.imread('parrot.jpg')
img = img / img.max()
distorted_img = apply_fisheye_effect(img, K, d)

plt.figure(figsize=(15,7))
plt.subplot(121), plt.imshow(img, aspect='auto'), plt.axis('off'), plt.title('original', size=20)
plt.subplot(122), plt.imshow(distorted_img, aspect='auto'), plt.axis('off'), plt.title('distorted', size=20)
plt.show()

请注意,通过对几个点(而不是所有点)进行采样并使用插值(例如scipy),可以使上述实现更快。

相关问题