OpenCV相机标定与3D重建(43)用于计算矫正和重映射的变换函数initUndistortRectifyMap()的使用

news2025/1/10 18:00:16
  • 操作系统:ubuntu22.04
  • OpenCV版本:OpenCV4.9
  • IDE:Visual Studio Code
  • 编程语言:C++11

算法描述

计算畸变矫正和校正变换映射。

该函数计算联合的畸变矫正和校正变换,并以 remap 所需的地图形式表示结果。矫正后的图像看起来像是原始图像,仿佛它是使用 cameraMatrix = newCameraMatrix 和零畸变的相机捕获的一样。对于单目相机,newCameraMatrix 通常等于 cameraMatrix,或者可以通过 getOptimalNewCameraMatrix 计算以更好地控制缩放。对于立体相机,newCameraMatrix 通常设置为由 stereoRectify 计算得到的 P1 或 P2。

此外,这个新的相机在坐标空间中的方向根据 R 不同。例如,这有助于对齐立体相机的两个头,使得两幅图像上的极线变得水平并且具有相同的 y 坐标(对于水平对齐的立体相机而言)。

该函数实际上构建了用于 remap 的逆映射算法的地图。也就是说,对于目标图像(即矫正和校正后的图像)中的每个像素 (u, v),该函数计算源图像(即来自相机的原始图像)中对应的坐标。应用以下过程:
x ← ( u − c ′ x ) / f ′ x y ← ( v − c ′ y ) / f ′ y [ X   Y   W ] T ← R − 1 ⋅ [ x   y   1 ] T x ′ ← X / W y ′ ← Y / W r 2 ← x ′ 2 + y ′ 2 x ′ ′ ← x ′ 1 + k 1 r 2 + k 2 r 4 + k 3 r 6 1 + k 4 r 2 + k 5 r 4 + k 6 r 6 + 2 p 1 x ′ y ′ + p 2 ( r 2 + 2 x ′ 2 ) + s 1 r 2 + s 2 r 4 y ′ ′ ← y ′ 1 + k 1 r 2 + k 2 r 4 + k 3 r 6 1 + k 4 r 2 + k 5 r 4 + k 6 r 6 + p 1 ( r 2 + 2 y ′ 2 ) + 2 p 2 x ′ y ′ + s 3 r 2 + s 4 r 4 s [ x ′ ′ ′ y ′ ′ ′ 1 ] = [ R 33 ( τ x , τ y ) 0 − R 13 ( τ x , τ y ) 0 R 33 ( τ x , τ y ) − R 23 ( τ x , τ y ) 0 0 1 ] ⋅ R ( τ x , τ y ) ⋅ [ x ′ ′ y ′ ′ 1 ] m a p x ( u , v ) ← x ′ ′ ′ f x + c x m a p y ( u , v ) ← y ′ ′ ′ f y + c y \begin{array}{l} x \leftarrow (u - {c'}_x) / {f'}_x \\ y \leftarrow (v - {c'}_y) / {f'}_y \\ [X\,Y\,W]^T \leftarrow R^{-1} \cdot [x \, y \, 1]^T \\ x' \leftarrow X/W \\ y' \leftarrow Y/W \\ r^2 \leftarrow x'^2 + y'^2 \\ x'' \leftarrow x' \frac{1 + k_1 r^2 + k_2 r^4 + k_3 r^6}{1 + k_4 r^2 + k_5 r^4 + k_6 r^6} + 2p_1 x' y' + p_2(r^2 + 2 x'^2) + s_1 r^2 + s_2 r^4 \\ y'' \leftarrow y' \frac{1 + k_1 r^2 + k_2 r^4 + k_3 r^6}{1 + k_4 r^2 + k_5 r^4 + k_6 r^6} + p_1 (r^2 + 2 y'^2) + 2 p_2 x' y' + s_3 r^2 + s_4 r^4 \\ s \begin{bmatrix} x''' \\ y''' \\ 1 \end{bmatrix} = \begin{bmatrix} R_{33}(\tau_x, \tau_y) & 0 & -R_{13}(\tau_x, \tau_y) \\ 0 & R_{33}(\tau_x, \tau_y) & -R_{23}(\tau_x, \tau_y) \\ 0 & 0 & 1 \end{bmatrix} \cdot R(\tau_x, \tau_y) \cdot \begin{bmatrix} x'' \\ y'' \\ 1 \end{bmatrix} \\ map_x(u,v) \leftarrow x''' f_x + c_x \\ map_y(u,v) \leftarrow y''' f_y + c_y \end{array} x(ucx)/fxy(vcy)/fy[XYW]TR1[xy1]TxX/WyY/Wr2x′2+y′2x′′x1+k4r2+k5r4+k6r61+k1r2+k2r4+k3r6+2p1xy+p2(r2+2x′2)+s1r2+s2r4y′′y1+k4r2+k5r4+k6r61+k1r2+k2r4+k3r6+p1(r2+2y′2)+2p2xy+s3r2+s4r4s x′′′y′′′1 = R33(τx,τy)000R33(τx,τy)0R13(τx,τy)R23(τx,τy)1 R(τx,τy) x′′y′′1 mapx(u,v)x′′′fx+cxmapy(u,v)y′′′fy+cy

