Search code examples
pythonnumpyopencvcamera-calibrationaruco

Problem with type Point3f in function cv2.calibrateCamera PYTHON


Goodmorning everyone!

I am struggling with the opencv function calibrateCamera where I retrieve the following error:

OpenCV(4.5.4) D:\a\opencv-python\opencv-python\opencv\modules\calib3d\src\calibration.cpp:3350: error: (-210:Unsupported format or combination of formats) objectPoints should contain vector of vectors of points of type Point3f in function 'cv::collectCalibrationData'

I tried to find a solution, but could not find anything anywhere except for type issues or length issues. I use a np.array of float 32 type for both objPoints and imgPoints:


    objpoints = np.array(objpoints, dtype = np.float32)
    imgpoints = np.array(imgpoints, dtype = np.float32)
    ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, imsize, None, None )

The Variable Explorer gives the following values for the used variables:


    In: objpoints
    Out: 
    array([[  0. , 246.5,   0. ],
           [ 14.5, 246.5,   0. ],
           [ 43.5, 246.5,   0. ],
           ...,
           [174. ,   0. ,   0. ],
           [319. ,   0. ,   0. ],
           [333.5,   0. ,   0. ]], dtype=float32)
    
    In: imgpoints
    Out: 
    array([[1310., 1032.],
           [1258., 1032.],
           [1154., 1032.],
           [1206., 1032.],
           ...,
           [ 739.,  134.],
           [ 686.,  133.],
           [ 162.,  132.],
           [ 110.,  132.]], dtype=float32)
    
    In: imsize
    Out: (1080, 1440)
    
    In: len(imgpoints)
    Out: 440
    In: len(objpoints)
    Out: 440

I also tried switching objpoints and imgpoints in the calibrateCamera function, but that resulted in the same error message. As I read a lot of solutions for this function in C++ I want to point out that this is a Python related question.

I hope someone can help me with this! Thanks in advance!


Solution

  • This function can take multiple views (let's say N), each possibly showing a different object.

    "vector of vector of points" means each "vector of points" is allowed to have a different length, because maybe that object is different from the objects seen in other views.

    You can pass a single array with outer dimension (N, ...), if all your views show the same object (the arrays have the same length), but you should pass a list of arrays in the general case, so each array can have its own suitable size.

    objApoints = np.array(objApoints, dtype=np.float32)
    img1points = np.array(img1points, dtype=np.float32)
    
    # have another picture? img2points...
    # it may show the same object (objApoints) or a different object (objBpoints)
    
    objpointslist = [objApoints]
    imgpointslist = [img1points]
    
    cv2.calibrateCamera(objpointslist, imgpointslist, ...)