w1nter
w1nter

Reputation: 367

python cv2.calibrateCamera throws error: objectPoints should contain vector of vectors of points of type Point3f

I have the code

img = cv2.imread("poolPictures\chessboard3.jpg", cv2.IMREAD_COLOR)
chessboardImage = cv2.imread("poolPictures\chessboardActual.jpg", cv2.IMREAD_COLOR)

ret, corners = cv2.findChessboardCorners(img, (9,6), None)
cv2.drawChessboardCorners(img, (9,6), corners, ret)

chessRet, chessCorners = cv2.findChessboardCorners(chessboardImage, (9,6), None)
ret, matrix, dist, rvecs, tvecs = cv2.calibrateCamera(corners, chessCorners, chessboardImage.shape[::-1][1:3], None, None)`

Running the code throws the error:

ret, matrix, dist, rvecs, tvecs = cv2.calibrateCamera(corners, chessCorners, chessboardImage.shape[::-1][1:3], None, None) cv2.error: C:\projects\opencv-python\opencv\modules\calib3d\src\calibration.cpp:3110: error: (-210) objectPoints should contain vector of vectors of points of type Point3f in function cv::collectCalibrationData

chessboard3.jpg:

chessboard3.jpg

chessboardActual.jpg:

chessboardActual.jpg

results of draw chessboard:

results of draw chessboard

I have tried converting the objectpoints to a 3 dimensional vector instead of 2 by by introducing a dummy 3rd dimension - I could not find the python version for Point3f().

I also saw from here https://github.com/opencv/opencv/issues/6002 that sometimes the error might be misleading, and that the real problem is that one of the vectors inside imagePoints is empty - I have tried printing the vectors and none are empty.

Hopefully someone can help, might just be a case of taking more pictures...

Cheers,

Upvotes: 6

Views: 12530

Answers (3)

Sunday
Sunday

Reputation: 811

OpenCV also requires floats to have single precision, as per this question.

This means every array needs to be converted to np.float32 before passing to calibrateCamera.

Upvotes: 5

w1nter
w1nter

Reputation: 367

As Zenith042 pointed out, I had image points and object points the wrong way round. However, the main issue was that instead of a numpy array for my image points like:

[[[ 137.5  205. ]]
[[ 143.5  206.5]]
 .
 .
 .
[[ 137.5  209.5]]]

I instead needed:

[[ 137.5 205. ]
[ 143.5 206.5]
.
.
.
[ 137.5 209.5]]]

Which I achieved with:

ret, corners = cv2.findChessboardCorners(img, (9,6), None)
corners = np.array([[corner for [corner] in corners]])

although I suspect there is a nicer way with numpy.reshape.

I also needed the same structure for the object points, i.e.

objp = np.array([objp])

Upvotes: 6

Zenith
Zenith

Reputation: 245

You can create dummy objPoints using

>>> objp = np.zeros((6*9, 3), np.float32)
>>> objp[:,:2] = np.mgrid[0:9, 0:6].T.reshape(-1,2)
>>> objp
array([[ 0.,  0.,  0.],
   [ 1.,  0.,  0.],
   [ 2.,  0.,  0.],
   [ 3.,  0.,  0.],
   [ 4.,  0.,  0.],
   [ 5.,  0.,  0.],
   [ 6.,  0.,  0.],
   [ 7.,  0.,  0.],
   [ 8.,  0.,  0.],
   [ 0.,  1.,  0.],
   [ 1.,  1.,  0.],
   [ 2.,  1.,  0.],
   [ 3.,  1.,  0.],
   [ 4.,  1.,  0.],
   [ 5.,  1.,  0.],
   [ 6.,  1.,  0.],
   [ 7.,  1.,  0.],
   [ 8.,  1.,  0.],
   [ 0.,  2.,  0.],
   [ 1.,  2.,  0.],
   [ 2.,  2.,  0.],
   [ 3.,  2.,  0.],
   [ 4.,  2.,  0.],
   [ 5.,  2.,  0.],
   [ 6.,  2.,  0.],
   [ 7.,  2.,  0.],
   [ 8.,  2.,  0.],
   [ 0.,  3.,  0.],
   [ 1.,  3.,  0.],
   [ 2.,  3.,  0.],
   [ 3.,  3.,  0.],
   [ 4.,  3.,  0.],
   [ 5.,  3.,  0.],
   [ 6.,  3.,  0.],
   [ 7.,  3.,  0.],
   [ 8.,  3.,  0.],
   [ 0.,  4.,  0.],
   [ 1.,  4.,  0.],
   [ 2.,  4.,  0.],
   [ 3.,  4.,  0.],
   [ 4.,  4.,  0.],
   [ 5.,  4.,  0.],
   [ 6.,  4.,  0.],
   [ 7.,  4.,  0.],
   [ 8.,  4.,  0.],
   [ 0.,  5.,  0.],
   [ 1.,  5.,  0.],
   [ 2.,  5.,  0.],
   [ 3.,  5.,  0.],
   [ 4.,  5.,  0.],
   [ 5.,  5.,  0.],
   [ 6.,  5.,  0.],
   [ 7.,  5.,  0.],
   [ 8.,  5.,  0.]], dtype=float32)

You can then call

ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objp, corners, img.shape[::-1],None,None)

You don't need to actually provide calibrateCamera with an 'actual' chessboard image.

Upvotes: 0

Related Questions