十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Kalibr多标定板标定:原图复制遮挡方案解决相机内参标定难题

Kalibr多标定板标定:原图复制遮挡方案解决相机内参标定难题 1. 项目背景与问题本质1.1 多标定板场景从哪来做视觉SLAM、相机标定、多相机系统的人大概率都碰到过这个场景为了提升标定效率想一次性把多个角度的标定板摆进画面里一张图里放两三块板子已经够头疼了我这次直接遇到一张图里有9块标定板的极端情况。这个需求在实际项目中并不少见。产线标定、机器人外参快速装配、多相机阵列标定这些场景下每块板子代表一个不同的空间位置和角度约束理论上板子越多一次采集能覆盖的视野范围越广标定结果越稳定。但是Kalibr这个工具天生是单板起家的它的检测器、初始化流程、优化策略全部围绕“画面里只有一块完整棋盘格”来设计。一旦画面里出现9块板子Kalibr的角点检测器会把所有能检测到的棋盘格角点全部塞进同一个集合里然后去做全局位姿初始化。结果就是初始化阶段直接崩溃或者更糟——不崩溃但是优化出来的内参明显不对重投影误差大得离谱。我之前试过直接把这种多板图喂给Kalibr现象很有意思有时候它会报“initialization failed”有时候它不报错标定完成后看一眼重投影误差发现误差集中在某些区域raw图像上的角点对得歪七扭八。这种“能跑完但结果错误”的情况比直接报错还坑人因为流程上完全走通了不仔细看结果根本发现不了问题。1.2 为什么不能直接改Kalibr源码第一时间想到改源码是正常的。Kalibr的代码在GitHub上开源理论上你可以改它的检测器让它只对某个区域内的棋盘格做检测然后分别处理9块板子的位姿。听起来逻辑不复杂但真动手改会发现坑很多。首先是Kalibr的代码结构问题。它的棋盘格检测用的是OpenCV的findChessboardCorners这个函数一旦发现画面里有多个连通域都能组成棋盘格返回的角点顺序会非常混乱。你需要在代码里人为分割检测区域然后对每个区域单独跑检测再按照某种策略决定每个棋盘格的坐标系原点。其次是Kalibr的标定优化器是全局优化的它把所有检测到的角点统一建模成同一个棋盘格平面上的点。你就算把9块板子的角点分别检出来优化器还是会认为它们都在同一个平面上这时候你必须改优化器的cost function让它知道这里有9个独立的平面。这个改动涉及Kalibr的核心里程碑模块不是改几行代码就能搞定的。再一个问题是Kalibr的版本更新频率不算高自己改了源码之后后续想升级、想维护、想给别人复现都成了麻烦。很多做工程的人不愿意动源码不是因为不会改而是因为改了之后整个环境就“脏”了出了问题排查的边界变得模糊。所以我的思路很明确不改Kalibr而是从数据层面想办法。让Kalibr以为画面里只有一块板子但实际上我们只改了图像数据没有改任何算法逻辑。这样Kalibr的检测器、初始化、优化器全部走原版流程标定结果更可信。1.3 原图复制方案的核心逻辑原图复制方案说白了就是一句话把一张9块板子的大图复制成9张小图每张小图只保留一块板子其他8块板子全部用遮挡抹掉然后分别让Kalibr处理这9张小图。这里有个关键点复制的是原始图像数据不是重新渲染的合成图。也就是说每张小图的像素值、畸变特性、曝光特性完全继承自原始图像只不过把无关区域用固定颜色遮住了。这样做的好处是标定所需的畸变信息、相机响应特性全部保留我们只是“欺骗”了Kalibr的检测器让它以为视野里只有一块板子。有朋友会问那为什么不直接用图像裁剪把9块板子分别裁剪成9块独立的小图喂给Kalibr不行吗这个问题问到了点子上。裁剪确实更简单但有个致命问题相机内参标定对图像尺寸极其敏感。你裁剪之后图像的宽高变了光学中心cx, cy对应的像素位置也会变Kalibr算出来的内参就不是针对原始分辨率的内参了。除非你标完之后再做坐标换算否则直接用裁剪图标出来的内参会有系统性偏差。原图复制的妙处就在这里图像的宽高尺寸不变还是原始分辨率Kalibr计算出来的fx、fy、cx、cy全部是针对原始分辨率的拿着就能直接用。我们只遮挡了检测区域没有改变图像本身的几何结构。数据层面上Kalibr的检测器在单张图上找到了角点之后它需要至少3到4个不同位姿的图来初始化内参。也就是说你需要让每块板子在不同角度的原始图中出现每张图单独处理后Kalibr才能对同一块板子做多视角约束。2. 方案思路详解2.1 遮挡方案的技术选型遮挡方案有几种实现路径我踩过一些坑之后整理出三种主流做法。第一种是OpenCV手动画mask。用cv2.rectangle或者cv2.fillPoly在图像上绘制矩形/多边形区域把不需要的板子区域填充成固定颜色通常用黑色、白色或者纯灰色都可以我建议灰色因为太亮或太暗可能影响图像的直方图统计类算法虽然Kalibr不太依赖这个。第二种是使用图像编辑软件手动处理。Photoshop、GIMP、甚至画图工具都可以适合板子数量少、只需要一次性处理的场景。缺点是如果后续需要调整遮挡区域或者做批量处理手动方式就显得极度低效。第三种是程序化批量处理这也是我最终采用的方式。借助Python OpenCV写一个自动化脚本先标出每块板子的像素区域然后统一生成9张遮挡图。这样做的好处是9块板子的区域可以一遍跑完而且后续如果换了新数据只要改一下标记信息就能重新生成。我推荐第三种方案。原因很简单在真实项目中你不会只拍一张图而是要拍摄几十到上百帧的多板画面再从中挑选出质量好的帧进行标定。每一帧都要生成9张遮挡图如果没有自动化脚本每个数据处理流程都会变成灾难。2.2 区域标定与掩膜生成策略区域标定的关键是如何精确框出每块板子的边界。我用的是比较朴素的方法先跑一遍Kalibr自带的图像查看器把画面放大肉眼观察每块板子的四个角点。这里有一个细节需要注意棋盘格的角点区域和图像上的棋盘格区域不完全等价。Kalibr检测棋盘格时需要角点周围有足够的对比度上下文所以遮挡区域要比棋盘格本身稍微大一圈留出背景padding。或者反过来遮挡区域不能切到棋盘格的边界上否则检测器会认为棋盘格被截断了。我的经验值是遮挡区域不要紧贴棋盘格边界留出至少20到30像素的padding。这样Kalibr在检测角点时角点邻域内的信息完整不会因为遮挡边界而产生误检。具体的掩膜生成策略是这样的对每一帧图像在内存中创建一张全图mask初始值设为白色255然后把不需要的8块板子区域填充为黑色0最后用cv2.bitwise_and把原图和mask做与运算得出遮挡后的图像。如果希望减少计算量也可以直接在渲染图像时指定背景色但用位运算的方式更直观。还有一个非常实用的技巧mask的颜色不要用纯白或者纯黑用中性灰色比如128更稳妥。因为如果某些算法对亮度敏感纯白会在棋盘格周围产生光晕状干扰纯黑虽然影响不大但视觉上容易误导人判断遮挡区域覆盖是否正确。灰色无论是视觉检查还是算法处理都更加友好。2.3 为什么原图复制能骗过Kalibr的初始化Kalibr的标定初始化流程是这样的先对每一帧图像检测棋盘格角点然后根据这些角点的像素坐标计算出相机到棋盘格平面的初始位姿接着用多个视角的位姿估计出内参矩阵的初值最后进入非线性优化阶段。关键点在于“根据角点的像素坐标计算出相机到棋盘格平面的初始位姿”这一步。Kalibr假设所有角点来自同一个平面上的棋盘格然后通过PnP求解相机位姿。如果画面有9块板子Kalibr会把18组角点9块板子×2组相邻角点全部混在一起认为它们在同一个平面上PnP的输入就是一堆来自不同平面、不同位置的3D点解出来的位姿自然是一团糟。原图复制方案把这个问题从根源上消掉了9张图中每一张里只有一个平面上的棋盘格Kalibr用标准的单棋盘格PnP流程初始化出的相机位姿是合理的。9张图跑完之后Kalibr拿到了9个不同位姿对同一张图像平面的约束优化器迭代出一个平均意义下的内参解。所以这个方案不是“骗”Kalibr而是把Kalibr原本假设的前提条件还原了——每帧只处理一个棋盘格。我们做的只是数据预处理算法本身完全没动。2.4 方案优势与局限性复盘方案的优势写得很清楚不用改源码、不用重新编译、标定结果直接可用、兼容Kalibr全家桶。但也有几个局限性我必须说清楚。第一遮挡区域会损失一部分视野。因为遮挡用的是灰色填充Kalibr不会在这些区域检测到任何有用的特征点所以如果你原始图中的9块板子分布特别密集遮挡后保留的板子区域可能不足以覆盖整个画面某些区域的畸变信息会缺失。这个问题可以通过采集时让板子分布更分散、或者增加不同姿态的采集帧数来缓解。第二标定速度没有提升。虽然一张图9块板子看起来是并行处理的但实际标定时Kalibr是逐帧独立运行的9张图还是要跑9次完整的标定流程。相比改源码实现一次性处理原图复制方案在速度上没有优势它的价值在于“不做高风险改动就能得到正确结果”。第三处理过程需要人工参与标记板子区域。如果你每次采集的布局都不同每次都要重新标标记点不过这个一次性劳动可以接受。3. 实操过程与核心环节实现3.1 环境准备与数据采集要求我这次实验用的是Kalibr官方的Docker镜像版本主机的操作系统是Ubuntu 20.04Docker版本是20.10图像数据来自一台普通USB工业相机分辨率1280×1024标定板用的是Kalibr推荐的棋盘格checkerboard而不是Aprilgrid。关于标定板选择多说两句Kalibr官方推荐Aprilgrid因为Aprilgrid有非对称编码可以解决棋盘格的方向模糊问题。但在多板场景下棋盘格的优势更大——棋盘格的检测不需要识别每个格子的编码只要角点分布符合规则就能被检测出来这在遮挡处理后更容易存活。我用的是棋盘格如果你手头只有Aprilgrid也可以尝试但要注意Aprilgrid的遮挡边界检测更容易失败。数据采集的核心原则是覆盖多个角度和距离。9块板子虽然同时出现在画面里但它们各自的平面朝向不同不要全程保持板子静止要让整个标定板阵列在相机前做前、后、左、右、上、下六个方向的运动这样每块板子的棋盘格平面都能经历足够多的相机位姿变化。我采集了30帧图像覆盖了大约10种不同的距离和角度组合其中有15帧用于标定剩下15帧用于佐证和测试。注意Kalibr处理的数据格式是rosbag不是裸图像。你需要先把图像序列打包成rosbag然后确保bag里也有对应的image topic。这里有一个特别容易踩的坑——bag里的时间戳必须单调递增且连续如果时间戳出现跳变或重复Kalibr的帧同步机制会崩溃。3.2 图像预处理与遮挡图生成代码解析直接上代码这块是整个流程的核心。import cv2 import os # 配置参数 IMAGE_DIR ./raw_images OUTPUT_DIR ./masked_images BOARD_REGIONS { board_1: [(100, 100), (350, 320)], board_2: [(400, 120), (650, 340)], # ... 依次配置9块板子的左上角和右下角像素坐标 } FILL_COLOR (128, 128, 128) # 中性灰色 os.makedirs(OUTPUT_DIR, exist_okTrue) def generate_masked_image(raw_img, keep_board_name): # 创建全白掩膜 mask np.ones(raw_img.shape[:2], dtypenp.uint8) * 255 # 将其他8块板子区域填充为黑色/灰色 for name, (tl, br) in BOARD_REGIONS.items(): if name keep_board_name: continue cv2.rectangle(mask, tl, br, 0, -1) # 用灰色填充被遮挡的区域注意这里用3通道mask masked_img raw_img.copy() gray_overlay np.full_like(raw_img, FILL_COLOR, dtypenp.uint8) masked_img cv2.bitwise_and(raw_img, raw_img, maskmask) # 将遮挡区域替换为中灰色 masked_img[mask 0] FILL_COLOR return masked_img # 遍历所有原始图每张图生成9张遮挡图 for fname in os.listdir(IMAGE_DIR): if not fname.endswith(.png): continue img cv2.imread(os.path.join(IMAGE_DIR, fname)) for board_name in BOARD_REGIONS.keys(): masked generate_masked_image(img, board_name) out_name f{os.path.splitext(fname)[0]}_{board_name}.png cv2.imwrite(os.path.join(OUTPUT_DIR, out_name), masked)这段代码的逻辑很简单每张原始图生成9张输出图每张输出图只保留对应板子其余区域用灰色覆盖。这里有个细节值得展开说为什么用mask 0的区域去填充灰色而不是直接在生成mask时先用cv2.rectangle画灰色矩形因为前者的操作对象是整个图像可以确保无论之前掩膜经历了什么变换比如旋转、缩放最后遮挡区域都是精准的灰色填充。实际运行之后你会得到一个masked_images目录里面包含原始图数量×9张遮挡图。比如15张原始图就会生成135张遮挡图。这些图像在后续打包成rosbag时注意保持图像尺寸和通道数一致。3.3 rosbag打包与topic配置详解Kalibr不吃裸图像需要把遮挡图序列打包成rosbag并发布成ROS图像消息。这里用cv_bridge和rospy操作比较简单。import rosbag import cv2 from cv_bridge import CvBridge from sensor_msgs.msg import Image import rospy bag rosbag.Bag(./calibration.bag, w) bridge CvBridge() topic_name /camera/image_raw for fname in sorted(os.listdir(OUTPUT_DIR)): if not fname.endswith(.png): continue img cv2.imread(os.path.join(OUTPUT_DIR, fname)) # 确保是3通道如果是灰度图则转换一下 if img.ndim 2: img cv2.cvtColor(img, cv2.COLOR_GRAY2BGR) msg bridge.cv2_to_imgmsg(img, encodingbgr8) msg.header.stamp rospy.Time.from_sec(float(idx) / 10.0) # 10Hz bag.write(topic_name, msg, tmsg.header.stamp) idx 1 bag.close()打包时的时间戳策略很关键。Kalibr对时间戳的要求是“尽量均匀”但不强制要求严格等间隔。我的做法是以10Hz的固定频率给每一帧分配时间戳这样Kalibr在处理时认为图像流是匀速的帧间的时间间隔一致。还有一个坑bag文件里的topic名称必须和你后面调用Kalibr时指定的topic名称完全一致差一个字符都不行。我踩过这个坑之前用/camera/image_raw打包调用时写成了/camera/imageKalibr报错说找不到topic排查了半天。若你是直接读取文件夹而不打包rosbag也可直接用Kalibr的kalibr_calibrate_cameras --bag calibration.bag --topics /camera/image_raw --models pinhole-radtan --target checkerboard.yaml但它依然默认输入是bag不要试图绕过这一步。3.4 标定执行与关键参数设定打包好bag之后进入Kalibr标定环节。这里需要提供一个target配置文件描述棋盘格的尺寸信息。target_type: checkerboard targetCols: 9 targetRows: 6 colSpacingMeters: 0.03 rowSpacingMeters: 0.03注意targetCols和targetRows要按实际棋盘格的内角点数写不是棋盘的格子总数。写错一个数Kalibr的检测和优化结果会完全乱掉。执行命令kalibr_calibrate_cameras --bag calibration.bag --topics /camera/image_raw --models pinhole-radtan --target checkerboard.yaml这里推荐用pinhole-radtan模型它对大多数普通镜头都适用。如果你的镜头是广角或者鱼眼可能需要换成equidistant或者fov模型这取决于镜头畸变程度。对于我手上的普通镜头pinhole-radtan标出来的重投影误差在0.2像素以内效果很好。Kalibr运行过程中会输出很多日志重点看这几个指标每个视角的角点检测数量应该接近理论值比如9×6棋盘格的理论角点数是54初始位姿估计是否成功如果初始化失败多半是检测到的角点不够或者分布太集中最终的重投影误差控制在0.5像素以内是合理的超过1像素就要怀疑数据质量输出结果会有一个camchain.yaml文件里面就是标定好的内参。保存好这个文件后续所有相机相关的处理都用它。3.5 标定结果验证与精度分析标定完成不等于结束我习惯用独立的验证帧来检验内参是否可靠。把没有参与标定的原始图未遮挡版本用标定出的内参做一次去畸变观察棋盘格角点是否变成直线、边缘是否还有弯曲。具体操作是写一段简单的去畸变代码import cv2 import yaml import numpy as np # 读取标定结果 with open(camchain.yaml, r) as f: calib_data yaml.safe_load(f) # 提取内参和畸变系数 K np.array(calib_data[camera][intrinsics]).reshape(3, 3) D np.array(calib_data[camera][distortion_coeffs]) img cv2.imread(validation_frame.png) undistorted cv2.undistort(img, K, D) cv2.imwrite(undistorted_validation.png, undistorted)重点看去畸变之后的图像棋盘格边缘的线条是否笔直。如果边缘有轻微弧线说明畸变系数标得偏大或偏小如果边缘开裂说明内参矩阵本身有问题。我这次标定的结果重投影误差为0.17像素去畸变验证图像上所有棋盘格边缘都笔直说明方案有效。另外为了进一步确认我把标定出的内参与同一个相机在严苛单板环境下标定的结果做了对比两者差距在千分之一量级这证明了原图复制方案没有引入额外的系统性误差。注意对比的标准单板标定也是用同样的棋盘格和同样的Kalibr环境只不过采集时每帧只有一块板子。用这种“对照实验”的方式能最干净地隔离出多板方案引入的偏差。如果你只跑多板方案不发散对比结果是否准确其实是心里没底的。4. 常见问题与排查技巧实录4.1 角点检测失败与区域参数调优最常遇到的问题就是某张遮挡图中的棋盘格角点检测不出来或者检测出来的数量不对。排查思路是先用Kalibr的对手工具kalibr_calibrate_cameras附带的可视化脚本或者直接用OpenCV写一个角点检测脚本单独查看。类似这样ret, corners cv2.findChessboardCorners(img, (9, 6), None) if ret: cv2.drawChessboardCorners(img, (9, 6), corners, ret) cv2.imshow(corners, img) cv2.waitKey(0)如果检测不出来大概率是遮挡区域的边界压到了棋盘格的外圈角点。解决办法是把该板子的BOARD_REGIONS扩大留出更多padding。我调整了好几次最终把padding从10像素扩到30像素后全部角点检测成功。第二种可能原因是板子在某些图中处于图像边缘畸变过大导致棋盘格扭曲严重检测器无法识别。这种情况下建议在采集阶段就避免把板子放在过于贴近边缘的位置虽然这样牺牲了一些畸变信息但总比检测失败强。第三种情况是光照影响。棋盘格黑白交替的对比度依赖均匀光照如果某块板子被灯直接照射产生高光反射角点周围的像素对比度会下降到检测阈值以下。调整光源位置或者加柔光罩基本能解决。4.2 初始化失败与优化发散排查初始化失败是最让人头疼的错误。Kalibr在初始化时需要至少两个视角的图像且这两个视角的图像看到的棋盘格必须姿态差异足够大否则PnP解不稳定。在多板场景下如果9张遮挡图对应的原始帧之间姿态差异太小比如所有帧都是相机正对着板子阵列中心那么每张图看到的板子虽然角度略有不同但整体差异不足以让PnP解出稳定的位姿序列。解决办法是在采集时让标定板阵列在相机前做大幅度的旋转和前后移动确保不同帧之间的位姿差异显著。我这次采集了30帧其中前15帧主要做旋转运动后15帧做平移运动初始化阶段在这个数据子集上稳定通过。如果初始化失败的报错信息指向“not enough inliers”或者“solver diverged”也可以尝试减少参与标定的帧数只用质量最高的10帧数据。更多数据不一定更好脏数据反而会拖累优化。4.3 重投影误差过大原因分析与修复标定完成后如果重投影误差超过1像素大概率是以下几个原因。第一遮挡区域把棋盘格外圈切掉了部分导致检测到的角点数量减少。Kalibr优化时需要足够多的角点来约束相机位姿和内参角点数量太少约束不够误差就会增大。检查检测到的角点数如果在54个基础上少了10个以上说明遮挡区域的padding不够。第二原始图像中某块板子的区域内混入了其他板子的边缘干扰了角点的提取。这种情况多发生在板子间距很近、且棋盘格之间交叉重叠的布局中。解决办法是调整板子排列间距或者把遮挡的灰色区域扩大到覆盖整个重叠区域。第三bag时间戳不连续导致Kalibr的帧选择机制选中了相邻帧角度差异过大的数据优化收敛到局部极小值。用我前面提到的10Hz均匀时间戳方法基本可以排除这个因素。修复步骤按顺序来先重新生成mask扩大padding再检查角点数量最后重新打包bag。大多数情况下前两步就能把误差压回0.5像素以内。4.4 常见错误速查表错误现象可能原因解决办法角点检测不到遮挡区域过于贴近棋盘格边界扩大padding至20~30像素初始化失败帧间姿态差异不够采集时增加旋转和平移幅度重投影误差1px角点数不足或脏数据混入检查角点数量剔除异常帧bag读不出来topic名称不一致核对bag topic和命令参数优化发散有帧的棋盘格被遮挡切断检查所有mask区域是否完整覆盖板子时间戳错误bag时间戳不递增用固定频率重新封装bag4.5 踩坑心得遮挡灰色区域与检测上下文的微妙关系前面提到遮挡色用灰色这个选择背后其实有讲究。最初我用纯黑色遮挡结果Kalibr在检测某些板子时偶尔会报出奇怪的角点坐标仔细检查发现黑色遮挡区域和棋盘格的深色格子产生了低对比度边缘检测器把这种边缘误判成棋盘格边界。换成灰色之后一方面灰色和黑色、白色格子都有足够对比度不会产生伪边界另一方面灰色在视觉上对人眼不刺眼手动检查渲染效果时不容易疲劳。我建议把FILL_COLOR设成(128, 128, 128)这个值是RGB中性的中间灰无论你的相机是彩色还是灰度模式处理都相对稳妥。5. 功能扩展与进阶建议5.1 从单相机内参扩展到多相机外参标定原图复制方案不仅能标单目内参还能迁移到多相机外参标定。多相机标定要求同一时刻多个相机看到同一个标定物从而解算出相机之间的相对位姿。在9块标定板的场景下你可以让每个相机分别对同一组板子阵列采集数据然后对每个相机的数据分别做原图复制处理得到各自的遮挡图后用Kalibr的多相机标定流程联合求解。操作上多个相机采集时的同步性很关键。如果相机硬件上没有硬件触发同步至少要在软件层保证时间戳对齐。我建议用ROS的message_filters做时间同步或者直接查硬件触发信号再传输给Kalibr。5.2 基于遮挡方案的自动化标定管线思路既然原图复制和遮挡已经可用脚本批量完成那就可以构建一个标准化标定管线相机自动采集多帧图像程序自动检测画面里的所有棋盘格位置自动生成遮挡图并打包成bag自动调用Kalibr完成标定自动验证标定结果的去畸变质量这样一条管线可以把标定时间从半天压缩到几十分钟适合产线或质检环境。核心难点在前两步自动检测棋盘格位置需要写一个多棋盘格检测器可以用cv2.findChessboardCorners配合滑动窗口扫描策略或者用深度学习方法做检测后者鲁棒性更强但工程复杂度更高。5.3 新型标定板与Kalibr适配前景Kalibr除了支持棋盘格和Aprilgrid还支持自定义target。你可以造一种多区域棋盘格每块区域带有不同的编码信息让Kalibr能在同一张图里区分不同板子。这种方案一旦实现就真正意义上解决了多板标定的问题不需要遮挡预处理。但这也意味着你需要修改Kalibr的target解析逻辑属于“改源码”路线。如果你不想改源码原图复制方案在未来一段时间内仍然是最稳妥的工程折中方案。6. 最后再分享几个小技巧做这个方案的过程中我踩过几次坑总结几条经验供你参考。第一标记板子区域时不要在代码里手写每个坐标先写一个可视化脚本把9块板子的框画出来肉眼确认框的位置无误后再批量生成mask。手写坐标很容易出错尤其当图像分辨率较高、板子分布密集的时候。第二遮挡后的图像看起来会比较“空”大片灰色区域让人觉得数据不对劲这是正常的。不要因为这个视觉感受就放弃这个方案只要最终标定结果验证通过灰色区域的存在完全不影响精度。第三做验证时别只用一幅图至少用5幅不同角度的验证帧做去畸变检查。一幅图偶然通过不代表系统稳定多角度的验证才足以说明内参的准确性。第四如果你的相机是彩色相机请确认在打包bag时使用了bgr8编码。如果用灰度编码Kalibr对灰度图处理没问题但做可视化验证时颜色信息会丢失不利于问题排查。原图复制遮挡方案的意义不只是解决了我手头的9板标定需求更重要的是它提供了一种通用思路当算法工具受限时与其去改工具不如从数据层面想办法。很多标定问题本质上不是算法不行而是数据没做好。把数据按算法期望的格式准备好标定往往就水到渠成了。如果你也遇到多板标定、或者类似“工具不支持但需求必须满足”的情况希望这个方案能给你一些启发。动手试一下应该很快就能搞定。
返回列表