当前位置: 首页 > news >正文

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()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 从校准图案的多个视图中找到相机的内参和外参参数. cv::calibrateCamera 是 OpenCV 中用于相机标定的一个非常重要的函数。它通过一系列已知的世…...

Linux信号量的编程

一&#xff0c;用信号量来实现是父进程先进行&#xff0c;还是子进程先进性 信号量的没有P&#xff0c;V操作之前&#xff0c;我们不知道如何控制&#xff1a; #include <stdio.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h>…...

“Yaker,你可以全局配置插件环境变量!“

周四周四&#xff0c;Vme50(bushi 大家好&#xff0c;这里是疯狂超级牛&#xff08;功能上新版&#xff09; 经常有用户问 “牛牛如何为不同插件配置相同的变量值呢&#xff1f;” “能有一个一波搞定插件变量的方式就好了” 超级牛听到了广大用户的声音&#xff0c;默默地拿起…...

SAAS美容美发系统架构解析

随着技术的不断发展&#xff0c;SAAS&#xff08;Software as a Service&#xff0c;软件即服务&#xff09;模式在各个行业的应用逐渐深化&#xff0c;美容美发行业也不例外。传统的美容美发店面通常依赖纸质记录、手动操作和复杂的管理流程&#xff0c;而随着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文件&#xff0c;该文件会在连接之后自动生成&#xff0c;用于验证远程服务器的身份。 konwn_host和id_rsa&#xff0c;id_rsa.pub的关系 &#xff08;1&#xff09;konwn_host用于客户端验证远程服务…...

智慧防汛平台在城市生命线安全建设中的应用

随着城市化进程的加快&#xff0c;城市基础设施的复杂性和互联性不断增强&#xff0c;城市生命线的安全管理面临前所未有的挑战。智慧防汛平台作为城市生命线安全建设的重要组成部分&#xff0c;通过现代信息技术提升城市防汛应急管理的智能化水平&#xff0c;保障城市安全。 …...

python实现TCP Socket控制测试仪器

python实现TCP Socket控制测试仪器 说明前提条件代码 说明 本例是用python实现TCP Socket&#xff0c;最终目的是为了控制LCR电容测试仪器。 前提条件 测试仪器 配备了以太网接口&#xff0c;支持TCP/IP协议栈 用户可以通过IP地址和端口号连接到仪器&#xff0c;建立TCP通信…...

51c自动驾驶~合集38

我自己的原文哦~ https://blog.51cto.com/whaosoft/12358456 #GaussianPretrain 万能3D高斯预训练表示&#xff01;爆拉3D检测、Occ、高精地图等四大任务&#xff01; 受Tesla的技术的推动&#xff0c;越来越多的厂商开始走"纯视觉"的路线&#xff0c;多数方案还…...

电脑显示器拔插DVI线后副屏不显示

问题&#xff1a;台式机副屏显示器插拔DVI线后副屏无法检测到&#xff0c;不显示 其他现象&#xff1a;电脑设备管理器“显示适配器”中只有独显&#xff0c;未显示集显。 尝试方法&#xff1a; 1、 重新插拔并拧紧DVI线、更换DVI线、将DVI线替换为VGA线、调换DVI线及VGA线两…...

Bash脚本常用命令

1.Bash常用快捷键 2.通配符 3.Bash其他特殊符号 4.位置参数 5.预定义变量 6.常用变量比较 7.基础正则表达式 8.文件类型判断 9.文件权限判断 10.整数比较命令 11.字符串判断 其他常用参考&#xff1a; https://zhuanlan.zhihu.com/p/748857250...

《Unity Shader 入门精要》高级纹理

立方体纹理 图形学中&#xff0c;立方体纹理&#xff08;Cubemap&#xff09;是环境映射&#xff08;Environment Mapping&#xff09;的一种实现方法。环境映射可以模拟物体周围的环境&#xff0c;而使用了环境映射的物体可以看起来像镀了层金属一样反射出周围的环境。 对立…...

vue3实现自定义导航菜单

一、创建项目 1. 打开HBuilder X 图1 2. 新建一个空项目 文件->新建->项目->uni-app 填写项目名称&#xff1a;vue3demo 选择项目存放目录&#xff1a;D:/HBuilderProjects 一定要注意vue的版本&#xff0c;当前选择的版本为vue3 图2 点击“创建”之后进入项目界面 图…...

[2024年3月10日]第15届蓝桥杯青少组stema选拔赛C++中高级(第二子卷、编程题(2))

方法一&#xff08;string&#xff09;&#xff1a; #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&#xff1a;什么是DevOps DevOps是十几年前&#xff0c;在互联网比较火的词&#xff0c;实际上就是ci/cd平台的另外一种说法&#xff0c;核心是说打破研发&#xff0c;测试&#xff0c;运维的边界&#xff0c;能够将整个产品开发的流程快速循环起来&#xff0c;随时可发版&a…...

从单机缓存到分布式缓存那些事

作者&#xff1a;秦怀 1 缓存前世今生 1.1 故事从硬件开始 Cache 一词来源于 1967 年的一篇电子工程期刊论文。其作者将法语词“cache”赋予“safekeeping storage”的涵义&#xff0c;用于电脑工程领域。当时没有 Cache&#xff0c;CPU 和内存都很慢&#xff0c;CPU 直接访…...

