我无法让charuco相机校准正常工作。据我所知,我做的一切正确,但是最终的未失真图像比预期的要扭曲得多。它确实适用于4x4电路板,但是校正后的面积太小,因此我需要使事情适用于7x7电路板。如果有人可以看到我在做什么,那么非常感谢您的帮助,此刻我有些困惑。所以是这种情况:
我设置了4个摄像头,每个摄像头都需要校准。
每个摄像机我都有11张charuco板7x7_1000的图片,因此总共有44张图片
这些是原始图像(适用于所有相机):
根据我在教程*中了解到的,并不是所有标记都必须是可见的,才能使charuco摄像机进行校准(这是charuco bord的全部思想)。据我所知,源图像很好。
我为每个摄像机检索图像集的标记和内插的棋盘角,并将其提供给v2.aruco.calibrateCameraCharuco函数。一切似乎都很好,因为这张只有一个标记的图像显示:
所以接下来我继续调用cv2.undistort函数,但是结果却不是我期望的:
这是我根据教程中的示例编写的代码:
def draw_charuco_board( filename, board, size=(2000, 2000) ):
imboard = board.draw(size)
cv2.imwrite(filename, imboard)
def detect_charuco_corners( full_board_image_gray, board ):
parameters = cv2.aruco.DetectorParameters_create()
return cv2.aruco.detectMarkers(full_board_image_gray, board.dictionary, parameters=parameters)
def charuco_camera_calib( board, filename_glob_pattern, do_flip=False, flip_axis=0 ):
"""
calibrates the camera using the charuco board
@see https://docs.opencv.org/trunk/d9/d6a/group__aruco.html#ga54cf81c2e39119a84101258338aa7383
@see https://github.com/opencv/opencv_contrib/blob/master/modules/aruco/samples/calibrate_camera_charuco.cpp
"""
charuco_corners = []
charuco_ids = []
calib_corners = []
calib_ids = []
fns = glob.glob(filename_glob_pattern)
size = None
for fn in fns:
image = cv2.imread(fn, flags=cv2.IMREAD_UNCHANGED)
image_size = tuple(image.shape[:2][::-1])
if size is None:
size = image_size
elif not image_size == size:
raise RuntimeError( "charuco_camera_calib:images are not the same size. previous: {} last: {}\n\tlast image: {}".format(size,image_size,fn))
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
if do_flip:
image = cv2.flip(image, flip_axis)
corners, ids, _ = detect_charuco_corners( image, board )
charuco_corners.append(np.array(corners))
charuco_ids.append(np.array(ids))
if len(corners):
# refine the detection
for i, corner in enumerate(corners):
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_COUNT, 30, 0.1)
cv2.cornerSubPix(image, corner,
winSize = (10,10),
zeroZone = (-1,-1),
criteria = criteria)
# interpolate to find all the chessboard corners
retval, chessboard_corners, chessboard_ids = cv2.aruco.interpolateCornersCharuco( corners, ids, image, board )
if chessboard_corners is not None and chessboard_ids is not None:
calib_corners.append(np.array(chessboard_corners))
calib_ids.append(np.array(chessboard_ids))
else:
raise RuntimeError( "charuco_camera_calib:could not get any markers from image: {}".format(fn))
retval, camera_matrix, dist_coeffs, rvecs, tvecs = cv2.aruco.calibrateCameraCharuco( np.array(calib_corners), np.array(calib_ids), board, size, None, None )
new_camera_matrix, roi = cv2.getOptimalNewCameraMatrix(
camera_matrix, dist_coeffs, size, 1, size
)
# map_x, map_y = cv2.initUndistortRectifyMap(
# camera_matrix, dist_coeffs, None, new_camera_matrix, size, cv2.CV_32FC1
# )
for i, fn in enumerate(fns):
image = cv2.imread(fn, flags=cv2.IMREAD_UNCHANGED)
image = cv2.aruco.drawDetectedMarkers(image, charuco_corners[i], charuco_ids[i])
image = cv2.drawChessboardCorners(image, (6,6), calib_corners[i], True)
image = cv2.undistort(image, camera_matrix, dist_coeffs)
# image = cv2.remap(image, map_x, map_y, cv2.INTER_LINEAR)
new_fn = fn.replace(".png", "_recified.png")
cv2.imwrite(new_fn, image)
return camera_matrix, dist_coeffs
董事会是使用创建
charuco_board = calibrate.create_charuco_board( dict_name=cv2.aruco.DICT_7X7_1000, squares_x=7, squares_y=7, square_length=40, marker_size=30 )
然后依次为每个摄像机的所有图像使用glob模式调用charuco_camera_calib,由于图像的方向正确,因此关闭了图像翻转。
正如我说的,我非常感谢您提供的任何帮助,因为我对这里出了问题不知所措,
乔纳森
*)tutorial_aruco_calibration
最佳答案
好吧,我终于解决了。问题是,如果我可能滥用该术语,则输入图像太“稀疏”。木炭板应覆盖相机的整个视野,而不仅仅是中央。将这些图像添加到混合中可以解决此问题。
关于opencv - opencv charuco相机校准无法正确失真,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/55689715/