1. 环境准备从零搭建标定工作流单目相机标定是计算机视觉项目的基础环节就像给尺子刻上刻度一样重要。我经历过无数次标定失败后发现环境配置是第一个拦路虎。这里推荐使用TartanCalib项目它集成了Kalibr环境用Docker容器封装了所有依赖项完美解决了在我机器上能跑的经典问题。首先需要准备Ubuntu 20.04系统这个版本对ROS和Docker的支持最稳定。安装Docker时有个小技巧记得把当前用户加入docker用户组否则每次都要sudo很麻烦。具体操作是执行sudo usermod -aG docker $USER然后重新登录生效。克隆TartanCalib项目的命令看似简单git clone https://github.com/castacks/tartancalib cd tartancalib docker build -t tartancalib -f Dockerfile_ros1_20_04 .但这里有个隐藏坑点国内用户可能会遇到网络问题导致构建失败。建议先配置Docker镜像加速器我在阿里云容器镜像服务申请的个人加速地址能显著提升拉取速度。容器运行时需要特别注意GUI显示配置FOLDER/path/to/your/data/on/host xhost local:root docker run -it -e DISPLAY -e QT_X11_NO_MITSHM1 \ -v /tmp/.X11-unix:/tmp/.X11-unix:rw \ -v $FOLDER:/data tartancalib这个命令里的xhost local:root容易被忽略但缺少它会导致图形界面无法显示。我曾在凌晨三点调试时卡在这个问题上后来发现是X11权限没配置好。2. 数据准备标定材料的科学制作标定板的选择就像选摄影道具——既要标准又要实用。Aprilgrid和棋盘格各有利弊Aprilgrid能提供更多特征点但打印精度要求高棋盘格更容易制作但角点检测可能不稳定。我建议新手先用棋盘格练手A4纸打印贴在硬纸板上就能用成本几乎为零。拍摄标定图片时有三个黄金法则标定板要占画面30%-70%面积需要覆盖画面各个区域中心、四角、边缘包含不同倾斜角度俯仰、偏转、旋转最近项目中发现个有趣现象用手机拍摄的标定图比工业相机效果更好。后来发现是因为手机自动优化了对比度而工业相机需要手动调整曝光。建议拍摄时关闭自动白平衡和HDR保持参数一致。图片命名必须采用19位数字格式如1653829476123456789.png这是Kalibr的硬性要求。我写了个简单的重命名脚本import os from datetime import datetime for i, filename in enumerate(os.listdir(.)): if filename.endswith(.jpg): ts int(datetime.now().timestamp())*1000 i os.rename(filename, f{ts}.jpg)打包bag文件时要注意时间同步问题rosrun kalibr kalibr_bagcreater --folder dataset-dir/ --output-bag awsome.bag如果遇到Timestamps not increasing错误可能是手机拍摄的EXIF时间戳有问题。可以用exiftool批量修改时间戳间隔建议保持在0.5-1秒。3. 参数配置模型选择的艺术标定板YAML文件就像菜谱中的配料表差之毫厘谬以千里。以6x7的棋盘格为例target_type: checkerboard targetCols: 6 # 注意是内角点数不是方格数 targetRows: 7 rowSpacingMeters: 0.06 # 实际测量打印的方格边长 colSpacingMeters: 0.06这里最容易出错的是targetCols和targetRows的理解——它们指的是内角点数量而非方格数量。上周指导实习生时就发现他把8x6的棋盘格误配为7x5参数导致标定完全失败。相机模型选择需要理解每个参数的含义pinhole-radtan普通相机标配适合大多数USB摄像头pinhole-equi鱼眼镜头优选大疆无人机常用omni-radtan全景相机专用如理光Theta有个简易判断方法用普通镜头拍A4纸如果边缘直线明显弯曲就用pinhole-equi轻微弯曲用pinhole-radtan严重变形考虑omni模型。去年给扫地机器人标定时就是通过这个方法发现其使用的是190°鱼眼镜头。4. 执行标定命令背后的秘密执行标定的核心命令看似简单rosrun kalibr kalibr_calibrate_cameras \ --target checkerboard.yaml \ --models pinhole-radtan \ --topics /cam0/image_raw \ --bag awsome.bag但实际运行时可能会遇到各种惊喜。最常见的是报错Not enough corners detected这通常意味着标定板未完全出现在画面中光照不均匀导致检测失败相机焦距未正确调整我开发了一套预处理检查脚本import cv2 import numpy as np def check_image(img_path): img cv2.imread(img_path) gray cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) ret, corners cv2.findChessboardCorners(gray, (6,7), None) if ret: cv2.drawChessboardCorners(img, (6,7), corners, ret) cv2.imshow(Corners, img) cv2.waitKey(500) return ret这个脚本能快速验证每张图片是否合格节省大量调试时间。标定结果主要关注两个文件results-cam.yaml包含内参矩阵和畸变系数report-cam.pdf可视化报告重投影误差应小于0.2像素有个经验公式当重投影误差大于0.5像素时应该检查数据质量大于1像素时建议重新标定。去年给工业检测相机标定时发现误差达到1.2像素后来发现是标定板打印尺寸存在0.5mm误差。5. 结果验证超越数字的评估拿到标定参数只是开始真正的考验在于实际验证。我习惯用下面这个Python脚本快速测试矫正效果import cv2 import yaml import numpy as np with open(results-cam.yaml) as f: data yaml.safe_load(f) K np.array(data[cam0][intrinsics]) D np.array(data[cam0][distortion_coeffs]) img cv2.imread(test.jpg) h, w img.shape[:2] new_K, roi cv2.getOptimalNewCameraMatrix(K, D, (w,h), 1) mapx, mapy cv2.initUndistortRectifyMap(K, D, None, new_K, (w,h), 5) dst cv2.remap(img, mapx, mapy, cv2.INTER_LINEAR)注意getOptimalNewCameraMatrix的alpha参数设为1会保留所有像素含黑边设为0会裁剪无效区域。产品级应用建议选0而算法开发阶段选1更方便。常见的标定问题有如边缘矫正不完全这可能是由于镜头边缘畸变过于复杂标定板未充分覆盖边缘区域选择了不匹配的畸变模型有个实用技巧用棋盘格视频流实时观察矫正效果。我在ROS中常用如下命令rosrun image_view image_view image:/camera/image_rect这比单张图片验证更直观能发现动态场景下的隐藏问题。6. 进阶技巧标定质量的提升之道高质量标定的秘诀在于细节把控。温度变化会导致镜头形变工业级应用建议在恒温环境下标定。我们实验室发现温度每变化10°C焦距会有0.3%左右的变化。多阶段标定法效果显著先用低分辨率快速标定获取初始参数用初始参数预矫正图像在高分辨率下进行精细标定标定板的平整度影响巨大。曾遇到0.2mm的弯曲导致标定误差增加40%现在都用亚克力板做底板。有个检测平整度的方法用激光笔照射标定板观察反射光点是否始终在同一位置。光照条件也需要标准化。建议使用5500K色温的均匀光源照度在500-1000lux之间。避免直射光造成的反光我常用偏振镜来消除金属标定板的镜面反射。最后提醒标定参数会随时间漂移。消费级相机建议每季度标定一次工业相机在重要任务前必须重新标定。建立标定日志非常必要记录每次标定的环境条件、参数版本和误差指标。
从零实践:基于TartanCalib与Kalibr的单目相机标定全流程解析
1. 环境准备从零搭建标定工作流单目相机标定是计算机视觉项目的基础环节就像给尺子刻上刻度一样重要。我经历过无数次标定失败后发现环境配置是第一个拦路虎。这里推荐使用TartanCalib项目它集成了Kalibr环境用Docker容器封装了所有依赖项完美解决了在我机器上能跑的经典问题。首先需要准备Ubuntu 20.04系统这个版本对ROS和Docker的支持最稳定。安装Docker时有个小技巧记得把当前用户加入docker用户组否则每次都要sudo很麻烦。具体操作是执行sudo usermod -aG docker $USER然后重新登录生效。克隆TartanCalib项目的命令看似简单git clone https://github.com/castacks/tartancalib cd tartancalib docker build -t tartancalib -f Dockerfile_ros1_20_04 .但这里有个隐藏坑点国内用户可能会遇到网络问题导致构建失败。建议先配置Docker镜像加速器我在阿里云容器镜像服务申请的个人加速地址能显著提升拉取速度。容器运行时需要特别注意GUI显示配置FOLDER/path/to/your/data/on/host xhost local:root docker run -it -e DISPLAY -e QT_X11_NO_MITSHM1 \ -v /tmp/.X11-unix:/tmp/.X11-unix:rw \ -v $FOLDER:/data tartancalib这个命令里的xhost local:root容易被忽略但缺少它会导致图形界面无法显示。我曾在凌晨三点调试时卡在这个问题上后来发现是X11权限没配置好。2. 数据准备标定材料的科学制作标定板的选择就像选摄影道具——既要标准又要实用。Aprilgrid和棋盘格各有利弊Aprilgrid能提供更多特征点但打印精度要求高棋盘格更容易制作但角点检测可能不稳定。我建议新手先用棋盘格练手A4纸打印贴在硬纸板上就能用成本几乎为零。拍摄标定图片时有三个黄金法则标定板要占画面30%-70%面积需要覆盖画面各个区域中心、四角、边缘包含不同倾斜角度俯仰、偏转、旋转最近项目中发现个有趣现象用手机拍摄的标定图比工业相机效果更好。后来发现是因为手机自动优化了对比度而工业相机需要手动调整曝光。建议拍摄时关闭自动白平衡和HDR保持参数一致。图片命名必须采用19位数字格式如1653829476123456789.png这是Kalibr的硬性要求。我写了个简单的重命名脚本import os from datetime import datetime for i, filename in enumerate(os.listdir(.)): if filename.endswith(.jpg): ts int(datetime.now().timestamp())*1000 i os.rename(filename, f{ts}.jpg)打包bag文件时要注意时间同步问题rosrun kalibr kalibr_bagcreater --folder dataset-dir/ --output-bag awsome.bag如果遇到Timestamps not increasing错误可能是手机拍摄的EXIF时间戳有问题。可以用exiftool批量修改时间戳间隔建议保持在0.5-1秒。3. 参数配置模型选择的艺术标定板YAML文件就像菜谱中的配料表差之毫厘谬以千里。以6x7的棋盘格为例target_type: checkerboard targetCols: 6 # 注意是内角点数不是方格数 targetRows: 7 rowSpacingMeters: 0.06 # 实际测量打印的方格边长 colSpacingMeters: 0.06这里最容易出错的是targetCols和targetRows的理解——它们指的是内角点数量而非方格数量。上周指导实习生时就发现他把8x6的棋盘格误配为7x5参数导致标定完全失败。相机模型选择需要理解每个参数的含义pinhole-radtan普通相机标配适合大多数USB摄像头pinhole-equi鱼眼镜头优选大疆无人机常用omni-radtan全景相机专用如理光Theta有个简易判断方法用普通镜头拍A4纸如果边缘直线明显弯曲就用pinhole-equi轻微弯曲用pinhole-radtan严重变形考虑omni模型。去年给扫地机器人标定时就是通过这个方法发现其使用的是190°鱼眼镜头。4. 执行标定命令背后的秘密执行标定的核心命令看似简单rosrun kalibr kalibr_calibrate_cameras \ --target checkerboard.yaml \ --models pinhole-radtan \ --topics /cam0/image_raw \ --bag awsome.bag但实际运行时可能会遇到各种惊喜。最常见的是报错Not enough corners detected这通常意味着标定板未完全出现在画面中光照不均匀导致检测失败相机焦距未正确调整我开发了一套预处理检查脚本import cv2 import numpy as np def check_image(img_path): img cv2.imread(img_path) gray cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) ret, corners cv2.findChessboardCorners(gray, (6,7), None) if ret: cv2.drawChessboardCorners(img, (6,7), corners, ret) cv2.imshow(Corners, img) cv2.waitKey(500) return ret这个脚本能快速验证每张图片是否合格节省大量调试时间。标定结果主要关注两个文件results-cam.yaml包含内参矩阵和畸变系数report-cam.pdf可视化报告重投影误差应小于0.2像素有个经验公式当重投影误差大于0.5像素时应该检查数据质量大于1像素时建议重新标定。去年给工业检测相机标定时发现误差达到1.2像素后来发现是标定板打印尺寸存在0.5mm误差。5. 结果验证超越数字的评估拿到标定参数只是开始真正的考验在于实际验证。我习惯用下面这个Python脚本快速测试矫正效果import cv2 import yaml import numpy as np with open(results-cam.yaml) as f: data yaml.safe_load(f) K np.array(data[cam0][intrinsics]) D np.array(data[cam0][distortion_coeffs]) img cv2.imread(test.jpg) h, w img.shape[:2] new_K, roi cv2.getOptimalNewCameraMatrix(K, D, (w,h), 1) mapx, mapy cv2.initUndistortRectifyMap(K, D, None, new_K, (w,h), 5) dst cv2.remap(img, mapx, mapy, cv2.INTER_LINEAR)注意getOptimalNewCameraMatrix的alpha参数设为1会保留所有像素含黑边设为0会裁剪无效区域。产品级应用建议选0而算法开发阶段选1更方便。常见的标定问题有如边缘矫正不完全这可能是由于镜头边缘畸变过于复杂标定板未充分覆盖边缘区域选择了不匹配的畸变模型有个实用技巧用棋盘格视频流实时观察矫正效果。我在ROS中常用如下命令rosrun image_view image_view image:/camera/image_rect这比单张图片验证更直观能发现动态场景下的隐藏问题。6. 进阶技巧标定质量的提升之道高质量标定的秘诀在于细节把控。温度变化会导致镜头形变工业级应用建议在恒温环境下标定。我们实验室发现温度每变化10°C焦距会有0.3%左右的变化。多阶段标定法效果显著先用低分辨率快速标定获取初始参数用初始参数预矫正图像在高分辨率下进行精细标定标定板的平整度影响巨大。曾遇到0.2mm的弯曲导致标定误差增加40%现在都用亚克力板做底板。有个检测平整度的方法用激光笔照射标定板观察反射光点是否始终在同一位置。光照条件也需要标准化。建议使用5500K色温的均匀光源照度在500-1000lux之间。避免直射光造成的反光我常用偏振镜来消除金属标定板的镜面反射。最后提醒标定参数会随时间漂移。消费级相机建议每季度标定一次工业相机在重要任务前必须重新标定。建立标定日志非常必要记录每次标定的环境条件、参数版本和误差指标。