OpenCV相机标定与3D重建(8)相机标定函数calibrateCamera()的使用
- 操作系统:ubuntu22.04
- OpenCV版本:OpenCV4.9
- IDE:Visual Studio Code
- 编程语言:C++11
算法描述
从校准图案的多个视图中找到相机的内参和外参参数.
cv::calibrateCamera 是 OpenCV 中用于相机标定的一个非常重要的函数。它通过一系列已知的世界坐标点(通常是棋盘格角点)和它们在图像中的对应点来计算相机的内参矩阵 cameraMatrix 和畸变系数 distCoeffs。
函数原型
double cv::calibrateCamera
(InputArrayOfArrays objectPoints,InputArrayOfArrays imagePoints,Size imageSize,InputOutputArray cameraMatrix,InputOutputArray distCoeffs,OutputArrayOfArrays rvecs,OutputArrayOfArrays tvecs,OutputArray stdDeviationsIntrinsics,OutputArray stdDeviationsExtrinsics,OutputArray perViewErrors,int flags = 0,TermCriteria criteria = TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, 30, DBL_EPSILON)
)
参数
- 参数objectPoints:
在新接口中,这是一个包含校准图案点在标定图案坐标空间中的向量的向量(例如 std::vector<std::vectorcv::Vec3f>)。外层向量包含的元素数量与图案视图的数量相同。如果每个视图中显示相同的标定图案且完全可见,则所有向量将相同。尽管可以使用部分遮挡的图案,甚至在不同的视图中使用不同的图案,在这种情况下,向量将不同。虽然这些点是3D的,但如果使用的标定图案是平面刚体,它们都位于标定图案的XY坐标平面上(因此Z坐标为0)。在旧接口中,来自不同视图的所有对象点向量被连接在一起。 - 参数imagePoints:
在新接口中,这是一个包含标定图案点投影的向量的向量(例如 std::vector<std::vectorcv::Vec2f>)。imagePoints.size() 和 objectPoints.size(),以及对于每个 i 的 imagePoints[i].size() 和 objectPoints[i].size() 必须分别相等。在旧接口中,来自不同视图的所有对象点向量被连接在一起。 - 参数imageSize:
图像尺寸,仅用于初始化相机内参矩阵。 - 参数cameraMatrix:
输入/输出 3x3 浮点相机内参矩阵 A = [ f x 0 c x 0 f y c y 0 0 1 ] A = \begin{bmatrix} f_x & 0 & c_x \\ 0 & f_y & c_y \\ 0 & 0 & 1 \end{bmatrix} A= fx000fy0cxcy1 。如果指定了 CALIB_USE_INTRINSIC_GUESS 和/或 CALIB_FIX_ASPECT_RATIO、CALIB_FIX_PRINCIPAL_POINT 或 CALIB_FIX_FOCAL_LENGTH,则必须在调用函数之前初始化 f_x、f_y、c_x 和 c_y 中的一个或全部。 - 参数distCoeffs:
输入/输出畸变系数向量 (k1, k2, p1, p2[, k3[, k4, k5, k6[, s1, s2, s3, s4[, τx, τy]]]]),包含 4、5、8、12 或 14 个元素。 - 参数rvecs:
输出旋转向量 (Rodrigues) 估计值,每个图案视图一个 (例如 std::vectorcv::Mat )。也就是说,每个第 i 个旋转向量和相应的第 i 个平移向量(见下一个输出参数描述)将标定图案从对象坐标空间(其中指定对象点)带到相机坐标空间。更技术地说,第 i 个旋转和平移向量的组合执行了从对象坐标空间到相机坐标空间的基变换。由于其对偶性,这个组合等同于标定图案相对于相机坐标空间的位置。 - 参数tvecs:
输出平移向量估计值,每个图案视图一个,参见上述参数描述。 - 参数stdDeviationsIntrinsics:
输出内参标准偏差估计值。偏差值的顺序:(fx, fy, cx, cy, k1, k2, p1, p2, k3, k4, k5, k6, s1, s2, s3, s4, τx, τy)。如果某个参数未估计,则其偏差为零。 - 参数stdDeviationsExtrinsics:
输出外参标准偏差估计值。偏差值的顺序:(R0, T0, …, RM−1, TM−1),其中 M 是图案视图的数量。Ri, Ti 是连接的 1x3 向量。 - 参数perViewErrors:
输出每个图案视图的 RMS 重投影误差估计值。 - 参数flags:
不同的标志,可以为零或以下值的组合:- CALIB_USE_INTRINSIC_GUESS: cameraMatrix 包含有效的初始值 fx, fy, cx, cy,这些值将进一步优化。否则,(cx, cy) 初始设置为图像中心(使用 imageSize),焦距通过最小二乘法计算。注意,如果已知内参参数,不需要使用此函数仅估计外参参数。应使用 solvePnP。
- CALIB_FIX_PRINCIPAL_POINT: 主点在全局优化过程中不改变。它保持在中心或在设置了 CALIB_USE_INTRINSIC_GUESS 时指定的不同位置。
- CALIB_FIX_ASPECT_RATIO: 函数仅考虑 fy 作为自由参数。fx/fy 的比例保持与输入 cameraMatrix 中的比例相同。当未设置 - CALIB_USE_INTRINSIC_GUESS 时,实际输入的 fx 和 fy 值被忽略,仅计算并使用它们的比例。
- CALIB_ZERO_TANGENT_DIST: 切向畸变系数 (p1, p2) 设置为零并保持为零。
- CALIB_FIX_FOCAL_LENGTH: 如果设置了 CALIB_USE_INTRINSIC_GUESS,则焦距在全局优化过程中不改变。
- CALIB_FIX_K1, …, CALIB_FIX_K6: 相应的径向畸变系数在优化过程中不改变。如果设置了 CALIB_USE_INTRINSIC_GUESS,则使用提供的 distCoeffs 矩阵中的系数。否则,将其设置为 0。
- CALIB_RATIONAL_MODEL: 启用系数 k4, k5 和 k6。为了提供向后兼容性,需要显式指定此额外标志以使标定函数使用有理模型并返回 8 个或更多系数。
- CALIB_THIN_PRISM_MODEL: 启用系数 s1, s2, s3 和 s4。为了提供向后兼容性,需要显式指定此额外标志以使标定函数使用薄棱镜模型并返回 12 个或更多系数。
- CALIB_FIX_S1_S2_S3_S4: 薄棱镜畸变系数在优化过程中不改变。如果设置了 CALIB_USE_INTRINSIC_GUESS,则使用提供的 - distCoeffs 矩阵中的系数。否则,将其设置为 0。
- CALIB_TILTED_MODEL: 启用系数 τX 和 τY。为了提供向后兼容性,需要显式指定此额外标志以使标定函数使用倾斜传感器模型并返回 14 个系数。
- CALIB_FIX_TAUX_TAUY: 倾斜传感器模型的系数在优化过程中不改变。如果设置了 CALIB_USE_INTRINSIC_GUESS,则使用提供的 distCoeffs 矩阵中的系数。否则,将其设置为 0。
- 参数criteria:
迭代优化算法的终止条件。
返回值
总体 RMS 重投影误差
该函数估计每个视图的相机内参和外参。算法基于 [314] 和 [37]。必须指定3D对象点及其在每个视图中的对应2D投影坐标。这可以通过使用具有已知几何形状且易于检测特征点的对象来实现。这种对象被称为校准装置或校准图案,OpenCV 内置支持棋盘格作为校准装置(见 findChessboardCorners)。目前,内参初始化(当未设置 CALIB_USE_INTRINSIC_GUESS 时)仅适用于平面校准图案(其中对象点的 Z 坐标必须全为零)。只要提供了初始的 cameraMatrix,也可以使用3D校准装置。
算法执行以下步骤:
- 计算初始内参(仅适用于平面校准图案)或从输入参数中读取。畸变系数最初全部设为零,除非指定了某些 CALIB_FIX_K?。
- 估计初始相机姿态,假设内参已经已知。这是通过 solvePnP 完成的。
- 运行全局 Levenberg-Marquardt 优化算法 以最小化重投影误差,即观测特征点 imagePoints 和投影(使用当前估计的相机参数和姿态)对象点 objectPoints 之间的总平方距离之和。有关详细信息,请参见 projectPoints。
- 注意事项
如果你使用非正方形(即非 N x N)网格并使用 findChessboardCorners 进行校准,并且 calibrateCamera 返回了不合理的值(例如,畸变系数为零,cx 和 cy 远离图像中心,或者 fx 和 fy 之间有较大的差异(比率超过 10:1 或更多)),那么你可能在 findChessboardCorners 中使用了 patternSize=cvSize(rows, cols) 而不是 patternSize=cvSize(cols, rows)。
如果提供了不支持的参数组合或系统欠定,该函数可能会抛出异常。
代码示例
#include <opencv2/opencv.hpp>
#include <iostream>
#include <vector>int main() {// 棋盘格参数int boardSize = 10; // 棋盘格的行数和列数double squareSize_mm = 10.0; // 每个方块的大小,以毫米为单位// 图像尺寸cv::Size imageSize;// 存储所有图像中的棋盘格角点std::vector<std::vector<cv::Point2f>> imagePoints;std::vector<std::vector<cv::Point3f>> objectPoints;// 生成对象点std::vector<cv::Point3f> obj;for (int y = 0; y < boardSize; ++y) {for (int x = 0; x < boardSize; ++x) {obj.push_back(cv::Point3f(x * squareSize_mm, y * squareSize_mm, 0));}}// 读取图像文件列表std::vector<std::string> imageFilenames = {"image1.jpg", "image2.jpg", "image3.jpg", "image4.jpg"}; // 添加更多图像for (const auto &filename : imageFilenames) {cv::Mat image = cv::imread(filename);if (image.empty()) {std::cerr << "无法读取图像: " << filename << std::endl;continue;}if (imageSize.width == 0 || imageSize.height == 0) {imageSize = image.size();}std::vector<cv::Point2f> corners;bool found = cv::findChessboardCorners(image, cv::Size(boardSize, boardSize), corners);if (found) {// 亚像素精度调整cv::cornerSubPix(image, corners, cv::Size(11, 11), cv::Size(-1, -1),cv::TermCriteria(cv::TermCriteria::EPS + cv::TermCriteria::COUNT, 30, 0.01));// 保存角点imagePoints.push_back(corners);objectPoints.push_back(obj);// 可视化角点cv::drawChessboardCorners(image, cv::Size(boardSize, boardSize), corners, found);cv::imshow("Chessboard Corners", image);cv::waitKey(500); // 显示图像,等待半秒} else {std::cerr << "无法找到棋盘格角点: " << filename << std::endl;}}// 标定相机cv::Mat cameraMatrix, distCoeffs;std::vector<cv::Mat> rvecs, tvecs;std::vector<float> perViewErrors;double rms = cv::calibrateCamera(objectPoints, imagePoints, imageSize, cameraMatrix, distCoeffs, rvecs, tvecs,cv::noArray(), cv::noArray(), perViewErrors,cv::CALIB_FIX_ASPECT_RATIO | cv::CALIB_ZERO_TANGENT_DIST);std::cout << "Reprojection error: " << rms << std::endl;std::cout << "Camera matrix: " << cameraMatrix << std::endl;std::cout << "Distortion coefficients: " << distCoeffs << std::endl;// 使用标定结果进行图像校正for (const auto &filename : imageFilenames) {cv::Mat image = cv::imread(filename);if (image.empty()) {std::cerr << "无法读取图像: " << filename << std::endl;continue;}cv::Mat undistortedImage;cv::undistort(image, undistortedImage, cameraMatrix, distCoeffs);cv::imshow("Undistorted Image", undistortedImage);cv::waitKey(0);}return 0;
}
相关文章:
OpenCV相机标定与3D重建(8)相机标定函数calibrateCamera()的使用
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 从校准图案的多个视图中找到相机的内参和外参参数. cv::calibrateCamera 是 OpenCV 中用于相机标定的一个非常重要的函数。它通过一系列已知的世…...
Linux信号量的编程
一,用信号量来实现是父进程先进行,还是子进程先进性 信号量的没有P,V操作之前,我们不知道如何控制: #include <stdio.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h>…...
“Yaker,你可以全局配置插件环境变量!“
周四周四,Vme50(bushi 大家好,这里是疯狂超级牛(功能上新版) 经常有用户问 “牛牛如何为不同插件配置相同的变量值呢?” “能有一个一波搞定插件变量的方式就好了” 超级牛听到了广大用户的声音,默默地拿起…...
SAAS美容美发系统架构解析
随着技术的不断发展,SAAS(Software as a Service,软件即服务)模式在各个行业的应用逐渐深化,美容美发行业也不例外。传统的美容美发店面通常依赖纸质记录、手动操作和复杂的管理流程,而随着SAAS平台的出现&…...
如何为 ext2/ext3/ext4 文件系统的 /dev/centos/root 增加 800G 空间
如何为 ext2/ext3/ext4 文件系统的 /dev/centos/root 增加 800G 空间 一、引言二、检查当前磁盘和分区状态1. 使用 `df` 命令检查磁盘使用情况2. 使用 `lsblk` 命令查看分区结构3. 使用 `fdisk` 或 `parted` 命令查看详细的分区信息三、扩展逻辑卷(如果使用 LVM)1. 检查 LVM …...
vscode远程连接ssh
一. 使用vscode里的ssh查件连不上远程的解决方法 删除Windows上的known_host文件,该文件会在连接之后自动生成,用于验证远程服务器的身份。 konwn_host和id_rsa,id_rsa.pub的关系 (1)konwn_host用于客户端验证远程服务…...
智慧防汛平台在城市生命线安全建设中的应用
随着城市化进程的加快,城市基础设施的复杂性和互联性不断增强,城市生命线的安全管理面临前所未有的挑战。智慧防汛平台作为城市生命线安全建设的重要组成部分,通过现代信息技术提升城市防汛应急管理的智能化水平,保障城市安全。 …...
python实现TCP Socket控制测试仪器
python实现TCP Socket控制测试仪器 说明前提条件代码 说明 本例是用python实现TCP Socket,最终目的是为了控制LCR电容测试仪器。 前提条件 测试仪器 配备了以太网接口,支持TCP/IP协议栈 用户可以通过IP地址和端口号连接到仪器,建立TCP通信…...
51c自动驾驶~合集38
我自己的原文哦~ https://blog.51cto.com/whaosoft/12358456 #GaussianPretrain 万能3D高斯预训练表示!爆拉3D检测、Occ、高精地图等四大任务! 受Tesla的技术的推动,越来越多的厂商开始走"纯视觉"的路线,多数方案还…...
电脑显示器拔插DVI线后副屏不显示
问题:台式机副屏显示器插拔DVI线后副屏无法检测到,不显示 其他现象:电脑设备管理器“显示适配器”中只有独显,未显示集显。 尝试方法: 1、 重新插拔并拧紧DVI线、更换DVI线、将DVI线替换为VGA线、调换DVI线及VGA线两…...
Bash脚本常用命令
1.Bash常用快捷键 2.通配符 3.Bash其他特殊符号 4.位置参数 5.预定义变量 6.常用变量比较 7.基础正则表达式 8.文件类型判断 9.文件权限判断 10.整数比较命令 11.字符串判断 其他常用参考: https://zhuanlan.zhihu.com/p/748857250...
《Unity Shader 入门精要》高级纹理
立方体纹理 图形学中,立方体纹理(Cubemap)是环境映射(Environment Mapping)的一种实现方法。环境映射可以模拟物体周围的环境,而使用了环境映射的物体可以看起来像镀了层金属一样反射出周围的环境。 对立…...
vue3实现自定义导航菜单
一、创建项目 1. 打开HBuilder X 图1 2. 新建一个空项目 文件->新建->项目->uni-app 填写项目名称:vue3demo 选择项目存放目录:D:/HBuilderProjects 一定要注意vue的版本,当前选择的版本为vue3 图2 点击“创建”之后进入项目界面 图…...
[2024年3月10日]第15届蓝桥杯青少组stema选拔赛C++中高级(第二子卷、编程题(2))
方法一(string): #include <iostream> #include <string> using namespace std;// 检查是否为回文数 bool isPalindrome(int n) {string str to_string(n);int left 0, right str.size() - 1;while (left < right) {if (s…...
EDA软件研发的DevOps平台
1:什么是DevOps DevOps是十几年前,在互联网比较火的词,实际上就是ci/cd平台的另外一种说法,核心是说打破研发,测试,运维的边界,能够将整个产品开发的流程快速循环起来,随时可发版&a…...
从单机缓存到分布式缓存那些事
作者:秦怀 1 缓存前世今生 1.1 故事从硬件开始 Cache 一词来源于 1967 年的一篇电子工程期刊论文。其作者将法语词“cache”赋予“safekeeping storage”的涵义,用于电脑工程领域。当时没有 Cache,CPU 和内存都很慢,CPU 直接访…...
[Ubuntu20] Gym入门,Mujoco
OpenAI Gym是 OpenAI 出的研究强化学习算法的 toolkit,对于强化学习算法来说,大部分的论文环境都已经被 OpenAI 的 gym 环境集成,我们可以很便利的使用该工程来测试自己的强化学习算法,与他人的算法做一个对比。 Gym 官网 Github…...
Linux(ubuntu)系统的一些基本操作和命令(持续更新)
操作: Ctrl Alt T(打开命令终端) Ctrl Shift (放大命令终端窗口) Ctrl c(退出当前在终端运行的程序) 在命令终端窗口按Tab键可以补全要写的命令 命令: pwd(查…...
【NLP高频面题 - 分布式训练】ZeRO1、ZeRO2、ZeRO3分别做了哪些优化?
【NLP高频面题 - 分布式训练】ZeRO1、ZeRO2、ZeRO3分别做了哪些优化? 重要性:★★ NLP Github 项目: NLP 项目实践:fasterai/nlp-project-practice 介绍:该仓库围绕着 NLP 任务模型的设计、训练、优化、部署和应用&am…...
android 安全sdk相关
前述 在网上有看到许多android安全sdk相关的内容,有重复的也有比较新鲜的内容,这里做一个整体的合集,以及后续又看到一些比较新的东西会一起放在这里。 android内sdk目前可以分为以下几个部分(有一些部分可能会存在一些重合&#…...
NVR监测软件EasyNVR多个NVR同时管理:录播主机的5条常见问题与解决办法
视频监控广泛应用于城市治安、交通管理、商业安保及家庭监控等领域。在使用EasyNVR平台管理多个NVR设备时,尤其是涉及到海康录播主机的场景中,使用者可能会遇到一些常见问题。本文将探讨海康录播主机的五个常见问题及其解决办法。 1、海康录播主机的5条常…...
Z2400027基于Java+SpringBoot+Mysql+thymeleaf引擎的图书馆管理系统的设计与实现 代码 论文
图书馆管理系统的设计与实现 一、项目背景与简介二、系统总体功能三、运行环境与技术选型四、系统架构与模块划分五、系统界面截图六、源码获取 一、项目背景与简介 项目背景: 随着信息技术的不断发展和图书资源的日益丰富,图书馆作为知识传播和学习的重…...
完美解决Docker pull时报错:https://registry-1.docker.io/v2/
1、错误描述 rootubuntu-database:/opt/dify/docker# docker compose up -d [] Running 9/9✘ api Error context canceled …...
A051-基于Spring Boot的网络海鲜市场系统的设计与实现
🙊作者简介:在校研究生,拥有计算机专业的研究生开发团队,分享技术代码帮助学生学习,独立完成自己的网站项目。 代码可以查看文章末尾⬇️联系方式获取,记得注明来意哦~🌹 赠送计算机毕业设计600…...
【组件】前端ElementUi 下拉Tree树形组件 带模糊搜索自动展开高亮功能 树结构 封装为组件使用
【组件】前端ElementUi 下拉Tree树形组件 带模糊搜索自动展开高亮功能 树结构 【组件】前端ElementUi 下拉Tree树形组件 带模糊 https://live.csdn.net/v/436057 单独使用 <template><div><el-popoverstyle"overflow-y: auto; "placement"bottom…...
Blender 运行python脚本
Blender 运行python脚本 步骤 1:打开 Blender 首先,打开 Blender 软件。你可以从官方网站 [blender.org]( 下载最新的 Blender 版本,并按照安装向导进行安装。 步骤 2:打开“文本编辑器”面板 在 Blender 的默认布局中ÿ…...
递归:求fib数列的第n项,前几项是1,1,2,3,5,每一项都等于前面两项的和:JAVA
链接:登录—专业IT笔试面试备考平台_牛客网 来源:牛客网 求fib数列的第n项,前几项是1,1,2,3,5,每一项都等于前面两项的和 输入描述: 输入一个整数n,n<46 输出描述: 输出一个…...
三分钟快速掌握——Linux【vim】的使用及操作方法
一、vim的使用 vim是一个文本编辑器 非常小巧轻便 1.1如何进入vim编辑器 方法一: 首先使用touch 1.c 创建一个源文件 然后使用vim 1.c进入 方法二: 直接使用指令 vim 2.c 会直接创建一个2.c的源文件 退出时记得保存(使用wq或者x&am…...
Wrapper包装类
包装类又叫封装类,Java的数据类型有两种,基础数据类型是基础的,从狭义的角度看它们不是面向对象的,在引用数据类型中,有八个引用数据类型对应了八个基础数据类型,这个八个引用数据类型就叫做基础数据类型的…...
MySQL高级(六):全局锁、表锁和行锁
全局锁 (Global Lock) 定义 全局锁作用于整个 MySQL 实例。加上全局锁后,整个数据库实例会被锁定,其他线程无法对数据库中的任何表或数据进行读写操作。 使用方式 通过命令 FLUSH TABLES WITH READ LOCK (FTWRL) 来加全局锁。 特点 影响范围&#…...
杭州做网站哪里好/武汉seo和网络推广
•参考资料 [1]:挑战程序设计竞赛(第二版) [2]:http://www.hankcs.com/program/m-n-recursive-division.html(注意看评论) •自学笔记 •对参考资料[2]的理解 定义dp[ i ][ j ] : 将 j 个物品划分成 i 组的总方案数 •1.对“我们定义 n 的 m 划分具体为一…...
wordpress建立移动m站/免费推广网站入口
目录 一、StreamTokenizer中的基本方法 二、StreamTokenizer的构造方法 2.1 指定单词要素 2.2 指定分隔符 三、算法题用法 3.1 普通用法 3.2 多组输入 一、StreamTokenizer中的基本方法 commenChar(int ch) - 指定某个字符为注释字符,此字符之后直到行结尾都被stre…...
国外做美食的网站有哪些/南京seo网站优化推广
[tips2] 文/superhei 05-02-10 1.不要错误判断(特殊字符)的sql注射 经典方法: id1 and 12 union select 1,1,1,1,1,1,1 再根据特殊字符判断 我们知道当上面的字段前后一样时,查询出来的字段数据都被1替换了,这里用可以把1改为一个特殊点的数字…...
qq营销/东莞网络优化公司
一大早,U-Mail客服张小姐就被电话催得迅速进入工作状态,原来一位客户心急火燎的说邮件往外界投递失败,但不知什么原因?张小姐迅速联系到客户专享技术工程师刘工,迅速对客户进行远程诊断,即刻排除了故障&…...
温州制作网站软件/实体店引流推广方法
PHP中两个数组合并可以使用或者array_merge,但之间还是有区别的,本篇文章介绍的就是PHP数组合并与array_merge的区别分析和对多个数组合并去重技巧 ,有需要的朋友可以看一下本文。主要区别是两个或者多个数组中如果出现相同键名,键…...
宁波企业网站制作/google中文搜索引擎
(点击上方公众号,可快速关注)来源:Float_Luuu,my.oschina.net/andylucc/blog/539783今天查了很多资料,主要是想搞清楚写JAVA和CacheLine有什么关系以及我们如何针对CacheLine写出更好的JAVA程序。CPU和内存CPU是计算机的大脑&…...