[相机标定]RealSense D435i相机标定

本文介绍使用Kalibr工具进行D435i相机的内参标定及与IMU间的外参标定过程。包括录制数据集、配置参数、运行命令等关键步骤,并解决遇到的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

为了获得相机的内参,以及D435i各传感器坐标的外参,利用intel自带的Dynamic Calibrator进行标定。

Kalibr标定d435i内参、与IMU外参

1.标定内参

录制数据集:

rosrun topic_tools throttle messages /camera/color/image_raw 4.0 /color

利用throttle工具降低录制的RGB图像频率,降至4HZ,新发布的topic名字是/color

录制时需要准备标定板,这里建议TB直接买人家做好的,省去自己打印的不好。Kalibr支持tag和chessboard,博主这里借用了同学的棋盘格标定板,按照Kalibr的提示修改yaml文件,这里采用的标定板实际是9*12的,但是注意配置文件中是内角点:

target_type: 'checkerboard' #gridtype
targetCols: 8               #number of internal chessboard corners
targetRows: 11               #number of internal chessboard corners
rowSpacingMeters: 0.025      #size of one chessboard square [m]
colSpacingMeters: 0.025      #size of one chessboard square [m]

录制好数据集就可以开始进行标定了:

kalibr_calibrate_cameras --target ~/dev/kalibr_ws/src/kalibr/data/checkerboard.yaml --bag ~/dev/kalibr_ws/src/kalibr/data/kalibr_color.bag --models pinhole-equi --topics /color

这是官网的例子,修改为自己的具体对应的文件就行,我这里是直接输入的绝对路径。

*问题:

这里运行时卡在提取角点上 

然后在github的issue里到了答案:

在上述命令后加入--show-extraction

这样就能够运行了,参考链接

2.标定与IMU的外参

同样录制数据集,降低图像数据到20HZ,IMU数据至200HZ。

这里需要不同的配置文件,camchain.yaml和imu.yaml

camchain.yaml:

cam0:
  camera_model: pinhole
  intrinsics: [632.9640658678117, 638.2668942402212, 339.9807921782614, 243.68020465500277]
  distortion_model: equidistant
  distortion_coeffs: [0.366041713382057, 1.1433178097591097, -3.008125411486294, -3.1186836086733227]
  T_cam_imu:
  - [0.01779318, 0.99967549,-0.01822936, 0.07008565]
  - [-0.9998017, 0.01795239, 0.00860714,-0.01771023]
  - [0.00893160, 0.01807260, 0.99979678, 0.00399246]
  - [0.0, 0.0, 0.0, 1.0]
  timeshift_cam_imu: -8.121e-05
  rostopic: /color
  resolution: [640, 480]

imu.yaml:

rostopic: /imu
update_rate: 200.0 #Hz

accelerometer_noise_density: 0.01 #continous
accelerometer_random_walk: 0.0002 
gyroscope_noise_density: 0.005 #continous
gyroscope_random_walk: 4.0e-06


这里我用得到的相机内参替换了官方模板程序里面的数值,但是T_cam_imu和time_shift_imu并未修改,这里博主也不是很清楚。

然后运行:

kalibr_calibrate_imu_camera --target ~/dev/kalibr_ws/src/kalibr/data/checkerboard.yaml --cam ~/dev/kalibr_ws/src/kalibr/data/camchain.yaml --imu ~/dev/kalibr_ws/src/kalibr/data/imu.yaml --bag ~/dev/kalibr_ws/src/kalibr/data/color_imu.bag --bag-from-to 5 45 --show-extraction

这样就能够运行了。上述命令的5 45指的是采用的数据集的范围。


D435i的IMU的标定(用RealSense官方的)

参考文献:官网链接

首先到github上安装librealsense,本人直接下载了压缩包,然后解压缩后,在librealsense文件夹中新建了一个build文件夹,然后进入build文件夹,打开命令行,运行:

cmake ..

然后如果网络情况不好的话,会报错:

报的错是librealsense/third-party/libtm/resources/CMakeLists.txt中的第98行报错,可以将92行到94行注释掉。

