OpenCV stereoCalibrateExtended报错:非平面标定板需指定初始内参
问题分析:OpenCV stereoCalibrateExtended 报错 "For non-planar calibration rigs the initial intrinsic matrix must be specified"
错误信息
cv2.error: OpenCV(4.10.0) /io/opencv/modules/calib3d/src/calibration.cpp:1682: error: (-5:Bad argument) For non-planar calibration rigs the initial intrinsic matrix must be specified in function 'cvCalibrateCamera2Internal'
用户代码
def stereo_calibrate(img, correspondences_left, correspondences_right, camera_matrix_L, camera_matrix_R, baseline=4.1, dist_coeffs=None): if dist_coeffs is None: dist_coeffs = np.zeros((4, 1)) # Extract image points and object points from correspondences image_points_left = correspondences_left[:, :2].astype(np.float32) image_points_right = correspondences_right[:, :2].astype(np.float32) object_points = correspondences_left[:, 2:].astype(np.float32) # Assuming object points are the same for both sets rvec_L, tvec_L = np.array([0., 0., 0.]), np.array([0, 0., 0.]) rvec_R, tvec_R = np.array([-0.00637872, 0.00102092, 0.000673804]), np.array([0., 0., 0.]) # Convert rotation vectors to rotation matrices R_L, _ = cv2.Rodrigues(rvec_L) R_R, _ = cv2.Rodrigues(rvec_R) print("after converting via Rodrigues:", R_L, R_R) # Initialize rotation and translation vectors R_init = R_R @ R_L.T # T_init = tvec_R - R_init @ tvec_L T_init = np.array([0., 0., 0.]) print("R_init", R_init) print("T_init", T_init) # Stereo calibration to refine the extrinsic parameters ret, cameraMatrix1, distCoeffs1, cameraMatrix2, distCoeffs2, R, T, E, F, perViewErrors, _, _= cv2.stereoCalibrateExtended( [object_points], [image_points_left], [image_points_right], camera_matrix_L, dist_coeffs, camera_matrix_R, dist_coeffs, imageSize=(img.shape[1], img.shape[0]), # Correct image size as (width, height) R=R_init, T=T_init, criteria=(cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 100, 1e-6), flags=cv2.CALIB_USE_EXTRINSIC_GUESS ) print("ret", ret) if ret: print("Stereo Calibration Successful") print("Rotation Matrix between the cameras:") print(R) print("Translation Vector between the cameras:") print(T) print("dist_coeffs1", distCoeffs1) print("dist_coeffs2", distCoeffs2) print(rvec_L) print(tvec_L) else: raise ValueError("stereoCalibrate failed to find a solution") # Reproject object points to both cameras reprojected_points_left, _ = cv2.projectPoints(object_points, rvec_L, tvec_L, camera_matrix_L, distCoeffs1) reprojected_points_right, _ = cv2.projectPoints(object_points, R, T, camera_matrix_R, distCoeffs2) return R, T, reprojected_points_left, reprojected_points_right correspondences_left = np.array([ [671.0889955686854, 193.80354505169868, 2.4492935982947064e-16, -4.0, 11], ... ]) correspondences_right = np.array([ [436.2245592329106, 193.79399938137954, 2.4492935982947064e-16, -4.0, 11], ... ]) # Camera intrinsic parameters, replace with your actual camera matrix camera_matrix_L = np.array([ [1018.9, 0, 601.447], [0, 1018.9, 517.462], [0, 0, 1] ], dtype=np.float32) camera_matrix_R = np.array([ [1018.9, 0, 690.392], [0, 1018.9, 517.462], [0, 0, 1] ], dtype=np.float32) # calling the function R, T, reprojected_points_left, reprojected_points_right = stereo_calibrate(img_left, correspondences_left, correspondences_right, camera_matrix_L, camera_matrix_R)
问题原因
- flags参数未锁定内参:当前仅设置了
CALIB_USE_EXTRINSIC_GUESS,允许OpenCV优化内参。但你的标定靶标是非平面的(物体点z坐标有变化),OpenCV在优化非平面靶标的标定时,需要明确的初始内参且不允许重新初始化,否则会触发该错误。 - 物体点仅单帧数据:
stereoCalibrateExtended需要多帧不同姿态的标定数据提供足够约束,单帧非平面点无法满足标定的自由度要求,也会导致内参初始化逻辑异常。 - 畸变系数共用变量:左右相机使用同一个
dist_coeffs变量,可能导致OpenCV在优化时出现参数冲突,间接影响内参的初始化判断。
解决方案
- 修改flags参数,锁定内参:添加
CALIB_FIX_INTRINSIC,强制OpenCV使用你传入的初始内参,不进行优化:flags=cv2.CALIB_USE_EXTRINSIC_GUESS + cv2.CALIB_FIX_INTRINSIC - 补充多帧标定数据:确保
objectPoints、imagePoints1、imagePoints2是包含多帧数据的列表,例如:
然后将这三个列表传入# 示例:假设有3帧数据 object_points_list = [object_points_frame1, object_points_frame2, object_points_frame3] image_points_left_list = [img_points_left1, img_points_left2, img_points_left3] image_points_right_list = [img_points_right1, img_points_right2, img_points_right3]stereoCalibrateExtended。 - 单独初始化左右相机畸变系数:避免共用变量,分别初始化:
并在函数调用时传入这两个变量:dist_coeffs_L = np.zeros((4, 1), dtype=np.float32) dist_coeffs_R = np.zeros((4, 1), dtype=np.float32)ret, cameraMatrix1, distCoeffs1, cameraMatrix2, distCoeffs2, R, T, E, F, perViewErrors, _, _= cv2.stereoCalibrateExtended( [object_points], [image_points_left], [image_points_right], camera_matrix_L, dist_coeffs_L, camera_matrix_R, dist_coeffs_R, # 其他参数不变 )
内容的提问来源于stack exchange,提问作者Yajax
相关产品推荐
相关产品推荐