其中 (k1, k2, p1, p2[, k3[, k4, k5, k6[, s1, s2, s3, s4[, τx, τy]]]]) 是畸变系数。

对于立体相机,此函数会被调用两次:每次针对一个相机头,在 stereoRectify 之后调用,而 stereoRectify 又是在 stereoCalibrate 之后调用的。但如果立体相机未经过校准,仍然可以直接从基本矩阵使用 stereoRectifyUncalibrated 计算校正变换。对于每个相机,该函数以像素域中的单应性矩阵 H 而不是三维空间中的旋转矩阵 R 来计算校正变换。R 可以通过 H 按照以下方式计算:
R = cameraMatrix − 1 ⋅ H ⋅ cameraMatrix \texttt{R} = \texttt{cameraMatrix} ^{-1} \cdot \texttt{H} \cdot \texttt{cameraMatrix} R=cameraMatrix1HcameraMatrix
其中 cameraMatrix 可以任意选择。

函数原型


void cv::initUndistortRectifyMap	
(
	InputArray 	cameraMatrix,
	InputArray 	distCoeffs,
	InputArray 	R,
	InputArray 	newCameraMatrix,
	Size 	size,
	int 	m1type,
	OutputArray 	map1,
	OutputArray 	map2 
)		

参数

  • 参数cameraMatrix 输入相机矩阵 cameraMatrix = A = [ f x 0 c x 0 f y c y 0 0 1 ] \text{cameraMatrix} = A = \begin{bmatrix}f_x & 0 & c_x \\0 & f_y & c_y \\0 & 0 & 1\end{bmatrix} cameraMatrix=A= fx000fy0cxcy1
  • 参数distCoeffs 输入畸变系数向量 (k1, k2, p1, p2[, k3[, k4, k5, k6[, s1, s2, s3, s4[, τx, τy]]]]),包含 4、5、8、12 或 14 个元素。如果该向量为 NULL/空,则假设畸变系数为零。
  • 参数R 可选的对象空间中的校正变换(3x3 矩阵)。可以传递由 stereoRectify 计算得到的 R1 或 R2。如果该矩阵为空,则假定为单位变换。在 initUndistortRectifyMap 中,R 假设为单位矩阵。
  • 参数newCameraMatrix 新的相机矩阵 $ newCameraMatrix = A ′ = [ f x ′ 0 c x ′ 0 f y ′ c y ′ 0 0 1 ] \text{newCameraMatrix} = A' = \begin{bmatrix} f'_x & 0 & c'_x \\ 0 & f'_y & c'_y \\ 0 & 0 & 1 \end{bmatrix} newCameraMatrix=A= fx000fy0cxcy1
  • 参数size 矫正后图像的尺寸。
  • 参数m1type 第一个输出映射的类型,可以是 CV_32FC1, CV_32FC2 或 CV_16SC2,参见 convertMaps。
  • 参数map1 第一个输出映射。
  • 参数map2 第二个输出映射。

代码示例

#include <iostream>
#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;

