OpenCV相机标定与3D重建(60)用于立体校正的函数stereoRectify()的使用
- 操作系统:ubuntu22.04
- OpenCV版本:OpenCV4.9
- IDE:Visual Studio Code
- 编程语言:C++11
算法描述
为已校准的立体相机的每个头计算校正变换。
cv::stereoRectify 是 OpenCV 中用于立体校正的函数,它基于已知的相机参数和相对位置(通过 cv::stereoCalibrate 或其他方法获得),计算出两个相机的投影矩阵和重映射变换,使得从两个相机获取的图像能够被矫正为仿佛它们是并排且光学轴平行的状态。这样做的目的是为了简化后续的视差图计算。
函数原型
void cv::stereoRectify
(InputArray cameraMatrix1,InputArray distCoeffs1,InputArray cameraMatrix2,InputArray distCoeffs2,Size imageSize,InputArray R,InputArray T,OutputArray R1,OutputArray R2,OutputArray P1,OutputArray P2,OutputArray Q,int flags = CALIB_ZERO_DISPARITY,double alpha = -1,Size newImageSize = Size(),Rect * validPixROI1 = 0,Rect * validPixROI2 = 0
)
参数
- 参数cameraMatrix1:第一个相机的内参矩阵。
- 参数distCoeffs1:第一个相机的畸变参数。
- 参数cameraMatrix2:第二个相机的内参矩阵。
- 参数distCoeffs2:第二个相机的畸变参数。
- 参数imageSize:用于立体校准的图像尺寸。
- 参数R:从第一个相机坐标系到第二个相机坐标系的旋转矩阵,详见 stereoCalibrate。
- 参数T:从第一个相机坐标系到第二个相机坐标系的平移向量,详见 stereoCalibrate。
- 参数R1:第一个相机的输出3x3校正变换(旋转矩阵)。该矩阵将未校正的第一个相机坐标系中的点转换为校正后的第一个相机坐标系中的点。更技术性地说,它执行了从未校正的第一个相机坐标系到校正后的第一个相机坐标系的基础变换。
- 参数R2:第二个相机的输出3x3校正变换(旋转矩阵)。该矩阵将未校正的第二个相机坐标系中的点转换为校正后的第二个相机坐标系中的点。同样地,它执行了从未校正的第二个相机坐标系到校正后的第二个相机坐标系的基础变换。
- 参数P1:第一个相机在新的(校正后)坐标系中的输出3x4投影矩阵,即它将校正后的第一个相机坐标系中的点投影到校正后的第一个相机的图像中。
- 参数P2:第二个相机在新的(校正后)坐标系中的输出3x4投影矩阵,即它将校正后的第一个相机坐标系中的点投影到校正后的第二个相机的图像中。
- 参数Q:输出4×4视差到深度映射矩阵(见 reprojectImageTo3D)。
- 参数flags:操作标志,可以是零或 CALIB_ZERO_DISPARITY。如果设置了该标志,则函数会使每个相机的主点在校正后的视图中具有相同的像素坐标。如果没有设置该标志,函数可能会沿水平或垂直方向(取决于极线的方向)移动图像,以最大化有用图像区域。
- 参数alpha:自由缩放参数。如果它是 -1 或未指定,函数将执行默认缩放。否则,参数应在 0 和 1 之间。alpha=0 表示校正后的图像被缩放和移动,使得只有有效的像素可见(校正后没有黑色区域)。alpha=1 表示校正后的图像被减少和移动,使得来自原始图像的所有像素都保留在校正后的图像中(不丢失源图像像素)。任何中间值都会产生这两个极端情况之间的中间结果。
- 参数newImageSize:校正后的新图像分辨率。应该传递给 initUndistortRectifyMap(见 OpenCV 示例目录中的 stereo_calib.cpp 样本)。当传递 (0,0)(默认值)时,它被设置为原始 imageSize。设置为更大的值可以帮助保留原始图像中的细节,尤其是在存在较大径向畸变的情况下。
- 参数validPixROI1:可选输出矩形,在校正后的图像中包含所有有效像素的区域。如果 alpha=0,则 ROI 覆盖整个图像。否则,它们可能较小(见下图)。
- 参数validPixROI2:同上,适用于第二个相机。
该函数计算每个相机的旋转矩阵,这些矩阵(虚拟地)使两个相机的图像平面成为同一平面。因此,这使得所有的极线平行,从而简化了密集立体对应问题。函数以 stereoCalibrate 计算的矩阵作为输入,并提供两个旋转矩阵以及两个新坐标系中的投影矩阵作为输出。根据相机的相对位置,函数区分以下两种情况:
水平立体
第一个和第二个相机视图主要沿 x 轴相对偏移(可能有小的垂直偏移)。在校正后的图像中,左右相机中的对应极线是水平的并且具有相同的 y 坐标。P1 和 P2 的形式如下:
P1 = [ f 0 c x 1 0 0 f c y 0 0 0 1 0 ] \texttt{P1} = \begin{bmatrix} f & 0 & cx_1 & 0 \\ 0 & f & cy & 0 \\ 0 & 0 & 1 & 0 \end{bmatrix} P1= f000f0cx1cy1000
P2 = [ f 0 c x 2 T x ⋅ f 0 f c y 0 0 0 1 0 ] , \texttt{P2} = \begin{bmatrix} f & 0 & cx_2 & T_x \cdot f \\ 0 & f & cy & 0 \\ 0 & 0 & 1 & 0 \end{bmatrix} , P2= f000f0cx2cy1Tx⋅f00 ,
Q = [ 1 0 0 − c x 1 0 1 0 − c y 0 0 0 f 0 0 − 1 T x c x 1 − c x 2 T x ] \texttt{Q} = \begin{bmatrix} 1 & 0 & 0 & -cx_1 \\ 0 & 1 & 0 & -cy \\ 0 & 0 & 0 & f \\ 0 & 0 & -\frac{1}{T_x} & \frac{cx_1 - cx_2}{T_x} \end{bmatrix} Q= 10000100000−Tx1−cx1−cyfTxcx1−cx2
其中 Tx 是相机之间的水平偏移,如果设置了 CALIB_ZERO_DISPARITY,则cx1=cx2。
垂直立体
第一个和第二个相机视图主要沿垂直方向相对偏移(可能有一点水平偏移)。在校正后的图像中,极线是垂直的并且具有相同的 x 坐标。P1 和 P2 的形式如下:
P1 = [ f 0 c x 0 0 f c y 1 0 0 0 1 0 ] \texttt{P1} = \begin{bmatrix} f & 0 & cx & 0 \\ 0 & f & cy_1 & 0 \\ 0 & 0 & 1 & 0 \end{bmatrix} P1= f000f0cxcy11000
P2 = [ f 0 c x 0 0 f c y 2 T y ⋅ f 0 0 1 0 ] , \texttt{P2} = \begin{bmatrix} f & 0 & cx & 0 \\ 0 & f & cy_2 & T_y \cdot f \\ 0 & 0 & 1 & 0 \end{bmatrix}, P2= f000f0cxcy210Ty⋅f0 ,
Q = [ 1 0 0 − c x 0 1 0 − c y 1 0 0 0 f 0 0 − 1 T y c y 1 − c y 2 T y ] \texttt{Q} = \begin{bmatrix} 1 & 0 & 0 & -cx \\ 0 & 1 & 0 & -cy_1 \\ 0 & 0 & 0 & f \\ 0 & 0 & -\frac{1}{T_y} & \frac{cy_1 - cy_2}{T_y} \end{bmatrix} Q= 10000100000−Ty1−cx−cy1fTycy1−cy2
其中 Ty 是相机之间的垂直偏移,如果设置了 CALIB_ZERO_DISPARITY,则cy1=cy2。
可以看到,P1 和 P2 的前三列实际上会成为新的“校正”相机矩阵。这些矩阵连同 R1 和 R2 可以传递给 initUndistortRectifyMap 来初始化每个相机的校正映射。
示例截图
下面是来自 stereo_calib.cpp 示例的截图。一些红色水平线通过对应的图像区域,这意味着图像已经很好地进行了校正,这是大多数立体对应算法所依赖的。绿色矩形是 roi1 和 roi2。可以看到,它们内部都是有效的像素。
代码示例
#include <iostream>
#include <opencv2/opencv.hpp>
#include <vector>using namespace cv;
using namespace std;// 生成测试图像函数
void generateTestImages( Size imageSize, Mat& img1, Mat& img2 )
{img1 = Mat::zeros( imageSize, CV_8UC3 );img2 = Mat::zeros( imageSize, CV_8UC3 );// 在第一张图像上画水平线,在第二张图像上画稍微偏移的水平线模拟立体图像for ( int y = 50; y < imageSize.height; y += 50 ){line( img1, Point( 0, y ), Point( imageSize.width, y ), Scalar( 0, 255, 0 ), 2 );line( img2, Point( 0, y + 10 ), Point( imageSize.width, y + 10 ), Scalar( 0, 255, 0 ), 2 );}
}int main()
{// 假设我们已经有以下数据(来自 stereoCalibrate 或其他来源)Mat cameraMatrix1 = ( Mat_< double >( 3, 3 ) << 520.9, 0, 325.1, 0, 521.0, 249.7, 0, 0, 1 );Mat cameraMatrix2 = ( Mat_< double >( 3, 3 ) << 520.9, 0, 325.1, 0, 521.0, 249.7, 0, 0, 1 );Mat distCoeffs1 = Mat::zeros( 5, 1, CV_64F ); // 简化的畸变系数模型Mat distCoeffs2 = Mat::zeros( 5, 1, CV_64F );// 假定的旋转和平移矩阵(根据实际情况调整)Mat R = ( Mat_< double >( 3, 3 ) << 0.999, 0.001, -0.044, -0.002, 0.998, 0.061, 0.044, -0.061, 0.998 );Mat T = ( Mat_< double >( 3, 1 ) << 60.0, 0.0, 0.0 ); // 假设两个相机沿X轴平移了60个单位Size imageSize( 640, 480 ); // 图像尺寸// 输出变量Mat R1, R2; // 校正后的旋转矩阵Mat P1, P2; // 新的投影矩阵Mat Q; // 视差到深度映射矩阵Rect validPixROI1, validPixROI2; // 有效像素区域// 操作标志和自由缩放参数int flags = CALIB_ZERO_DISPARITY;double alpha = -1;Size newImageSize = imageSize; // 使用原始图像尺寸// 执行立体校正stereoRectify( cameraMatrix1, distCoeffs1, cameraMatrix2, distCoeffs2, imageSize, R, T, R1, R2, P1, P2, Q, flags, alpha, newImageSize, &validPixROI1, &validPixROI2 );cout << "Rectification matrices for the first camera:\n" << R1 << endl;cout << "Rectification matrices for the second camera:\n" << R2 << endl;cout << "Projection matrix for the first camera:\n" << P1 << endl;cout << "Projection matrix for the second camera:\n" << P2 << endl;cout << "Disparity-to-depth mapping matrix:\n" << Q << endl;// 初始化重映射Mat map1x, map1y, map2x, map2y;initUndistortRectifyMap( cameraMatrix1, distCoeffs1, R1, P1, newImageSize, CV_32FC1, map1x, map1y );initUndistortRectifyMap( cameraMatrix2, distCoeffs2, R2, P2, newImageSize, CV_32FC1, map2x, map2y );// 生成一对测试图像Mat img1, img2;generateTestImages( imageSize, img1, img2 );// 应用重映射Mat rectifiedImg1, rectifiedImg2;remap( img1, rectifiedImg1, map1x, map1y, INTER_LINEAR );remap( img2, rectifiedImg2, map2x, map2y, INTER_LINEAR );// 显示结果imshow( "Original Image 1", img1 );imshow( "Original Image 2", img2 );imshow( "Rectified Image 1", rectifiedImg1 );imshow( "Rectified Image 2", rectifiedImg2 );waitKey( 0 ); // 等待按键关闭窗口return 0;
}
运行结果
命令行输出:
Rectification matrices for the first camera:
[0.9990327505785522, 0.002838302200161476, -0.0438806029137316;-0.001498542304358349, 0.9995325828506972, 0.03053473744403527;0.04394675917987673, -0.03043944579710149, 0.9985700388541362]
Rectification matrices for the second camera:
[1, 2.782197548109867e-17, -9.101507439329915e-16;-4.437342568756724e-17, 0.9995349355631407, -0.03049446816700398;9.047190730013251e-16, 0.03049446816700397, 0.9995349355631405]
Projection matrix for the first camera:
[521, 0, 340.8940467834473, 0;0, 521, 249.6826610565186, 0;0, 0, 1, 0]
Projection matrix for the second camera:
[521, 0, 340.8940467834473, 31260;0, 521, 249.6826610565186, 0;0, 0, 1, 0]
Disparity-to-depth mapping matrix:
[1, 0, 0, -340.8940467834473;0, 1, 0, -249.6826610565186;0, 0, 0, 521;0, 0, -0.01666666666666667, 0]
相关文章:

OpenCV相机标定与3D重建(60)用于立体校正的函数stereoRectify()的使用
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 为已校准的立体相机的每个头计算校正变换。 cv::stereoRectify 是 OpenCV 中用于立体校正的函数,它基于已知的相机参数和相对位置&am…...
Android wifi列表中去自身的热点
Android wifi列表中去自身的热点 一、前言 Android wifi列表中能搜索到自身的热点wifi? 正常手机上都不会出现这个问题;可能是系统底层已经做了过滤处理。 现实开发中Android设备的Wifi能搜索到自身热点也可能会存在。 比如基于两个单独的wifi双模组硬…...

Windows环境本地配置pyspark环境详细教程
目录 一、背景简记二、本地单机spark环境配置详细步骤第一步:python环境安装第二步:安装jdk及配置环境变量安装包下载安装环境变量配置 第三步:安装Spark安装包下载安装配置环境变量 第四步:安装hadoop安装包下载安装配置环境变量…...

《自动驾驶与机器人中的SLAM技术》ch9:自动驾驶车辆的离线地图构建
目录 1 点云建图的流程 2 前端实现 2.1 前端流程 2.2 前端结果 3 后端位姿图优化与异常值剔除 3.1 两阶段优化流程 3.2 优化结果 ① 第一阶段优化结果 ② 第二阶段优化结果 4 回环检测 4.1 回环检测流程 ① 遍历第一阶段优化轨迹中的关键帧。 ② 并发计算候选回环对…...