[Ubuntu20] Gym入门,Mujoco

OpenAI Gym是 OpenAI 出的研究强化学习算法的 toolkit&#xff0c;对于强化学习算法来说&#xff0c;大部分的论文环境都已经被 OpenAI 的 gym 环境集成&#xff0c;我们可以很便利的使用该工程来测试自己的强化学习算法&#xff0c;与他人的算法做一个对比。 Gym 官网 Github…...

Linux(ubuntu)系统的一些基本操作和命令(持续更新)

操作&#xff1a; Ctrl Alt T&#xff08;打开命令终端&#xff09; Ctrl Shift &#xff08;放大命令终端窗口&#xff09; Ctrl c&#xff08;退出当前在终端运行的程序&#xff09; 在命令终端窗口按Tab键可以补全要写的命令 命令&#xff1a; pwd&#xff08;查…...

【NLP高频面题 - 分布式训练】ZeRO1、ZeRO2、ZeRO3分别做了哪些优化?

【NLP高频面题 - 分布式训练】ZeRO1、ZeRO2、ZeRO3分别做了哪些优化&#xff1f; 重要性&#xff1a;★★ NLP Github 项目&#xff1a; NLP 项目实践&#xff1a;fasterai/nlp-project-practice 介绍&#xff1a;该仓库围绕着 NLP 任务模型的设计、训练、优化、部署和应用&am…...

android 安全sdk相关

前述 在网上有看到许多android安全sdk相关的内容&#xff0c;有重复的也有比较新鲜的内容&#xff0c;这里做一个整体的合集&#xff0c;以及后续又看到一些比较新的东西会一起放在这里。 android内sdk目前可以分为以下几个部分&#xff08;有一些部分可能会存在一些重合&#…...

React Native 开发环境搭建(全平台详解)

React Native 开发环境搭建&#xff08;全平台详解&#xff09; 在开始使用 React Native 开发移动应用之前&#xff0c;正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南&#xff0c;涵盖 macOS 和 Windows 平台的配置步骤&#xff0c;如何在 Android 和 iOS…...

【WiFi帧结构】

文章目录 帧结构MAC头部管理帧 帧结构 Wi-Fi的帧分为三部分组成&#xff1a;MAC头部frame bodyFCS&#xff0c;其中MAC是固定格式的&#xff0c;frame body是可变长度。 MAC头部有frame control&#xff0c;duration&#xff0c;address1&#xff0c;address2&#xff0c;addre…...

安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件

在选煤厂、化工厂、钢铁厂等过程生产型企业&#xff0c;其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进&#xff0c;需提前预防假检、错检、漏检&#xff0c;推动智慧生产运维系统数据的流动和现场赋能应用。同时&#xff0c;…...

零基础设计模式——行为型模式 - 责任链模式

第四部分&#xff1a;行为型模式 - 责任链模式 (Chain of Responsibility Pattern) 欢迎来到行为型模式的学习&#xff01;行为型模式关注对象之间的职责分配、算法封装和对象间的交互。我们将学习的第一个行为型模式是责任链模式。 核心思想&#xff1a;使多个对象都有机会处…...

uniapp中使用aixos 报错

问题&#xff1a; 在uniapp中使用aixos&#xff0c;运行后报如下错误&#xff1a; AxiosError: There is no suitable adapter to dispatch the request since : - adapter xhr is not supported by the environment - adapter http is not available in the build 解决方案&…...

华硕a豆14 Air香氛版,美学与科技的馨香融合

在快节奏的现代生活中&#xff0c;我们渴望一个能激发创想、愉悦感官的工作与生活伙伴&#xff0c;它不仅是冰冷的科技工具&#xff0c;更能触动我们内心深处的细腻情感。正是在这样的期许下&#xff0c;华硕a豆14 Air香氛版翩然而至&#xff0c;它以一种前所未有的方式&#x…...

A2A JS SDK 完整教程:快速入门指南

目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库&#xff…...

Go 并发编程基础:通道(Channel)的使用

在 Go 中&#xff0c;Channel 是 Goroutine 之间通信的核心机制。它提供了一个线程安全的通信方式&#xff0c;用于在多个 Goroutine 之间传递数据&#xff0c;从而实现高效的并发编程。 本章将介绍 Channel 的基本概念、用法、缓冲、关闭机制以及 select 的使用。 一、Channel…...

C++_哈希表

本篇文章是对C学习的哈希表部分的学习分享 相信一定会对你有所帮助~ 那咱们废话不多说&#xff0c;直接开始吧&#xff01; 一、基础概念 1. 哈希核心思想&#xff1a; 哈希函数的作用&#xff1a;通过此函数建立一个Key与存储位置之间的映射关系。理想目标&#xff1a;实现…...

在鸿蒙HarmonyOS 5中使用DevEco Studio实现指南针功能

指南针功能是许多位置服务应用的基础功能之一。下面我将详细介绍如何在HarmonyOS 5中使用DevEco Studio实现指南针功能。 1. 开发环境准备 确保已安装DevEco Studio 3.1或更高版本确保项目使用的是HarmonyOS 5.0 SDK在项目的module.json5中配置必要的权限 2. 权限配置 在mo…...