ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

OpenCV ccalib 全向相机标定完全指南:Mei 模型标定、图像校正与立体三维重建

OpenCV ccalib 全向相机标定完全指南:Mei 模型标定、图像校正与立体三维重建 计算机视觉图像处理机器学习【免费下载链接】opencv_contrib项目地址https://gitcode.com/gh_mirrors/ope/opencv_contrib点击查看免费下载导读本文围绕 OpenCV 扩展模块ccalib中的全向相机Omnidirectional Camera功能展开系统讲解如何基于 C. Mei 的单视点统一模型完成单相机标定、双相机立体标定、畸变图像校正透视/圆柱/球极/经纬度四种投影以及从一对全向图像直接重建三维点云的完整流程。阅读本文后你将掌握cv::omnidir::calibrate、stereoCalibrate、undistortImage、stereoReconstruct等核心 API 的完整参数语义、推荐配置与源码级工作原理能够直接复现仓库中自带的示例程序与标定数据。模块概览从折反射相机到鱼眼相机的统一模型全向相机模块位于 modules/ccalib头文件为 include/opencv2/ccalib/omnidir.hpp提供全向相机的标定、校正与立体三维重建三类能力。模块采用的相机模型来自论文C. Mei and P. Rives, Single view point omnidirectional camera calibration from planar grids, ICRA 2007.该模型属于单视点single viewpoint统一模型能够同时描述两类拥有超大视场角FOV的相机折反射catadioptric相机由普通相机加曲面反射镜如抛物面、双曲面镜组成鱼眼fisheye相机通过广角镜头直接成像。标定部分的实现则参考了 Li 等人在 IROS 2013 发表的基于特征描述子标定图案的多相机系统标定工具箱B. Li, L. Heng, K. Kevin and M. Pollefeys, A Multiple-Camera System Calibration Toolbox Using A Feature Descriptor-Based Calibration Pattern, IROS 2013.从模块头文件注释可知omnidir模块最初是 OpenCV 2015 年 GSoC 项目成果作者 Baisheng Lai导师 Bo LiAPI 以cv::omnidir命名空间形式暴露主要包含以下能力能力核心 API说明单相机标定omnidir::calibrate输出内参 K、Mei 模型参数 xi、畸变系数 D 及各视图外参立体标定omnidir::stereoCalibrate同时标定两台相机并输出两相机相对位姿图像校正omnidir::undistortImage/initUndistortRectifyMap四种投影方式去除大畸变立体校正omnidir::stereoRectify计算两台相机的校正旋转使极线水平立体重建omnidir::stereoReconstruct输入一对全向图像输出视差图与三维点云辅助接口projectPoints/undistortPoints三维点投影、畸变点去畸变含雅可比矩阵单相机标定Single Camera Calibration第一步准备标定图案与提取角点单相机标定的第一步是准备标定图案并拍摄多张照片。OpenCV 支持多种标定图案棋盘格checkerboard使用cv::findChessboardCorners提取角点圆点网格circle grid使用cv::findCirclesGrid提取圆心随机图案random pattern使用ccalib模块自带的randomPatternCornerFinder类实现位于 src/randpattern.cpp配套示例见 samples/random_pattern_calibration.cpp 与 samples/random_pattern_generator.cpp。提取到的图像角点保存在类似imagePoints的变量中类型可以是std::vectorstd::vectorcv::Vec2f外层 vector 对应每一帧图像内层 vector 对应单帧内的全部角点std::vectorcv::Mat每个cv::Mat为CV_32FC264F 深度同样可接受。同时需要提供图案坐标系下对应的三维点保存在objectPoints中其类型与imagePoints一一对应std::vectorstd::vectorcv::Vec3f或std::vectorcv::Mat其中cv::Mat类型为CV_32FC3。关键约束objectPoints与imagePoints的帧数外层大小必须完全一致因为它们逐帧对应。三维点坐标只需根据标定板的物理尺寸如棋盘格边长自行生成即可。第二步加载示例数据仓库在 tutorials/data/omni_calib_data.xml 中提供了完整的示例数据objectPoints、imagePoints 与 imageSize其中每个棋盘视图含 54 个内角点。可用如下代码加载cv::FileStorage fs(omni_calib_data.xml, cv::FileStorage::READ); std::vectorcv::Mat objectPoints, imagePoints; cv::Size imgSize; fs[objectPoints] objectPoints; fs[imagePoints] imagePoints; fs[imageSize] imgSize;第三步调用标定函数定义输出参数变量并调用cv::omnidir::calibratecv::Mat K, xi, D, idx; int flags 0; cv::TermCriteria critia(cv::TermCriteria::COUNT cv::TermCriteria::EPS, 200, 0.0001); std::vectorcv::Mat rvecs, tvecs; double rms cv::omnidir::calibrate(objectPoints, imagePoints, imgSize, K, xi, D, rvecs, tvecs, flags, critia, idx);各输出参数含义K相机内参矩阵CV_64F深度即K [fx s cx; 0 fy cy; 0 0 1]xiMei 模型参数单值变量对应模型中的镜像球面参数是区别于普通针孔模型的关键参数D畸变系数(k1, k2, p1, p2)四项rvecs/tvecs每个视图图案相对相机的外参旋转向量与平移向量深度为CV_64FidxCV_32S类型的 Mat记录真正参与最终优化的图像索引。原因在于部分图像在初始化阶段失败如角点分布不佳会被自动剔除而不参与最终优化因此rvecs的个数等于idx.total()返回值rms重投影误差的均方根Root Mean Square是衡量标定质量的核心指标值越小说明标定越准。从源码实现src/omnidir.cpp 的cv::omnidir::calibrateL1067 起可以看出标定的完整流程输入断言检查要求objectPoints与imagePoints帧数相同、通道数分别为 3 和 2深度为CV_32F或CV_64F内部会统一转换为 64F 计算调用内部initializeCalibration做初始化得到初始K、xi、各视图om/t及通过初检的图像索引idx根据idx剔除未通过初始化的帧将参数编码为10 6*n维向量内参 10 维 每帧外参 6 维进入带平滑因子 alpha_smooth 的高斯-牛顿Gauss-Newton迭代优化每轮用computeJacobian计算雅可比更新参数直至满足TermCriteria或达到最大迭代数最终解码参数并输出K、xi、D、rvecs、tvecs。flags 枚举标定中固定哪些参数flags是一个位或bitwise OR枚举用于指定标定过程中固定不参与优化的参数。各枚举值定义于 omnidir.hpp枚举数值含义cv::omnidir::CALIB_USE_GUESS1使用输入的 K、D、xi 作为初始猜测值cv::omnidir::CALIB_FIX_SKEW2固定倾斜系数 skews0cv::omnidir::CALIB_FIX_K14固定畸变系数 k1cv::omnidir::CALIB_FIX_K28固定畸变系数 k2cv::omnidir::CALIB_FIX_P116固定畸变系数 p1cv::omnidir::CALIB_FIX_P232固定畸变系数 p2cv::omnidir::CALIB_FIX_XI64固定 Mei 模型参数 xicv::omnidir::CALIB_FIX_GAMMA128固定纵横比相关参数cv::omnidir::CALIB_FIX_CENTER256固定主点principal point于图像中心多个标志用或|组合例如CALIB_FIX_SKEW CALIB_FIX_K1表示同时固定 skew 与 k1。flags0表示所有参数均自由优化这也是教程示例的默认做法。criteria 与 TermCriteria 语义criteria是优化停止条件。例如cv::TermCriteria(cv::TermCriteria::COUNT cv::TermCriteria::EPS, 200, 0.0001)含义为最多迭代 200 次且当相对变化小于 0.0001 时提前停止。对照源码 L1123-L1127 的逻辑类型含COUNT值 1时迭代次数达到maxCount停止类型含EPS值 2时相对变化change epsilon停止两种同时指定值 3时两者任一满足即停止。示例程序 samples/omni_calibration.cpp 中使用的是TermCriteria(3, 200, 1e-8)即迭代上限 200 次、相对变化阈值 1e-8。用官方示例跑通整条标定流程仓库在 samples/omni_calibration.cpp 中提供了完整的命令行示例完整覆盖读取图像列表 → 检测棋盘角点 → 生成 objectPoints → 标定 → 保存参数全流程。其命令行参数如下omni_calibration -w6 -h9 -sw80 -sh80 imagelist.xml参数说明-w/-h棋盘内角点列数/行数boardSize-sw/-sh棋盘格边长默认 1.0单位任意须与真实物理尺寸一致-o输出参数文件默认out_camera_params.xml-fs设置CALIB_FIX_SKEW-fp设置CALIB_FIX_CENTER位置参数图像列表文件可用 OpenCV 的imagelist_creator工具生成。示例中的关键实现细节值得参考角点检测后统一convertTo(points, CV_64FC2)保证 64F 深度生成的objectPoints由calcChessboardCorners按Vec3d(j*sw, i*sh, 0.0)填充每个视图复制同一份标定完成后saveCameraParams会把 K、D、xi、flags、实际使用的图像名由 idx 索引detec_list、外参与 rms 一并写入 XML。立体标定Stereo Calibration立体标定用于同时标定两台相机输出两台相机的内参以及它们之间的相对位姿。由于需要恢复相对位姿两台相机必须同时观测同一块标定板因此两台相机的objectPoints完全相同。操作步骤分别对左右相机检测角点得到imagePoints1与imagePoints2计算共享的objectPoints。仓库提供了立体标定示例数据 tutorials/data/omni_stereocalib_data.xml含 48 个内角点、多组双目视图的imagePoints1/imagePoints2以及两组不同尺寸的imageSize1/imageSize2。加载方式cv::FileStorage fs(omni_stereocalib_data.xml, cv::FileStorage::READ); std::vectorcv::Mat objectPoints, imagePoints1, imagePoints2; cv::Size imgSize1, imgSize2; fs[objectPoints] objectPoints; fs[imagePoints1] imagePoints1; fs[imagePoints2] imagePoints2; fs[imageSize1] imgSize1; fs[imageSize2] imgSize2;然后调用cv::omnidir::stereoCalibratecv::Mat K1, K2, xi1, xi2, D1, D2; int flags 0; cv::TermCriteria critia(cv::TermCriteria::COUNT cv::TermCriteria::EPS, 200, 0.0001); std::vectorcv::Mat rvecsL, tvecsL; cv::Mat rvec, tvec; double rms cv::omnidir::stereoCalibrate(objectPoints, imagePoints1, imagePoints2, imgSize1, imgSize2, K1, xi1, D1, K2, xi2, D2, rvec, tvec, rvecsL, tvecsL, flags, critia, idx);输出参数语义K1、xi1、D1/K2、xi2、D2左右相机各自的内参与畸变系数rvec、tvec第一台相机到第二台相机的旋转向量与平移向量即两相机相对位姿rvecsL、tvecsL各视图标定板相对第一台相机的位姿idx通过初始化并真正参与优化的图像对索引rvecsL数量与其一致rms重投影误差均方根。从源码L1213 起看立体标定会先分别对左右相机各做一次独立单目标定以获得初始值内部调用calibrate条件为TermCriteria(3, 100, 1e-6)再由initializeStereoCalibration求相对位姿初值最后进入联合优化computeJacobianStereo 高斯-牛顿更新即先单目、后立体联合精化的经典策略。命令行示例见 samples/omni_stereo_calibration.cpp用法omni_stereo_calibration -w 8 -h 6 -sw 2.4399 -sh 2.4399 imagelist_left.xml imagelist_right.xml与单目示例不同的是它需要两个图像列表文件左右各一并且仅当左右两幅图都成功检测到角点时才把该帧计入标定数据。图像校正Image Rectification全向图像具有非常大的畸变不符合人眼观察习惯。在已知相机参数的前提下可以对图像做校正得到更自然的视角。下图是一张水平视场角达 360° 的全向相机原始图像畸变非常明显undistortImage 接口运行图像校正的核心接口为cv::omnidir::undistortImage(distorted, undistorted, K, D, xi, int flags, Knew, new_size);参数说明distorted/undistorted原始畸变图像与校正后的输出图像K、D、xi标定得到的相机参数Knew校正后图像的新相机矩阵new_size校正后图像尺寸默认取原图尺寸flags校正类型共四种见下表。四种校正类型枚举含义特点RECTIFY_PERSPECTIVE透视校正输出类人眼透视视图会丢失部分视场角RECTIFY_CYLINDRICAL圆柱投影校正保留全部视场角场景仅在底部中间略显不自然RECTIFY_STEREOGRAPHIC球极投影校正底部中间畸变比圆柱小但其他区域畸变更大且不能保留全部视场RECTIFY_LONGLATI经纬度longitude-latitude校正类似地球仪的世界地图展开不适合直接观看但使极线约束落在同一条水平线上可用于后续立体匹配四种校正类型的示例效果分别存放在 tutorials/img 下的sample_rec_per.jpg、sample_rec_cyl.jpg、sample_rec_ste.jpg、sample_rec_log.jpg。经验结论来自教程原文透视校正只保留很小一部分视场观感一般圆柱校正保留全部视场仅底部中间场景不自然球极校正底部中间畸变小于圆柱但其余区域畸变更大且无法保留全部视场对畸变极大的图像经纬度校正的视觉结果不佳但它让极线约束落在一条直线上使得全向图像上的立体匹配成为可能经纬度展开方式的原理可参考论文Li S., Binocular spherical stereo, IEEE Transactions on Intelligent Transportation Systems, 2008, 9(4): 589-600。Knew 的推荐取值为获得较好校正效果需要根据相机特性仔细选择Knew一般而言焦距越小视场角越大焦距越大视场角越小。教程给出了两组推荐初始设置。对于RECTIFY_PERSPECTIVEKnew Matx33f(new_size.width/4, 0, new_size.width/2, 0, new_size.height/4, new_size.height/2, 0, 0, 1);对于RECTIFY_CYLINDRICAL、RECTIFY_STEREOGRAPHIC、RECTIFY_LONGLATIKnew Matx33f(new_size.width/3.1415, 0, 0, 0, new_size.height/3.1415, 0, 0, 0, 1);即圆柱/球极/经纬度三类投影的主点建议放在图像左上角 (0,0)焦距取new_size.width/π与new_size.height/π。实际使用时可能还需调整主点(u0, v0)以获得更好的视野。立体重建示例中也采用了KNew(width/3.1415, 0, 0, 0, height/3.1415, 0, 0, 0, 1)的形式其中 theta 取值范围为 (0, π)phi 取值范围为 (0, π)。底层实现上undistortImage会调用initUndistortRectifyMap生成两张重映射查找表CV_16SC2类型再执行cv::remap见 src/omnidir.cpp L536-L544因此对固定相机参数可以复用查找表以提升效率。立体三维重建Stereo Reconstruction为什么全向立体重建有挑战性立体重建是计算机视觉的基本问题但在全向相机上并不常见因为巨大的畸变增加了难度。传统做法是先透视校正再做立体匹配但正如上文所述透视校正会丢失过多视场角反而浪费了全向相机大视场的核心优势。因此omnidir模块的思路是优先采用经纬度校正或可选透视校正使极线成为水平线再进行立体匹配与三维重建。stereoReconstruct 完整流程与代码该流程对应的 API 为cv::omnidir::stereoReconstruct其内部调用链见 src/omnidir.cpp L1383 起为立体校正调用stereoRectify(R, T, R1, R2)求得左右相机的校正旋转使两台相机的成像平面共面且极线水平图像校正分别用undistortImage(image1, ..., R1)与undistortImage(image2, ..., R2)得到极线对齐的image1Rec/image2Rec立体匹配用cv::StereoSGBM::create(0, numDisparities, SADWindowSize, ...)计算视差图原始 SGBM 视差除以 16.0 得到真实视差点云生成由视差与相机几何生成pointCloud。使用示例教程原文整理cv::Size imgSize img1.size(); int numDisparities 16*5; int SADWindowSize 5; cv::Mat disMap; int flag cv::omnidir::RECTIFY_LONGLATI; int pointType omnidir::XYZRGB; // theta 取值范围 (0, pi)phi 取值范围 (0, pi) cv::Matx33d KNew(imgSize.width / 3.1415, 0, 0, 0, imgSize.height / 3.1415, 0, 0, 0, 1); Mat imageRec1, imageRec2, pointCloud; cv::omnidir::stereoReconstruct(img1, img2, K1, D1, xi1, K2, D2, xi2, R, T, flag, numDisparities, SADWindowSize, disMap, imageRec1, imageRec2, imgSize, KNew, pointCloud);参数要点flag校正类型只有RECTIFY_LONGLATI推荐与RECTIFY_PERSPECTIVE有效。源码中也有CV_Assert(flag omnidir::RECTIFY_LONGLATI || flag omnidir::RECTIFY_PERSPECTIVE)的断言约束numDisparitiescv::StereoSGBM的最大视差参数示例为 16×580即 80 像素SADWindowSizecv::StereoSGBM的 SAD 窗口尺寸示例为 5pointType点云类型标志omnidir::XYZRGB值 1每个点是 6 维向量前 3 个元素为 xyz 坐标后 3 个元素为 rgb 颜色信息omnidir::XYZ值 2每个点仅含 3 维 xyz 坐标imageRec1/imageRec2校正后的左右图像两者的极线具有相同的 y 坐标从而大大简化立体匹配disMapcv::StereoSGBM输出的视差图pointCloud存储于 3 通道cv::MatCV_64FC3中的点云数据头文件注释亦作此说明可通过pointType控制是否携带颜色。重建示例与中间结果以仓库教程配套的双目全向输入图像为例左右两张全向图并排展示经过经纬度校正后两幅图像的极线被对齐到同一水平线上仓库示例图lines.jpg展示了这种良好的对齐效果。StereoSGBM基于校正后的图像计算出视差图示例图disparity.jpg最后由视差生成三维点云。点云可视化示例见 tutorials/img/pointCloud.jpg从源码看重建输出会通过校正后图像的非黑色区域生成有效掩膜排除左右视图公共视野之外的无效视差区域保证点云中只保留有效三维点。与 OpenCV calib3d 鱼眼模型的对比本教程最后提及与 OpenCV 主模块opencv/calib3d中**鱼眼模型fisheye model**的对比。二者的核心区别在于模型形式与适用范围calib3d的 fisheye 模型专为鱼眼镜头设计的畸变模型只覆盖鱼眼这类大视场镜头不含折反射镜面模型omnidir的 Mei 模型单视点统一模型通过参数xi统一描述折反射相机与鱼眼相机覆盖范围更广这也是omnidirectional全向命名所强调的能力。因此若只需标定普通鱼眼镜头calib3d的 fisheye API 足够若需要同时处理折反射全向相机、或需要在全向图像上做极线约束立体匹配则应使用omnidir模块。具体数值层面的对比结论需结合各自标定实验得出本文不给出未经实测的结论。延伸阅读模块总览与更多标定能力modules/ccalib/README.md含随机标定图案与多相机标定multicalib的介绍单相机标定完整示例samples/omni_calibration.cpp立体标定完整示例samples/omni_stereo_calibration.cpp随机图案标定示例samples/random_pattern_calibration.cppAPI 头文件与全部枚举定义include/opencv2/ccalib/omnidir.hpp底层实现初始化、雅可比、高斯-牛顿优化、立体重建流水线src/omnidir.cpp单目/立体标定示例数据tutorials/data/omni_calib_data.xml 与 tutorials/data/omni_stereocalib_data.xml多相机标定教程tutorials/multi_camera_tutorial.markdown。赞分享计算机视觉图像处理机器学习【免费下载链接】opencv_contrib项目地址https://gitcode.com/gh_mirrors/ope/opencv_contrib点击查看免费下载相关推荐OpenCV 全向相机标定实战基于 ccalib 模块的鱼眼/折反射相机标定、矫正与立体重建OpenCV 全向相机标定实战基于 ccalib 模块的鱼眼/折反射相机标定、矫正与立体重建 全向相机Omnidirectional Camera通常指视计算机视觉图像处理深度学习机器学习终极广角镜头校正指南OpenCV ccalib模块相机标定实战终极广角镜头校正指南OpenCV ccalib模块相机标定实战 想要解决广角镜头带来的严重畸变问题吗OpenCV的ccalib模块提供了完整的全向相机标定解计算机视觉图像处理机器学习如何永久保存你的微信聊天记录WeChatMsg完整指南如何永久保存你的微信聊天记录WeChatMsg完整指南 你是否曾为那些消失的聊天记录感到遗憾那些深夜的温馨对话、重要的商务沟通、珍贵的家庭回忆都随着手机更上一篇ComfyUI-VideoHelperSuite3分钟掌握AI视频合成核心技巧下一篇ComfyUI-VideoHelperSuite终极指南5分钟掌握AI视频合成技巧创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表