@Steve_in_Denver
- Yes, i’ve checked the camera resolution is the same in the images used for calibration and detection
- ~20 calibration images
- The number of rowxcols as well as physical measurement of the grid & marker size compared to what I use in the code below are consistent
- Code and images are below
def calibrate_camera_intrinsic(image_filenames):
aruco_dict = cv2.aruco.getPredefinedDictionary(cv2.aruco.DICT_6X6_250)
grid_size = 0.123333
board = cv2.aruco.CharucoBoard((6, 4), grid_size, grid_size / 2.0,
aruco_dict)
allCorners = []
allIds = []
decimator = 0
# sub pixel corner improvement criteria
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 100, 0.00001)
for img_file in image_filenames:
print("=> Processing image {0}".format(img_file))
img_bgr = cv2.imread(img_file)
img_gray = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2GRAY)
corners, ids, rejectedImgPoints = aruco.detectMarkers(img_gray, aruco_dict)
if len(corners) > 0:
# SUB PIXEL DETECTION
for corner in corners:
cv2.cornerSubPix(img_gray, corner,
winSize=(3, 3),
zeroZone=(-1, -1),
criteria=criteria)
retVal, chCorners, chIds = cv2.aruco.interpolateCornersCharuco(corners, ids, img_gray, board)
if chCorners is not None and chIds is not None and len(chCorners) > 3 and decimator % 1 == 0:
allCorners.append(chCorners)
allIds.append(chIds)
decimator += 1
imsize = img_gray.shape
distCoeffsInit = np.zeros((8, 1))
cameraMatrixInit = np.array([[773.029, 0.0, 1.09045081e+03],
[0.0, 773.029 , 6.18946622e+02],
[0., 0., 1., ]])
flags = (cv2.CALIB_USE_INTRINSIC_GUESS + cv2.CALIB_RATIONAL_MODEL)
# flags = (cv2.CALIB_USE_INTRINSIC_GUESS + cv2.CALIB_FIX_FOCAL_LENGTH)
# flags = (cv2.CALIB_USE_INTRINSIC_GUESS + cv2.CALIB_FIX_K1 + cv2.CALIB_FIX_K2 + cv2.CALIB_FIX_K3 + cv2.CALIB_FIX_K4+ cv2.CALIB_FIX_K5 + cv2.CALIB_FIX_K6 + cv2.CALIB_FIX_S1_S2_S3_S4 + cv2.CALIB_FIX_TANGENT_DIST + cv2.CALIB_FIX_TAUX_TAUY )
# flags = cv2.CALIB_USE_INTRINSIC_GUESS
# flags = (cv2.CALIB_RATIONAL_MODEL)
(ret, camera_matrix, distortion_coefficients,
rotation_vectors, translation_vectors,
stdDeviationsIntrinsics, stdDeviationsExtrinsics,
perViewErrors) = cv2.aruco.calibrateCameraCharucoExtended(
charucoCorners=allCorners,
charucoIds=allIds,
board=board,
imageSize=imsize,
cameraMatrix=cameraMatrixInit,
distCoeffs=distCoeffsInit,
flags=flags,
criteria=(cv2.TERM_CRITERIA_EPS & cv2.TERM_CRITERIA_COUNT, 10000, 1e-9))
print('ret:', ret)
print('camera_matrix:', camera_matrix)
print('distortion_coefficients:', distortion_coefficients)
print('rotation_vectors:', rotation_vectors)
print('translation_vectors:', translation_vectors)
return True, camera_matrix, distortion_coefficients
def detect_calib_board(image_rgb,camera_matrix, dist_coeffs):
aruco_dict = cv2.aruco.getPredefinedDictionary(cv2.aruco.DICT_6X6_250)
grid_size = 0.123333
board = cv2.aruco.CharucoBoard((6, 4), grid_size, grid_size / 2.0,
aruco_dict)
output_img_rgb = image_rgb.copy()
image_gray = cv2.cvtColor(image_rgb, cv2.COLOR_RGB2GRAY)
corners, ids, rejected_img_points = aruco.detectMarkers(image_gray, aruco_dict)
if len(corners) != 0: # some markers were detected
output_img_rgb = aruco.drawDetectedMarkers(output_img_rgb, corners, ids)
ret_val, allCorners, allIds = cv2.aruco.interpolateCornersCharuco(corners, ids, image_gray, board)
output_img_rgb = cv2.aruco.drawDetectedCornersCharuco(output_img_rgb,allCorners, allIds)
board_rvec_rdg = np.zeros((1,3))
board_tvec = np.zeros((1,3))
ret_val, board_rvec_rdg, board_tvec = aruco.estimatePoseCharucoBoard(allCorners, allIds, board, camera_matrix,
dist_coeffs , board_rvec_rdg, board_tvec, useExtrinsicGuess=False)
if ret_val: # board's pose could be estimated
print('Board rvec: ')
print(board_rvec_rdg)
print('Board tvec: ')
print(board_tvec)
length_of_axis = 0.015
output_img_rgb = cv2.drawFrameAxes(output_img_rgb, camera_matrix, dist_coeffs, board_rvec_rdg, board_tvec,
length_of_axis)
plt.imshow(output_img_rgb)
plt.show()
return True, board_rvec_rdg, board_tvec, output_img_rgb
else:
print('Error: Could not identity the pose of the calibration board in the image!')
return False, None, None, output_img_rgb
else:
print('Error: Could not identity the calibration board in the image!')
return False, None, None, output_img_rgb
Result:
error: 0.29379795366788053
camera_matrix: [[1.97924630e+03 0.00000000e+00 1.12217025e+03]
[0.00000000e+00 1.97516547e+03 6.19508215e+02]
[0.00000000e+00 0.00000000e+00 1.00000000e+00]]
distortion_coefficients: [[-9.91883164e+00]
[-2.51426039e+01]
[-3.51000391e-04]
[ 6.58633780e-04]
[-7.93967022e+00]
[-9.84978313e+00]
[-2.69354144e+01]
[ 5.34058048e+00]
[ 0.00000000e+00]
[ 0.00000000e+00]
[ 0.00000000e+00]
[ 0.00000000e+00]
[ 0.00000000e+00]
[ 0.00000000e+00]]
Board detection:
(cropped image)
Board rvec:
[[-0.00455889]
[-0.00658869]
[ 1.56128103]]
Board tvec:
[[ 0.18143146]
[-0.32179749]
[ 1.41092617]]
Expected distance to board ~0.65m