OpenCV相机标定与3D重建(43)用于计算矫正和重映射的变换函数initUndistortRectifyMap()的使用
- 操作系统: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←(u−c′x)/f′xy←(v−c′y)/f′y[XYW]T←R−1⋅[xy1]Tx′←X/Wy′←Y/Wr2←x′2+y′2x′′←x′1+k4r2+k5r4+k6r61+k1r2+k2r4+k3r6+2p1x′y′+p2(r2+2x′2)+s1r2+s2r4y′′←y′1+k4r2+k5r4+k6r61+k1r2+k2r4+k3r6+p1(r2+2y′2)+2p2x′y′+s3r2+s4r4s x′′′y′′′1 = R33(τx,τy)000R33(τx,τy)0−R13(τ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=cameraMatrix−1⋅H⋅cameraMatrix
其中 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′= fx′000fy′0cx′cy′1 。
- 参数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 和新的相机矩阵 newCameraMatrixMat 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;
}
相关文章:
OpenCV相机标定与3D重建(43)用于计算矫正和重映射的变换函数initUndistortRectifyMap()的使用
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 计算畸变矫正和校正变换映射。 该函数计算联合的畸变矫正和校正变换,并以 remap 所需的地图形式表示结果。矫正后的图像看起来像是原…...
ansible-api分析(Inventory)
一. 简述: 通过ansible 实现系统初始化功能, 为和平台嵌入, 需要通过ansible的api进行功能实现。 准确来说,ansible并没有纯粹的外部接入api功能, 只是官方提供了原生类,用于继承接入,从而实现a…...
使用FDBatchMove的几个问题总结
FDBatchMove的使用,搞了好久,今天终于解决了自己的几个问题,网上很少例子,记录一下,仅做参考。 1、使用firedac导入excel表,需要access database驱动,不要使用2007,一定要使用2010&…...
人工智能前沿探讨:从Transformer架构到机器意识与迁移学习的应用
Transformer架构可能为理解人脑的运作提供新的视角 Transformer架构与人脑的相似之处是一个颇受关注的话题。虽然人脑和Transformer架构之间有许多差异,但也有一些相似之处,值得我们探讨。 相似之处: 注意力机制: Transformer架构中的注意力机制是它的…...
Flutter Web 中文字体显示异常问题
flutter web 在中文使用粗体的时候发现了两个问题 一个字的笔画颜色不相同带有 ‘口’的字 这个口由于太粗出现了实体闭合的情况 解决方案 替换字体 对于这个问题解决的办法只有替换中文字体库,因为只有粗体才有问题,所以只需要添加粗体字体即可。我…...
【Nginx】设置https和http同时使用同一个端口访问
以下是一个同时使用 HTTP 和 HTTPS 并通过 8070 端口的配置示例: server {listen 8070;server_name your_domain.com;location / {root /var/www/html;index index.html;} }server {listen 8070 ssl;server_name your_domain.com;# SSL 证书和私钥的路径ssl_certif…...
clickhouse query_log 常用查询语句
1、查询一段时间耗时超过3秒的语句。 SELECT* FROMsystem.query_log WHEREquery_duration_ms > 30000AND event_time > 2024-12-31 15:50:00 AND event_time < 2024-12-31 17:50:00 ORDER BYevent_time desc;2、查询一段时间报错的语句 SELECT* FROMsystem.query_lo…...
【Linux】RPMSG通讯协议介绍
RPMSG协议通讯协议介绍 RPMSG,全称Remote processor Messaging。是一种核间通讯协议。在Linux Kernel中,已经内置了RPMSG。 Linux RPMSG基于共享内存,利用RPMSG可以高效的实现核间通信。比如Linux与FreeRTOS、Linux与Android,都可…...
Idea(中文版) 项目结构/基本设置/设计背景
目录 1. Idea 项目结构 1.1 新建项目 1.2 新建项目的模块 1.3 新建项目模块的包 1.4 新建项目模块包的类 2. 基本设置 2.1 设置主题 2.2 设置字体 2.3 设置注释 2.4 自动导包 2.5 忽略大小写 2.6 设置背景图片 3. 项目与模块操作 3.1 修改类名 3.2 关闭项目 1. I…...
深入理解 Android 中的 ActivityInfo
深入理解 Android 中的 ActivityInfo 在 Android 开发中,ActivityInfo 是一个非常重要的类,它包含了关于 Activity 的元信息。这些信息通常是从 AndroidManifest.xml 文件中提取的,开发者可以通过 ActivityInfo 类来获取和操作这些信息。本文…...
Linux初识——基本指令
我们在linux下输入各种指令,其实就相当于在windows中的相关操作,比如双击,新建文件夹等。 以下是相关基本指令基本用法 一.ls(显示当前目录下的所有文件和目录) 那如何显示当前目录(我们所在的位置&…...
c/c++ 里的进程间通信 , 管道 pipe 编程举例
(1)以下是一个网上的使用 pipe 编程的范例: #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <sys/types.h> #include <sys/wait.h>int main() {int pipefd…...
【C++笔记】红黑树(RBTree)深度剖析和AVL树的对比分析
【C笔记】红黑树(RBTree)深度剖析和AVL树的对比分析 🔥个人主页:大白的编程日记 🔥专栏:C笔记 文章目录 【C笔记】红黑树(RBTree)深度剖析和AVL树的对比分析前言一.红黑树的定义1.1 红黑树的概念1.2红黑树的规则1.3 红黑树对比A…...
Pytorch初学
创建虚拟环境 python控制台,jupyter notebook,python文件运行的差异,后续结合使用三者。 jupter主要可以对代码进行分割单独运行,主要做一些探索性工作。 数据集的常见存储模式 1、以标签命名图像。 2、单独存储图像的地址。 加载数据集…...
Golang学习笔记_20——error
Golang学习笔记_17——方法 Golang学习笔记_18——接口 Golang学习笔记_19——Stringer 文章目录 error1. 接口2. 创建3. 自定义错误4. 处理错误5. 实现Error接口 源码 error 在Go语言中,error 是一个内建的接口类型,用于表示和处理错误情况。它是Go语言…...
基于Vite+TS初始项目 | 不断更新
1 创建项目 1.1 初始化项目 # 创建项目 pnpm create vite# 使用vue-ts模板创建项目 pnpm create vite xyz-vue-app-ts --template vue-ts1.2 添加ts类型检查命令 添加 "type-check" 类型检查命令 {"name": "xyz-vue-app-ts-test","scri…...
R语言装环境Gcc报错以及scater包的安装
error: ‘timespec_get’ has not been declared in ‘::’ 80 | using ::timespec_get; 在conda 的虚拟环境中升级gcc的版本 conda install -c conda-forge gcc11 gxx11终极方法,在R的最新版本和环境下装啥都能成功!! 比如beyondcell的方法…...
关于量子神经网络的思考
其实在写这篇文章之前想了很多,主要是想法太超前,有可能颠覆未来机器智能行业甚至是影响世界。 1、计算机的历史 计算机的历史可以追溯到20世纪中叶,最早的电子计算机如ENIAC和EDVAC采用了冯诺依曼架构(John von Neumann Archit…...
注册中心如何选型?Eureka、Zookeeper、Nacos怎么选
这是小卷对分布式系统架构学习的第9篇文章,第8篇时只回答了注册中心的工作原理的内容,面试官的第二个问题还没回答,今天再来讲讲各个注册中心的原理,以及区别,最后如何进行选型 上一篇文章:如何设计一个注册…...
使用 Conda创建新的环境遇到的问题
下载速度很慢 1、更新 conda update -n base -c defaults conda2、清理缓存 conda clean --all解决方法 方法 1:关闭严格的渠道优先级 检查是否开启了严格渠道优先级: conda config --show channel_priority 如果返回 strict,说明启用了严…...
深入浅出Asp.Net Core MVC应用开发系列-AspNetCore中的日志记录
ASP.NET Core 是一个跨平台的开源框架,用于在 Windows、macOS 或 Linux 上生成基于云的新式 Web 应用。 ASP.NET Core 中的日志记录 .NET 通过 ILogger API 支持高性能结构化日志记录,以帮助监视应用程序行为和诊断问题。 可以通过配置不同的记录提供程…...
golang循环变量捕获问题
在 Go 语言中,当在循环中启动协程(goroutine)时,如果在协程闭包中直接引用循环变量,可能会遇到一个常见的陷阱 - 循环变量捕获问题。让我详细解释一下: 问题背景 看这个代码片段: fo…...
PHP和Node.js哪个更爽?
先说结论,rust完胜。 php:laravel,swoole,webman,最开始在苏宁的时候写了几年php,当时觉得php真的是世界上最好的语言,因为当初活在舒适圈里,不愿意跳出来,就好比当初活在…...
STM32F4基本定时器使用和原理详解
STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...
[ICLR 2022]How Much Can CLIP Benefit Vision-and-Language Tasks?
论文网址:pdf 英文是纯手打的!论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误,若有发现欢迎评论指正!文章偏向于笔记,谨慎食用 目录 1. 心得 2. 论文逐段精读 2.1. Abstract 2…...
Linux云原生安全:零信任架构与机密计算
Linux云原生安全:零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言:云原生安全的范式革命 随着云原生技术的普及,安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测,到2025年,零信任架构将成为超…...
TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案
一、TRS收益互换的本质与业务逻辑 (一)概念解析 TRS(Total Return Swap)收益互换是一种金融衍生工具,指交易双方约定在未来一定期限内,基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...
Reasoning over Uncertain Text by Generative Large Language Models
https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829 1. 概述 文本中的不确定性在许多语境中传达,从日常对话到特定领域的文档(例如医学文档)(Heritage 2013;Landmark、Gulbrandsen 和 Svenevei…...
HashMap中的put方法执行流程(流程图)
1 put操作整体流程 HashMap 的 put 操作是其最核心的功能之一。在 JDK 1.8 及以后版本中,其主要逻辑封装在 putVal 这个内部方法中。整个过程大致如下: 初始判断与哈希计算: 首先,putVal 方法会检查当前的 table(也就…...
spring Security对RBAC及其ABAC的支持使用
RBAC (基于角色的访问控制) RBAC (Role-Based Access Control) 是 Spring Security 中最常用的权限模型,它将权限分配给角色,再将角色分配给用户。 RBAC 核心实现 1. 数据库设计 users roles permissions ------- ------…...