然后:

make

sudo make install

然后按照pdf的教程安装各种python的东西,最后在tools/rs-imu-calibration中运行

python rs-imu-calibration.py

按照PDF的提示,一步步操作,最后输入footer按enter就能看到最后标定的结果,选择是否将结果写入到相机的eeprom中。


 

### 使用张正友标定法对Intel RealSense D435i相机进行标定 #### 准备工作 为了使用张正友标定法对标定RealSense D435i相机,需准备如下材料: - **棋盘格图案**:用于拍摄多角度图像以供后续处理。建议打印高对比度、无反光材质的A4纸大小棋盘格模板。 - **安装依赖库**:确保计算机上已经安装OpenCV以及Pyrealsense2 Python包以便于读取摄像头数据流并执行角点检测算法[^1]。 ```bash pip install pyrealsense2 opencv-python-headless numpy ``` #### 数据采集过程 启动Python脚本连接到D435i设备获取彩色帧序列,并保存含有清晰可见完整棋盘格子区域的画面文件集合。期间应变换不同视角位置重复此操作多次来增加样本多样性从而提高最终精度。 ```python import cv2 import numpy as np import pyrealsense2 as rs def capture_images(num_imgs=20, save_dir="./calib_images/"): pipeline = rs.pipeline() config = rs.config() # Configure depth and color streams... config.enable_stream(rs.stream.color) profile = pipeline.start(config) try: for i in range(1, num_imgs + 1): frames = pipeline.wait_for_frames() color_frame = frames.get_color_frame() img_name = f"{save_dir}img_{str(i).zfill(2)}.png" cv2.imwrite(img_name, np.asanyarray(color_frame.get_data())) print(f"Captured {img_name}") finally: pipeline.stop() if __name__ == "__main__": import os if not os.path.exists("./calib_images/"): os.makedirs("./calib_images/") capture_images() ``` #### 执行内估计程序 编写另一段代码片段加载先前存储下来的图片集合作为目标函数输入数;调用`cv::findChessboardCorners()`定位黑白相间方块交界处坐标点位信息;最后通过最小化重投影误差完成单目标镜头内部几何特性数值计算任务。 ```python import glob from typing import List criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001) def calibrate_camera(image_paths: List[str], board_size=(9, 6)): objp = np.zeros((np.prod(board_size), 3), dtype=np.float32) objp[:, :2] = np.mgrid[0:board_size[0], 0:board_size[1]].T.reshape(-1, 2) object_points = [] # type: ignore image_points = [] images = sorted(glob.glob(image_paths)) gray_shape = None for fname in images: img = cv2.imread(fname) gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) ret, corners = cv2.findChessboardCorners(gray, board_size, flags=cv2.CALIB_CB_ADAPTIVE_THRESH + cv2.CALIB_CB_FAST_CHECK + cv2.CALIB_CB_NORMALIZE_IMAGE) if ret is True: object_points.append(objp) refined_corners = cv2.cornerSubPix( gray, corners, (11, 11), (-1, -1), criteria) image_points.append(refined_corners) drawn_img = cv2.drawChessboardCorners( img.copy(), board_size, refined_corners, ret) cv2.imshow('Detected Corners', drawn_img) k = cv2.waitKey(500) if gray_shape is None: gray_shape = gray.shape[::-1] cv2.destroyAllWindows() _, camera_matrix, dist_coeffs, rvecs, tvecs = \ cv2.calibrateCamera(object_points, image_points, gray_shape, None, None) return { 'cameraMatrix': camera_matrix.tolist(), 'distCoeffs': dist_coeffs.flatten().tolist(), 'rVecs': [vec.tolist() for vec in rvecs], 'tVecs': [vec.tolist() for vec in tvecs] } if __name__ == '__main__': result = calibrate_camera('./calib_images/*.png') with open('intrinsics.json', 'w') as fp: json.dump(result, fp, indent=4) ``` 上述代码实现了基于张正友方法的相机数求解逻辑框架结构设计思路说明。
评论 40
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值