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,说明启用了严…...

(二)原型模式
原型的功能是将一个已经存在的对象作为源目标,其余对象都是通过这个源目标创建。发挥复制的作用就是原型模式的核心思想。 一、源型模式的定义 原型模式是指第二次创建对象可以通过复制已经存在的原型对象来实现,忽略对象创建过程中的其它细节。 📌 核心特点: 避免重复初…...

2025盘古石杯决赛【手机取证】
前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来,实在找不到,希望有大佬教一下我。 还有就会议时间,我感觉不是图片时间,因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...
什么是EULA和DPA
文章目录 EULA(End User License Agreement)DPA(Data Protection Agreement)一、定义与背景二、核心内容三、法律效力与责任四、实际应用与意义 EULA(End User License Agreement) 定义: EULA即…...
解决本地部署 SmolVLM2 大语言模型运行 flash-attn 报错
出现的问题 安装 flash-attn 会一直卡在 build 那一步或者运行报错 解决办法 是因为你安装的 flash-attn 版本没有对应上,所以报错,到 https://github.com/Dao-AILab/flash-attention/releases 下载对应版本,cu、torch、cp 的版本一定要对…...
【HTTP三个基础问题】
面试官您好!HTTP是超文本传输协议,是互联网上客户端和服务器之间传输超文本数据(比如文字、图片、音频、视频等)的核心协议,当前互联网应用最广泛的版本是HTTP1.1,它基于经典的C/S模型,也就是客…...

处理vxe-table 表尾数据是单独一个接口,表格tableData数据更新后,需要点击两下,表尾才是正确的
修改bug思路: 分别把 tabledata 和 表尾相关数据 console.log() 发现 更新数据先后顺序不对 settimeout延迟查询表格接口 ——测试可行 升级↑:async await 等接口返回后再开始下一个接口查询 ________________________________________________________…...
NPOI Excel用OLE对象的形式插入文件附件以及插入图片
static void Main(string[] args) {XlsWithObjData();Console.WriteLine("输出完成"); }static void XlsWithObjData() {// 创建工作簿和单元格,只有HSSFWorkbook,XSSFWorkbook不可以HSSFWorkbook workbook new HSSFWorkbook();HSSFSheet sheet (HSSFSheet)workboo…...

【从零开始学习JVM | 第四篇】类加载器和双亲委派机制(高频面试题)
前言: 双亲委派机制对于面试这块来说非常重要,在实际开发中也是经常遇见需要打破双亲委派的需求,今天我们一起来探索一下什么是双亲委派机制,在此之前我们先介绍一下类的加载器。 目录 编辑 前言: 类加载器 1. …...
从面试角度回答Android中ContentProvider启动原理
Android中ContentProvider原理的面试角度解析,分为已启动和未启动两种场景: 一、ContentProvider已启动的情况 1. 核心流程 触发条件:当其他组件(如Activity、Service)通过ContentR…...

五子棋测试用例
一.项目背景 1.1 项目简介 传统棋类文化的推广 五子棋是一种古老的棋类游戏,有着深厚的文化底蕴。通过将五子棋制作成网页游戏,可以让更多的人了解和接触到这一传统棋类文化。无论是国内还是国外的玩家,都可以通过网页五子棋感受到东方棋类…...