IP属地会随着人的移动而改变吗
在当今数字化时代,互联网已成为人们生活中不可或缺的一部分。无论是社交媒体的日常互动,还是在线购物、远程工作,IP地址作为网络身份的重要标识,扮演着举足轻重的角色。随着移动互联网技术的飞速发展,人们越来越多地在…...

openharmony应用开发快速入门
开发准备 本文档适用于OpenHarmony应用开发的初学者。通过构建一个简单的具有页面跳转/返回功能的应用(如下图所示),快速了解工程目录的主要文件,熟悉OpenHarmony应用开发流程。 在开始之前,您需要了解有关OpenHarmon…...

USB3020任意波形发生器4路16位同步模拟量输出卡1MS/s频率 阿尔泰科技
信息社会的发展,在很大程度上取决于信息与信号处理技术的先进性。数字信号处理技术的出现改变了信息 与信号处理技术的整个面貌,而数据采集作为数字信号处理的必不可少的前期工作在整个数字系统中起到关键 性、乃至决定性的作用,其应用已经深…...

云消息队列 Kafka 版 V3 系列荣获信通院“云原生技术创新标杆案例”
2024 年 12 月 24 日,由中国信息通信研究院(以下简称“中国信通院”)主办的“2025 中国信通院深度观察报告会:算力互联网分论坛”,在北京隆重召开。本次论坛以“算力互联网 新质生产力”为主题,全面展示中国…...

