多视图几何--立体校正--Bouguet方法
Bouguet算法的数学原理详解
Bouguet算法的核心目标是实现双目相机的极线校正,使左右图像的对应点位于同一水平线上,从而简化立体匹配。其数学原理围绕旋转矩阵分解、极线约束构造和重投影优化展开,以下是分步推导:
一、坐标系定义与极线校正目标
设左相机坐标系为世界坐标系原点,右相机坐标系由旋转矩阵 R R R和平移向量 T T T定义。目标是将左右相机的图像平面变换到同一平面上,且基线与图像平面平行,实现极线水平对齐。
数学目标:
- 构造新的旋转矩阵 R rect R_{\text{rect}} Rrect,使左右相机的光轴平行,且基线方向与图像x轴对齐。
- 将原始旋转矩阵 R R R分解为左右相机的部分旋转 R l R_l Rl和 R r R_r Rr,满足 R = R r T R l R = R_r^T R_l R=RrTRl。
二、旋转矩阵分解与极线对齐
-
基线方向对齐:
平移向量 T = [ T x , T y , T z ] T T = [T_x, T_y, T_z]^T T=[Tx,Ty,Tz]T表示右相机相对于左相机的位置。
归一化基线方向: e 1 = T ∥ T ∥ = [ e 1 x , e 1 y , e 1 z ] T e_1 = \frac{T}{\|T\|} = [e_{1x}, e_{1y}, e_{1z}]^T e1=∥T∥T=[e1x,e1y,e1z]T。 -
构造正交基 R rect R_{\text{rect}} Rrect:
新坐标系的x轴沿基线方向: r 1 = e 1 r_1 = e_1 r1=e1
y轴与原光轴正交: r 2 = [ 0 , 0 , 1 ] T − ( e 1 T [ 0 , 0 , 1 ] T ) e 1 ∥ [ 0 , 0 , 1 ] T − ( e 1 T [ 0 , 0 , 1 ] T ) e 1 ∥ r_2 = \frac{[0, 0, 1]^T - (e_1^T [0, 0, 1]^T)e_1}{\|[0, 0, 1]^T - (e_1^T [0, 0, 1]^T)e_1\|} r2=∥[0,0,1]T−(e1T[0,0,1]T)e1∥[0,0,1]T−(e1T[0,0,1]T)e1.
z轴由叉乘确定: r 3 = r 1 × r 2 r_3 = r_1 \times r_2 r3=r1×r2.
构造正交旋转矩阵:
R rect = [ r 1 T r 2 T r 3 T ] . R_{\text{rect}} = \begin{bmatrix} r_1^T \\ r_2^T \\ r_3^T \end{bmatrix}. Rrect= r1Tr2Tr3T .
- 平分旋转角度:
将原始旋转矩阵 R R R分解为左右相机各旋转一半:
R l = R rect ⋅ R 1 / 2 , R r = R rect ⋅ R − 1 / 2 . R_l = R_{\text{rect}} \cdot R^{1/2}, \quad R_r = R_{\text{rect}} \cdot R^{-1/2}. Rl=Rrect⋅R1/2,Rr=Rrect⋅R−1/2.
其中 R 1 / 2 R^{1/2} R1/2是 R R R的平方根矩阵,满足 R 1 / 2 ⋅ R 1 / 2 = R R^{1/2} \cdot R^{1/2} = R R1/2⋅R1/2=R。
三、投影矩阵构造与重映射
- 构造新的投影矩阵:
左相机投影矩阵:
P l = K l ⋅ [ R rect 0 ] . P_l = K_l \cdot \begin{bmatrix} R_{\text{rect}} & 0 \end{bmatrix}. Pl=Kl⋅[Rrect0].
右相机投影矩阵:
P r = K r ⋅ [ R rect T rect ] , P_r = K_r \cdot \begin{bmatrix} R_{\text{rect}} & T_{\text{rect}} \end{bmatrix}, Pr=Kr⋅[RrectTrect],
其中 T rect = R rect ⋅ T T_{\text{rect}} = R_{\text{rect}} \cdot T Trect=Rrect⋅T.
- 极线约束的数学表达:
校正后,极线方程退化为水平线 y = y 0 y = y_0 y=y0,对应极线方程为:
x r = x l + [ d 0 0 ] , \mathbf{x}_r = \mathbf{x}_l + \begin{bmatrix} d \\ 0 \\ 0 \end{bmatrix}, xr=xl+ d00 ,
其中 d d d为视差。
code:
#include <iostream>
#include <Eigen/Dense>
#include <Eigen/Geometry>using namespace Eigen;// 定义相机参数结构体
struct CameraParams {Matrix3f K; // 内参矩阵Vector3f T; // 平移向量 (右相机相对于左相机)Matrix3f R; // 旋转矩阵 (右相机相对于左相机)
};// Bouguet立体校正核心函数
void bouguetRectify(const CameraParams& left, const CameraParams& right, Matrix3f& R_rect, Matrix3f& R_left, Matrix3f& R_right,Matrix34f& P1, Matrix34f& P2) {// ------------ 步骤1: 构造校正旋转矩阵 R_rect ------------// 计算基线方向 (左相机到右相机的归一化平移向量)Vector3f e1 = left.T.normalized();// 构造正交基Vector3f r1 = e1;Vector3f temp = Vector3f::UnitZ() - e1.dot(Vector3f::UnitZ()) * e1;Vector3f r2 = temp.normalized();Vector3f r3 = r1.cross(r2);// 构造 R_rectR_rect.row(0) = r1.transpose();R_rect.row(1) = r2.transpose();R_rect.row(2) = r3.transpose();// ------------ 步骤2: 分解旋转矩阵 ------------// 计算旋转矩阵的平方根分解 R = R_half * R_halfEigen::Matrix3f R = left.R; // 原始旋转矩阵Eigen::Matrix3f logR, R_half;// 使用对数-指数方法计算平方根logR = R.log(); // 矩阵对数R_half = (0.5 * logR).exp(); // 矩阵指数// 左右相机旋转矩阵R_left = R_rect * R_half;R_right = R_rect * R_half.inverse();// ------------ 步骤3: 构造投影矩阵 ------------// 左相机投影矩阵 P1 = K * [R_rect | 0]P1.block<3,3>(0,0) = left.K * R_rect;P1.col(3) = Vector3f::Zero();// 右相机投影矩阵 P2 = K * [R_rect | T_rect]Vector3f T_rect = R_rect * left.T;P2.block<3,3>(0,0) = right.K * R_rect;P2.col(3) = right.K * T_rect;
}int main() {// 相机参数CameraParams left, right;// 左相机内参left.K << 800, 0, 320,0, 800, 240,0, 0, 1;left.T = Vector3f(0.1, 0, 0); // 平移向量left.R = Matrix3f::Identity(); // 左相机无旋转// 右相机参数 right.K = left.K; // 假设内参相同right.T = Vector3f::Zero(); // 无额外平移right.R = AngleAxisf(0.2, Vector3f::UnitY()).toRotationMatrix(); // Y轴旋转// 输出参数Matrix3f R_rect, R_left, R_right;Matrix34f P1, P2; // 3x4投影矩阵// 执行校正bouguetRectify(left, right, R_rect, R_left, R_right, P1, P2);// 打印结果std::cout << "校正旋转矩阵 R_rect:\n" << R_rect << "\n\n";std::cout << "左相机旋转 R_left:\n" << R_left << "\n\n";std::cout << "右相机旋转 R_right:\n" << R_right << "\n\n";std::cout << "左投影矩阵 P1:\n" << P1 << "\n\n";std::cout << "右投影矩阵 P2:\n" << P2 << "\n";return 0;
}
参考:《learning opencv》
1
2
相关文章:
多视图几何--立体校正--Bouguet方法
Bouguet算法的数学原理详解 Bouguet算法的核心目标是实现双目相机的极线校正,使左右图像的对应点位于同一水平线上,从而简化立体匹配。其数学原理围绕旋转矩阵分解、极线约束构造和重投影优化展开,以下是分步推导: 一、坐标系定义…...
debian12 mysql完全卸载
MySQL 的数据目录通常是 /var/lib/mysql,配置文件通常在 /etc/mysql 目录下。使用以下命令删除这些目录: sudo rm -rf /var/lib/mysql sudo rm -rf /etc/mysql清理残留文件 sudo find / -name "mysql*" -exec rm -rf {} \; 2>/dev/null验…...
随机动作指令活体检测技术的广泛应用,为人脸识别安全保驾护航
随着人脸识别技术在金融支付、门禁系统、手机解锁等领域的广泛应用,攻击手段也日益多样化,如照片、视频回放、3D面具等伪造方式对系统安全构成严重威胁。传统的人脸识别技术难以区分真实人脸与伪造攻击,正是在这样的背景下,随机动…...
Chrome 135 版本开发者工具(DevTools)更新内容
Chrome 135 版本开发者工具(DevTools)更新内容 一、性能(Performance)面板改进 1. 性能面板中的配置文件和函数调用现已显示来源和脚本链接 Performance > Summary(性能 > 概览)选项卡现在会显示配…...
《算法:以三种算法思想及两种优化策略解决Fibonacci数》
文章目录 0.题目:red_circle:一.递归记忆化搜索**a.普通递归****b.记忆化搜索(优化)**算法讲解: :red_circle:二.前缀和a.算法讲解b.代码示例 :red_circle:三.动态规划滚动数组a.算法讲解b.普通动规代码示例c.滚动数组优化 作者的个人gitee 作者的算法讲…...
定制开发开源AI智能名片S2B2C商城小程序源码中的产品运营协同进化机制研究
摘要 在数字化产品发展进程中,产品经理与运营人员的协同工作机制对产品迭代方向具有决定性作用。本文以定制开发开源AI智能名片S2B2C商城小程序源码为研究对象,通过分析其技术架构中的智能推荐系统、三级账户体系及社交裂变引擎等创新模块,揭…...
Colmap的安装和使用
Colmap 网站: https://colmap.github.io/GitHub: https://github.com/colmap/colmap 安装 Windows 从 GitHub发布页 GitHub Releases 下载预编译的二进制, 区分带CUDA和不带CUDA的版本. Ubuntu 在 Ubuntu 22.04 下可以通过apt install colmap安装, 但是这样安装的是不带C…...
Springboot框架—单元测试操作
Springboot单元测试的操作步骤: 1.添加依赖spring-boot-starter-test 在pom.xml中添加依赖spring-boot-starter-test 2.在src/test/java下新建java class 3.单元测试入口代码结构 import org.junit.Test; import org.junit.runner.RunWith; import org.springfra…...
Elasticearch数据流向
Elasticearch数据流向 数据流向图 --- config: layout: elk look: classic theme: mc --- flowchart LR subgraph s1["图例"] direction TB W["写入流程"] R["读取流程"] end A["Logstash Pipeline"] -- 写入请求 --> B["Elas…...
dB,dBi, dBd, dBc,dBm,dBw释义及区别
贝尔(B) 贝尔(B)最初用于表示音量功率10与1的比值,亚历山大.格拉汉姆.贝尔的名字命名。因此,1B表示功率比10:1,这是一种对数的关系,底数为10,100:12B,1000:13B。即lg(P2/P1)。 可以看出B是一个较大的单位…...
CRM是企业AI Agent应用的关键切入点
CRM(Customer Relationship Management,客户关系管理)是一套用于系统化管理企业与客户交互的技术、策略和流程,旨在优化客户体验、提升忠诚度并驱动业务增长。其核心功能包括客户数据整合(如联系信息、交易记录、行为轨…...
aws(学习笔记第三十八课) codepipeline-build-deploy-github-manual
文章目录 aws(学习笔记第三十八课) codepipeline-build-deploy-github-manual学习内容:1. 整体架构1.1 代码链接1.2 全体处理架构 2. 代码分析2.1 创建ImageRepo,并设定给FargateTaskDef2.2 创建CodeBuild project2.3 对CodeBuild project赋予权限&#…...
【数据分享】1999—2023年地级市市政公用事业和邮政、电信业发展情况相关指标(Shp/Excel格式)
在之前的文章中,我们分享过基于2000-2024年《中国城市统计年鉴》整理的1999-2023年地级市的人口相关数据、染物排放和环境治理相关数据、房地产投资情况和商品房销售面积相关指标数据、社会消费品零售总额和年末金融机构存贷款余额、各类用地面积、地方一般公共预算…...
vscode 跳转失败之c_cpp_properties.json解析
{"configurations": [{"name": "Linux", // 配置名称,对应当前平台,VS Code 中可选"includePath": ["${workspaceFolder}/**", // 包含当前工作区下所有文件夹的头文件(递归&…...
批量将图片转换为 jpg/png/Word/PDF/Excel 等其它格式
图片的格式种类非常的多,常见的图片格式就有 jpg、png、webp、bmp 等等,我们在工作当中经常会碰到需要将一种格式的图片转换为其他格式的需求。今天就给大家介绍一种方法,可以实现批量转换图片格式,支持各种格式的图片之间相互转换…...
MCP+Blender创建电力塔
MCP(Model Context Protocol)与Blender的结合是当前AI与3D建模领域的热门技术,它通过协议化的方式让Claude等AI模型直接控制Blender,实现自动化3D建模。 1. 功能与原理 • 核心能力:用户通过自然语言指令(…...
kafka存储原理
topic分着存储在broker的分区中,分区进一步分为segment。 日志目录中的每一组文件都代表一个段。 段文件名中的后缀表示该段的基本偏移量。 log.segment.bytes表示分段的最大大小。 消息写入分区时,kafka会将这些消息写入段,写满了再创建一个…...
Arduino开发物联网ESP32快速入门指南(包含开发语言说明、学习路径和实战教程)
一、Arduino开发语言本质 核心语言:基于C/C的扩展语言,包含Arduino特有的API和库 特点: 去除了C的复杂特性(如STL) 内置硬件操作函数(digitalWrite()、analogRead()等) 支持面向对象编程&…...
《系统架构设计师教程(第2版)》第19章-大数据架构设计理论与实践-01-传统数据处理系统存在的问题
文章目录 1. 异步处理队列2. 数据库分区3 读写分离4. 基于Hadoop的 Map/Reduce 管道 1. 异步处理队列 出现的原因:用户访问量增加,数据库无法支撑用户请求的负载,导致数据库服务器无法及时响应用户请求解决:在Web服务器和数据库中…...
Vue接口平台学习五——测试环境页面
一、实现效果图及界面布局简单梳理 这块内容分左侧,中间,右侧三大部分 左侧: 上面一行固定内容,显示icon,名字,一个按钮。下面部分通过v-for循环读取数据库获取的测试环境列表用来展示名称。 中间&#…...
FFMpeg视频编码实战和音频编码实战
视频编码流程 avcodec_find_encoder:首先,通过指定的编码器名称(如H.264、MPEG-4等)找到对应的编码器。avcodec_alloc_context3:为找到的编码器分配一个上下文结构,这个结构包含了编码器所需的各种参数和状…...
vue+uniapp 获取上一页直接传递的参数
在小程序里页面之间跳转有时候需要传递参数给下个页面用 const toDetail item > { uni.navigateTo({ url: /pagesFood/stu/FoodSelection?groupCode1&merchCode2, }); }; 那么下个页面就要获取到这些参数,在实际开发中ÿ…...
各种排序思路及实现
目录 1.排序概念常见的排序算法 2.常见排序算法实现(1)插入排序直接插入排序希尔排序(缩小增量排序) (2)选择排序直接选择排序堆排序 (3)交换排序冒泡排序快速排序(hoare…...
GPT文生图模型新玩法
GPT-4o发布了最新的生图模型GPT-4o-Image,在图像控制力、一致性上实现了显著提升,其表现甚至展现出超越Midjourney的潜力。这款模型不仅能读懂细致的指令,还能赋予照片艺术化的新生命。接下来,我们将介绍几个有趣的实践方向&#…...
uni-app ucharts自定义换行tooltips
实现效果: 第一步:在uni_modules文件夹下找到config-ucharts.js和u-charts.js文件 第二步:在config-ucharts.js文件中配置换行格式 // 换行格式"wrapTooltip":function(item, category, index, opts){return item.name:…...
java 集合进阶
双列集合 map 实例 package mymap;import java.util.HashMap; import java.util.Map;public class MapDemo1 {public static void main(String[] args) {/*V put(K key,v value)添加元素V remove(object key)根据键删除键值对元素void clear()移除所有的键值对元素boolean c…...
RPC 2025/4/8
RPC(Remote Procedure Call),远程过程调用。 应用场景:大型微服务项目,服务部署到不同的服务器上,需要远程调用,可以使用RPC。 两个概念: 远程过程调用本地调用 RPC目的:…...
浅层神经网络:全面解析(扩展)
浅层神经网络:全面解析(扩展) 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,可以分享一下给大家。点击跳转到网站。 https://www.captainbed.cn/ccc 一、神经网络架构演进图谱 #mermaid-svg-…...
【Hadoop入门】Hadoop生态之ZooKeeper简介
1 什么是ZooKeeper? 在分布式系统的世界里,协调各节点之间的工作是一项复杂而关键的任务。ZooKeeper正是为解决这一问题而生的开源分布式协调服务,它像一个高效的"和事佬",帮助分布式系统中的各个组件达成一致、同步状态…...
树和图论(详细整理,简单易懂!)
树和图论 树的遍历模版 #include <iostream> #include <cstring> #include <vector> #include <queue> // 添加queue头文件 using namespace std;const int MAXN 100; // 假设一个足够大的数组大小 int ls[MAXN], rs[MAXN]; // 定义左右子树数…...
CWGAN-GP 原理及实现(pytorch版)
CWGAN-GP 一、CWGAN-GP 原理1.1 CWGAN-GP 的核心改进1.2 CWGAN-GP 的损失函数1.3 CWGAN-GP 的优势1.4 关键参数选择1.5 应用场景 二、CWGAN-GP 实现2.1 导包2.2 数据加载和处理2.3 构建生成器2.4 构建判别器2.5 训练和保存模型2.6 查看训练损失2.7 图片转GIF2.8 模型加载和推理…...
zookeeper平滑扩缩容
在进行ZooKeeper的扩容和缩容操作时,需要注意以下几点: 数据一致性 重要性:ZooKeeper的核心特性之一是保证数据的一致性。在操作过程中,必须确保数据的一致性,以避免数据丢失或损坏。 实现方式:ZooKeeper通…...
Github 热点项目 ChartDB AI自动导表结构+迁移脚本,3分钟生成专业数据库关系图
ChartDB堪称数据库设计神器!亮点①:动动手指输入SQL,秒出结构图,表关系一目了然,团队评审时再也不用画图两小时。亮点②:AI智能转换超贴心,MySQL转PostgreSQL只需点个按钮,跨平台迁移…...
RVOS-1.环境搭建与系统引导
0.环境搭建 riscv-operating-system-mooc: 开放课程《循序渐进,学习开发一个 RISC-V 上的操作系统》配套教材代码仓库。 mirror to https://github.com/plctlab/riscv-operating-system-mooc 在 Ubuntu 20.04 以上环境下我们可以直接使用官方提供的 GNU工具链和 QEM…...
Java List<JSONObject> 转换为 List<实体类>
可以使用 Fastjson 的 toJavaObject 方法直接转换,无需中间序列化步骤。以下是具体实现和注意事项: import com.alibaba.fastjson.JSONObject; import java.util.List; import java.util.stream.Collectors;public class Converter {public static List…...
CesiumEarth v1.12 更新,支持安卓平板离线浏览3DTiles格式的三维倾斜模型
CesiumEarth v1.12 更新 2025年4月8日 阅读需 1 分钟 发布时间:2025年04月08日 新增用户登录: 从1.12版本开始需要通过登录方可使用CesiumEarth 账号可以通过邮箱免费注册 后续将陆续发布云服务相关的功能 发布Desktop版本: Deskt…...
OpenEuler运维实战-系统资源监控与性能优化-CPU·内存·IO
CPU 基本概念定界定位思路常用CPU性能分析工具 基本概念 中央处理器(Central Processing Unit,简称CPU)是计算机的主要设备之一,其功能是解释计算机指令以及处理计算机软件中的数据。 物理核:可以真实看到的CPU核&…...
react实现SVG地图区域中心点呈现圆柱体,不同区域数据不同,圆柱体高度不同
效果图: 代码: import React, { useState, useEffect } from react;const InnerMongoliaMap () > {// 每个区域的数据(名称、中心坐标、圆柱体高度值)const [regionData, setRegionData] useState([{ id: "呼和浩特市…...
Qwen - 14B 怎么实现本地部署,权重参数大小:21GB
Qwen - 14B 权重参数大小:21GB 参数量与模型占用存储空间(GB)是不同概念。Qwen - 14B参数量约140亿 。其模型大小在不同精度下占用存储空间不同,如在一些资料中提到,Qwen - 14B在特定情况下占用空间约21GB 。实际存储…...
线程实现参考资料
参考 并发编程系列 - Java线程池监控及CompletableFuture详解_taskexecutor.execute没有执行如何监控到-CSDN博客 JAVA异步实现的四种方式_java异步编程的四种方法-CSDN博客 Java线程池深度解析与自定义实战-CSDN博客 Java8 CompletableFuture 异步多线程的实现_java_脚本之…...
python-63-前后端分离之图书管理系统的Flask后端
文章目录 1 flask后端1.1 数据库实例extension.py1.2 数据模型models.py1.3 .flaskenv1.4 app.py1.5 运行1.6 测试链接2 关键函数和文件2.1 请求视图类MethodView2.2 .flaskenv文件3 参考附录基于flask形成了图书管理系统的后端,同时对其中使用到的关键文件.flaskenv和函数类M…...
Qt网络编程之服务端
Qt网络编程之服务端 TCP(传输控制协议)是一种可靠的、面向流的、面向连接的传输协议。它特别适合连续的数据传输。 1. 主要类和函数 1.1 QTcpServer 监听函数: bool QTcpServer::listen(const QHostAddress &address QHostAddress::…...
案例-流量统计
1.建一个data目录,在data下建log.txt文件 输入手机号码 上行流量 下行流量 2.在com.example.flow下建四个Java类3.flowBean flowMapper flowReducer flowDriver...
开源身份和访问管理方案之keycloak(二)管理员引导和恢复
文章目录 开源身份和访问管理方案之keycloak(二)管理员引导和恢复管理员引导和恢复在 Keycloak 启动时引导临时管理员帐户对于恢复丢失的管理员访问权限使用专用命令引导管理员用户或服务帐户创建一个管理员用户创建一个服务账号重新获得对具有更高安全性…...
TCP,UDP协议和域名地址
1.TCP(传输控制协议)是面向连接,UDP(用户数据报协议)是无连接的 2.应用层:FTP,HTTP,SMTP,TELNET,DNS,TFTP 传输层;TCP,UDP 网际层:IP,ICMP,ARP,RARP 3.TCP21:20端口数据传输;21端…...
算法进阶指南 分形
问题描述 分形,具有以非整数维形式充填空间的形态特征。通常被定义为: “一个粗糙或零碎的几何形状,可以分成数个部分,且每一部分都(至少近似地)是整体缩小后的形状”,即具有自相似的性质。 现…...
2025年 npm淘宝镜像最新地址
查看当前镜像 npm config get registry 切换陶宝镜像源 npm config set registry https://registry.npmmirror.com/ 验证npm镜像源是否切换成功 npm config get registry 如果返回的地址是https://registry.npmmirror.com/,那么说明你已经成功切换到淘宝的npm…...
0基础 | 硬件 | LM386芯片
LM386芯片:音频功率放大器芯片 内部集成三极管功能将微弱信号放大20-200倍,并且驱动内阻为8Ω的扬声器注意CD系列芯片,内部集成MOS管 LM386特性 LM386主要由以下三个部分组成 内部电路 差分输入 差分输入 多个三极管左右对称,形…...
Spring Boot集成APK Parser库实现APK文件解析
目录 1. 添加依赖 2. 创建APK解析服务 3. 创建控制器 4. 测试 注意事项 在Spring Boot项目中集成APK Parser库并解析APK文件,可以按照以下步骤进行操作: 1. 添加依赖 在项目的pom.xml文件中添加apk-parser库的依赖: <dependency&…...
java基础 迭代Iterable接口以及迭代器Iterator
Itera迭代 Iterable < T>迭代接口(1) Iterator iterator()(2) forEach(Consumer<? super T> action)forEach结合Consumer常见场景forEach使用注意细节 (3)Spliterator spliterator() Iterator< T>迭代器接口如何“接收” Iterator<T>核心方法迭代器的…...