Reputation: 367
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:
chessboardActual.jpg:
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
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
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
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