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目前可以分为以下几个部分(有一些部分可能会存在一些重合&#…...
使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式
一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明:假设每台服务器已…...
云计算——弹性云计算器(ECS)
弹性云服务器:ECS 概述 云计算重构了ICT系统,云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台,包含如下主要概念。 ECS(Elastic Cloud Server):即弹性云服务器,是云计算…...
条件运算符
C中的三目运算符(也称条件运算符,英文:ternary operator)是一种简洁的条件选择语句,语法如下: 条件表达式 ? 表达式1 : 表达式2• 如果“条件表达式”为true,则整个表达式的结果为“表达式1”…...
【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例
文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...
Rust 异步编程
Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...
【HTTP三个基础问题】
面试官您好!HTTP是超文本传输协议,是互联网上客户端和服务器之间传输超文本数据(比如文字、图片、音频、视频等)的核心协议,当前互联网应用最广泛的版本是HTTP1.1,它基于经典的C/S模型,也就是客…...
浅谈不同二分算法的查找情况
二分算法原理比较简单,但是实际的算法模板却有很多,这一切都源于二分查找问题中的复杂情况和二分算法的边界处理,以下是博主对一些二分算法查找的情况分析。 需要说明的是,以下二分算法都是基于有序序列为升序有序的情况…...
Spring AI与Spring Modulith核心技术解析
Spring AI核心架构解析 Spring AI(https://spring.io/projects/spring-ai)作为Spring生态中的AI集成框架,其核心设计理念是通过模块化架构降低AI应用的开发复杂度。与Python生态中的LangChain/LlamaIndex等工具类似,但特别为多语…...
Xen Server服务器释放磁盘空间
disk.sh #!/bin/bashcd /run/sr-mount/e54f0646-ae11-0457-b64f-eba4673b824c # 全部虚拟机物理磁盘文件存储 a$(ls -l | awk {print $NF} | cut -d. -f1) # 使用中的虚拟机物理磁盘文件 b$(xe vm-disk-list --multiple | grep uuid | awk {print $NF})printf "%s\n"…...
Golang——7、包与接口详解
包与接口详解 1、Golang包详解1.1、Golang中包的定义和介绍1.2、Golang包管理工具go mod1.3、Golang中自定义包1.4、Golang中使用第三包1.5、init函数 2、接口详解2.1、接口的定义2.2、空接口2.3、类型断言2.4、结构体值接收者和指针接收者实现接口的区别2.5、一个结构体实现多…...
