【问题标题】:OpenCV-Python - How to format numpy arrays when using calibration functionsOpenCV-Python - 使用校准函数时如何格式化 numpy 数组
【发布时间】:2016-03-25 03:06:49
【问题描述】:

我正在尝试使用 OpenCV 3.0.0 python 绑定(使用非对称圆形网格)校准鱼眼相机,但我无法正确格式化对象和图像点数组。我当前的来源如下所示:

import cv2
import glob
import numpy as np


def main():
    circle_diameter = 4.5
    circle_radius = circle_diameter/2.0
    pattern_width = 4
    pattern_height = 11
    num_points = pattern_width*pattern_height

    images = glob.glob('*.bmp')
    criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)

    imgpoints = []
    objpoints = []
    obj = []

    for i in range(pattern_height):
        for j in range(pattern_width):
            obj.append((
                 float(2*j + i % 2)*circle_radius,
                 float(i*circle_radius),
                 0
            ))

    for name in images:
        image = cv2.imread(name)
        grayimage = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
        retval, centers = cv2.findCirclesGrid(grayimage, (pattern_width, pattern_height), flags=(cv2.CALIB_CB_ASYMMETRIC_GRID + cv2.CALIB_CB_CLUSTERING))

        imgpoints_tmp = np.zeros((num_points, 2))
        if retval:
            for i in range(num_points):
                imgpoints_tmp[i, 0] = centers[i, 0, 0]
                imgpoints_tmp[i, 1] = centers[i, 0, 1]

            imgpoints.append(imgpoints_tmp)
            objpoints.append(obj)


    # Convertion to numpy array
    imgpoints = np.array(imgpoints, dtype=np.float32)
    objpoints = np.array(objpoints, dtype=np.float32)

    K, D = cv2.fisheye.calibrate(objpoints, imgpoints, image_size=(1280, 800), K=None, D=None)

if __name__ == '__main__':
    main()

错误信息是:

OpenCV Error: Assertion failed (objectPoints.type() == CV_32FC3 || objectPoints.type() == CV_64FC3) in cv::fisheye::calibrate

objpoints 的形状为 (31,44,3)

所以objpoints 数组需要以不同的方式格式化,但我无法实现正确的布局。也许有人可以在这里提供帮助?

【问题讨论】:

标签: python opencv numpy opencv3.0 camera-calibration


【解决方案1】:

objpoints 的正确布局是一个带有 len(objpoints) = "number of pictures" 的 numpy 数组列表,每个条目都是一个 numpy 数组。

请查看the official help。 OpenCV 文档谈到了“向量”,它相当于一个列表或 numpy.array。在这种情况下,“向量的向量”可以解释为 numpy.arrays 的列表。

【讨论】:

  • 每个向量的长度是多少? 2 或 3 元素?
【解决方案2】:

在 OpenCV (Camera Calibration) 的示例中,他们将 objp 设置为 objp2 = np.zeros((8*9,3), np.float32)

但是,在全向相机或鱼眼相机中,它应该是: objp = np.zeros((1,8*9,3), np.float32)

想法来自这里Calibrate fisheye lens using OpenCV — part 1

【讨论】:

    【解决方案3】:

    数据类型正确,但形状不正确。 objpoints 的预期形状应该是 (n_observations, 1, n_corners_per_observation, 3)。因此,您的案例中的代码应该是:

    imgpoints = np.array(imgpoints, dtype=np.float32).reshape(
      -1, 
      1, 
      pattern_width * pattern_height, 
      3
    )
    

    或更笼统地说:

    imgpoints = np.array(imgpoints, dtype=np.float32).reshape(
      n_observations, 
      1, 
      n_corners_per_observation, 
      3
    )
    

    错误信息有点误导。

    【讨论】:

      【解决方案4】:

      在这里没有找到令人满意的答案,所以我搞砸了,最终让这个块工作:

      calibration_flags = cv2.fisheye.CALIB_RECOMPUTE_EXTRINSIC + cv2.fisheye.CALIB_CHECK_COND + cv2.fisheye.CALIB_FIX_SKEW
      
      # lists with each element a [1,n_points,_] array of type float32
      obj_points = [np.random.rand(1,10,3).astype(np.float32)]
      fisheye_points = [np.random.rand(1,10,2).astype(np.float32)]
      
      # initialize empty variables of correct size and type, where total_num_points is summed across all arrays in each above list
      rvecs = [np.zeros((1, 1, 3), dtype=np.float32) for i in range(total_num_points)]
      tvecs = [np.zeros((1, 1, 3), dtype=np.float32) for i in range(total_num_points)]
      D = np.zeros([4,1]).astype(np.float32)
      K = np.zeros([3,3]).astype(np.float32)
      
      outputs = cv2.fisheye.calibrate(gt_points,fisheye_points,(1920,1080),K,D,rvecs,tvecs)
      

      【讨论】:

        猜你喜欢
        • 2021-12-22
        • 2021-05-19
        • 2013-08-10
        • 2021-12-02
        • 2020-02-25
        • 2021-05-17
        • 2021-06-02
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多