linux下的NFS和FTP部署
目录 NFS应用场景架构通信原理部署权限认证Kerberos5其他认证方式 命令serverclient查看测试系统重启后自动挂载 NFS 共享 高可用实现 FTP对比一些ftp服务器1. **vsftpd (Very Secure FTP Daemon)**2. **ProFTPD (Professional FTP Daemon)**3. **Pure-FTPd**4. **WU-FTPD (Was…...
JS Clipboard API
1.作用 在web应用程序中,当用户授予了相应的权限,Clipboard API 就能实现系统剪切板的复制、粘贴和剪切功能。系统剪切板暴露在Navigator.clipboard 中。 2.例子 window.onload () > {// 监听用户的复制事件document.addEventListener(copy, (e) …...

MySQL中大量数据优化方案
文章目录 1 大量数据优化1.1 引言1.2 评估表数据体量1.2.1 表容量1.2.2 磁盘空间1.2.3 实例容量 1.3 出现问题的原因1.4 解决问题1.4.1 数据表分区1.4.1.1 简介1.4.1.2 分区限制和执行计划1.4.1.3 分区表的索引1.4.1.4 为什么分区键必须是主键的一部分1.4.1.5 操作分区1.4.1.5.…...

重拾Python学习,先从把python删除开始。。。
自己折腾就是不行啊,屡战屡败,最近终于找到前辈教我 第一步 删除Python 先把前阵子折腾的WSL和VScode删掉。还是得用spyder,跟matlab最像,也最容易入手。 从VScode上搞python,最后安装到appdata上,安装插…...
centos 安全配置基线
centos 安全配置基线 一、系统防火墙及SE系统1. 系统自带防火墙iptables(Centos6)基础命令查看防火墙设置使用命令查看防火墙设置使用命令清除防火墙设置防火墙策略开放指定的端口屏蔽IP 2. 系统自带防火墙firewalled(Centos7)基础…...
高级编程语言的基本语法在CPU的眼中是什么样的呢?
任何一门高级编程语言,就一定存在下面这几个语法元素 变量类型数组控制语句(条件,循环)运算符(算术运算,布尔运算,赋值运算,关系运算,位运算)函数 而本节探…...

Redis 性能优化:多维度技术解析与实战策略
文章目录 1 基准性能2 使用 slowlog 优化耗时命令3 big key 优化4 使用 lazy free 特性5 缩短键值对的存储长度6 设置键值的过期时间7 禁用耗时长的查询命令8 使用 Pipeline 批量操作数据9 避免大量数据同时失效10 客户端使用优化11 限制 Redis 内存大小12 使用物理机而非虚拟机…...

.netframwork模拟启动webapi服务并编写对应api接口
在.NET Framework环境中模拟启动Web服务,可以使用几种不同的方法。一个常见的选择是利用HttpListener类来创建一个简单的HTTP服务器,或者使用Owin/Katana库来自托管ASP.NET Web API或MVC应用。下面简要介绍Owin/Katana示例代码。这种方法更加灵活&#x…...
MongoDB 学习指南与资料分享
MongoDB学习资料 MongoDB学习资料 MongoDB学习资料 在数据爆炸的当下,MongoDB 作为非关系型数据库的佼佼者,以其独特优势在各领域发光发热。无论是海量数据的存储,还是复杂数据结构的处理,MongoDB 都能轻松应对。接下来…...

【Azure 架构师学习笔记】- Azure Function (2) --实操1
本文属于【Azure 架构师学习笔记】系列。 本文属于【Azure Function 】系列。 接上文【Azure 架构师学习笔记】- Azure Function (1) --环境搭建和背景介绍 前言 上一文介绍了环境搭建,接下来就在本地环境下使用一下。 环境准备 这里我下载了最新的VS studio&…...
扫描深度?滤光片和偏振片区别?
扫描深度 https://www.shining3d.cn/chike/kousao/aoralscan-wireless.html 是指扫描仪能够准确捕捉和测量的最大距离范围。这一参数对于不同类型的三维扫描仪和应用场景非常重要,具体含义包括: 扫描范围 定义: 扫描深度通常指从扫描仪到被扫描物体表…...
HJ4 字符串分隔(Java版)
一、试题地址 字符串分隔_牛客题霸_牛客网 二、试题内容 描述 对于给定的由小写字母和数字混合构成的字符串 s ,你需要按每 8 个字符换一行的方式书写它,具体地: 书写前 8 个字符,换行;书写接下来的 88 个字符&am…...

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明
LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造,完美适配AGV和无人叉车。同时,集成以太网与语音合成技术,为各类高级系统(如MES、调度系统、库位管理、立库等)提供高效便捷的语音交互体验。 L…...

微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】
微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来,Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...

【第二十一章 SDIO接口(SDIO)】
第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个生活电费的缴纳和查询小程序
一、项目初始化与配置 1. 创建项目 ohpm init harmony/utility-payment-app 2. 配置权限 // module.json5 {"requestPermissions": [{"name": "ohos.permission.INTERNET"},{"name": "ohos.permission.GET_NETWORK_INFO"…...

Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决
Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决 问题背景 在一个基于 Spring Cloud Gateway WebFlux 构建的微服务项目中,新增了一个本地验证码接口 /code,使用函数式路由(RouterFunction)和 Hutool 的 Circle…...
在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?
uni-app 中 Web-view 与 Vue 页面的通讯机制详解 一、Web-view 简介 Web-view 是 uni-app 提供的一个重要组件,用于在原生应用中加载 HTML 页面: 支持加载本地 HTML 文件支持加载远程 HTML 页面实现 Web 与原生的双向通讯可用于嵌入第三方网页或 H5 应…...
重启Eureka集群中的节点,对已经注册的服务有什么影响
先看答案,如果正确地操作,重启Eureka集群中的节点,对已经注册的服务影响非常小,甚至可以做到无感知。 但如果操作不当,可能会引发短暂的服务发现问题。 下面我们从Eureka的核心工作原理来详细分析这个问题。 Eureka的…...

用机器学习破解新能源领域的“弃风”难题
音乐发烧友深有体会,玩音乐的本质就是玩电网。火电声音偏暖,水电偏冷,风电偏空旷。至于太阳能发的电,则略显朦胧和单薄。 不知你是否有感觉,近两年家里的音响声音越来越冷,听起来越来越单薄? —…...

VM虚拟机网络配置(ubuntu24桥接模式):配置静态IP
编辑-虚拟网络编辑器-更改设置 选择桥接模式,然后找到相应的网卡(可以查看自己本机的网络连接) windows连接的网络点击查看属性 编辑虚拟机设置更改网络配置,选择刚才配置的桥接模式 静态ip设置: 我用的ubuntu24桌…...

安全突围:重塑内生安全体系:齐向东在2025年BCS大会的演讲
文章目录 前言第一部分:体系力量是突围之钥第一重困境是体系思想落地不畅。第二重困境是大小体系融合瓶颈。第三重困境是“小体系”运营梗阻。 第二部分:体系矛盾是突围之障一是数据孤岛的障碍。二是投入不足的障碍。三是新旧兼容难的障碍。 第三部分&am…...