int main()
{
    // 假设的相机矩阵和畸变系数
    Mat cameraMatrix = ( Mat_< double >( 3, 3 ) << 500, 0, 320, 0, 500, 240, 0, 0, 1 );
    Mat distCoeffs   = ( Mat_< double >( 5, 1 ) << 0.1, 0.05, -0.01, 0.005, 0 );

    // 假设的旋转矩阵 R 和新的相机矩阵 newCameraMatrix
    Mat R               = Mat::eye( 3, 3, CV_64F );  // 单位矩阵作为示例
    Mat newCameraMatrix = cameraMatrix.clone();

    // 图像尺寸
    Size imageSize( 640, 480 );

    // 定义输出映射类型
    int m1type = CV_32FC1;

    // 初始化矫正映射
    Mat map1, map2;
    initUndistortRectifyMap( cameraMatrix, distCoeffs, R, newCameraMatrix, imageSize, m1type, map1, map2 );

    cout << "Undistortion and rectification maps created." << endl;

    // 使用 remap 对图像进行矫正
    Mat originalImage = imread( "/media/dingxin/data/study/OpenCV/sources/images/remap.png" );  // 加载原始图像
    if ( originalImage.empty() )
    {
        cerr << "Error: Could not open or find the image!" << endl;
        return -1;
    }

    Mat undistortedImage;
    remap( originalImage, undistortedImage, map1, map2, INTER_LINEAR );

    // 显示结果
    imshow( "Original Image", originalImage );
    imshow( "Undistorted Image", undistortedImage );
    waitKey( 0 );

    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2274472.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

同步整流 MT6705 应用注意事项

MT6705 是用于反激式变换器的高性能45V 同步整流器。它兼容各种反激转换器类型。支持 DCM、CCM 和准谐振模式。MT6705集成了一个40V功率MOSFET&#xff0c;可以取代肖特基二极管&#xff0c;提高效率。MT6705 PCB 布局应遵循以下规则: 1、VCC 电容器: VCC 引脚必须放置电容,电容…

LLaMA-Factory web微调大模型并导出大模型

LLaMA-Factory 开源大模型如LLaMA&#xff0c;Qwen&#xff0c;Baichuan等主要都是使用通用数据进行训练而来&#xff0c;其对于不同下游的使用场景和垂直领域的效果有待进一步提升&#xff0c;衍生出了微调训练相关的需求&#xff0c;包含预训练&#xff08;pt&#xff09;&am…

Jenkins内修改allure报告名称

背景&#xff1a; 最近使用Jenkins搭建自动化测试环境时&#xff0c;使用Jenkins的allure插件生成的报告&#xff0c;一直显示默认ALLURE REPORT&#xff0c;想自定义成与项目关联的名称&#xff0c;如图所示&#xff0c;很明显自定义名称显得高大上些&#xff0c;之前…

RK3588平台开发系列讲解(系统篇)Linux Kconfig的语法

文章目录 一、什么是Kconfig二、config模块三、menuconfig四、menu 和 endmenu五、choice 和 endchoice六、source七、depends on八、default九、help十、逻辑表达式沉淀、分享、成长,让自己和他人都能有所收获!😄 一、什么是Kconfig Kconfig的语法及代码结构非常简单。本博…

Android原生开发同一局域网内利用socket通信进行数据传输

1、数据接收端代码如下&#xff0c;注意&#xff1a;socket 接收信息需要异步运行&#xff1a; // port 端口号自定义一个值&#xff0c;比如 8888&#xff0c;但需和发送端使用的端口号保持一致 ServerSocket serverSocket new ServerSocket(port); while (true) {//这里为了…

Elasticsearch学习(1) : 简介、索引库操作、文档操作、RestAPI、RestClient操作

目录 1.elasticsearch简介1.1.了解es1.2.倒排索引正向索引和倒排索引 1.3.es的一些概念:文档和字段&#xff1b;索引和映射&#xff1b;Mysql与ES1.4.安装es、kibana部署单点es部署kibanaIK分词器安装IK分词器与测试扩展与停用词词典总结 部署es集群 2.索引库操作2.1.mapping映…

Clickhouse基础(一)

操作命令&#xff1a; sudo clickhouse start sudo clickhouse restart sudo clickhouse status进入clickhouse clickhouse-client -mCREATE TABLE db_13.t_assist (modelId UInt64,taskId UInt64,testNo String,tdId UInt64,eventDay String,eventDaytime UInt64,eventBatch …

记录将springboot的jar包和lib分离,使用docker-compose部署

本文讲诉如何把jar里的lib依赖包独立出来&#xff0c;方便更新服务时&#xff0c;缩小jar的体积&#xff0c;下面以若依的system服务为例&#xff0c;配置中的路径请酌情修改&#xff0c;主要提供大致配置逻辑 第一步&#xff1a;修改项目的pom.xml&#xff0c;调整build的配…

【对象存储】-- s3:\\、s3n:\\、s3a:\\ 简介

目录 1. s3:\ 2. s3n:\ 3. s3a:\ 区别对比 总结 在 Hadoop 和大数据处理领域&#xff0c;s3:\\、s3n:\\ 和 s3a:\\ 是访问 Amazon S3 的不同文件系统实现方式。以下是它们的简要介绍、区别及应用场景&#xff1a; 1. s3:\ 全称&#xff1a;Hadoop S3 Native FileSystem。…

Springboot3.x工程创建及必要引用(基础篇)

下面从环境的安装和配置开始&#xff0c;到Springboot3.x工程创建&#xff0c;记录一下让完全没有基础的小白用户也能够开始自己的第一个项目。 准备 安装JDK环境&#xff08;这里最好安装JDK17及以上版本&#xff09;安装IntelliJ IDEA Ultimate工具&#xff08;可以从官网下…

腾讯云AI代码助手-公司职位分析AI助手

作品简介 腾讯云AI代码助手是一款智能工具&#xff0c;专注于为公司提供职位分析服务。通过自然语言处理和机器学习技术&#xff0c;它能快速解析职位描述&#xff0c;提取关键信息&#xff0c;并提供数据驱动的洞察&#xff0c;帮助公司优化招聘流程和职位设计。 技术架构 …

QML学习(八) Quick中的基础组件:Item,Rectangle,MouseArea说明及使用场景和使用方法

上一篇中我们从设计器里可以看到Qt Quick-Base中有几大基础组件&#xff0c;如下图&#xff0c;这篇文章先介绍下Item&#xff0c;Rectangle&#xff0c;MouseArea这三个的说明及使用场景和使用方法 Item Item 是 QML 中所有可视元素的基类&#xff0c;是一个非常基础和通用的…

宇航用VIRTEX5系列FPGA的动态刷新方法及实现

SRAM型FPGA在宇航领域有广泛的应用&#xff0c;为解决FPGA在空间环境中的单粒子翻转问题&#xff0c;增强设计的可靠性&#xff0c;本文介绍一种低成本的抗辐照解决方案。该方案从外置高可靠存储器中读取配置数据&#xff0c;通过定时刷新结合三模冗余的方式消除单粒子影响&…

03.MPLS静态LSP配置实验

MPLS静态LSP配置实验 1、实验环境2、基础配置开启全局mpls接口下开启mpls配置静态LSP配置FEC从1.1.1.1到3.3.3.3配置FEC从3.3.3.3到1.1.1.13、信息查看查看LFIB表(标签转发信息表)查看FIB表(转发信息表)查看详细FFIB表tracert lsp iptracert -vping lsp ip4、抓包验证1、实…

el-table表格合并某一列

需求&#xff1a;按照下图完成单元格合并&#xff0c;数据展示 可以看到科室列是需要合并的 并加背景色展示&#xff1b;具体代码如下&#xff1a; <el-tableref"tableA":data"tableDataList":header-cell-style"{ backgroundColor: #f2dcdb, col…

PostgreSQL学习笔记(二):PostgreSQL基本操作

PostgreSQL 是一个功能强大的开源关系型数据库管理系统 (RDBMS)&#xff0c;支持标准的 SQL 语法&#xff0c;并扩展了许多功能强大的操作语法. 数据类型 数值类型 数据类型描述存储大小示例值SMALLINT小范围整数&#xff0c;范围&#xff1a;-32,768 到 32,7672 字节-123INTE…

javaEE-网络编程4.TCP回显服务器

目录 TCP流套接字编程 一.API介绍 ServerSocket类 构造方法&#xff1a; ​编辑方法&#xff1a; Socket类 构造方法&#xff1a; 方法&#xff1a; 二、TCP连接 三、通过TCP实现回显服务器 TCP服务端&#xff1a; 1.创建Socket对象 2.构造方法 3.start方法 TCP客…

RIS智能无线电反射面:原理、应用与MATLAB代码示例

一、引言 随着无线通信技术的快速发展,人们对通信系统的容量、覆盖范围、能效以及安全性等方面的要求日益提高。传统的无线通信系统主要通过增加基站数量、提高发射功率和优化天线阵列等方式来提升性能,但这些方法面临着资源有限、能耗高和成本上升等挑战。因此,探索新的无线…

合并模型带来的更好性能

研究背景与问题提出 在人工智能领域&#xff0c;当需要处理多个不同任务时&#xff0c;有多种方式来运用模型资源。其中&#xff0c;合并多个微调模型是一种成本效益相对较高的做法&#xff0c;相较于托管多个专门针对不同任务设计的模型&#xff0c;能节省一定成本。然而&…

城市生命线安全综合监管平台

【落地产品&#xff0c;有需要可留言联系&#xff0c;支持项目合作或源码合作】 一、建设背景 以关于城市安全的重要论述为建设纲要&#xff0c;聚焦城市安全重点领域&#xff0c;围绕燃气爆炸、城市内涝、地下管线交互风险、第三方施工破坏、供水爆管、桥梁坍塌、道路塌陷七…