从零开始学习SLAM六(单应矩阵)

news2024/9/25 23:15:05

本文参考:计算机视觉life

概念

单应性(homography)是指两个平面之间的一种保直线性的对应关系。如果一个平面上的点集经过某种变换后,在另一个平面上形成的新点集仍然保持原来的线性特性(如共线的点仍然共线),那么这种变换就称为单应性变换。在数学上,单应性变换可以用一个3x3的矩阵来表示,这个矩阵就是所谓的单应矩阵。

回顾相机成像

世界坐标系到相机坐标系的变换为:
在这里插入图片描述
我们简化表达式为, 其中M是3 x 3的矩阵:

( u v 1 ) = M ( x y z 1 ) \begin{pmatrix} u\\ v\\ 1 \end{pmatrix} = M\begin{pmatrix} x\\ y\\ z\\ 1 \end{pmatrix} uv1 =M xyz1

对于两个不同的相机,像素坐标和空间点坐标可以写成如下的表示
在这里插入图片描述
我们把上面两个式子合并一下就得到了下面这个式子,其中的H就是单应矩阵啦!H矩阵的两边是两张图像对应的匹配点对。也就是说单应矩阵H把三维空间中同一平面的点在两个相机的成像图片坐标进行了映射。
在这里插入图片描述
有时1会被平面方程替代,是因为
1.约束条件:在推导单应矩阵的过程中,通常会涉及到多个未知数。为了求解单应矩阵 H,我们需要建立足够的约束条件。平面方程在这里被用来增加额外的约束条件,以便降低问题的自由度。
2. 降维: 由于单应矩阵 H 是一个3x3的矩阵,理论上包含9个参数。但由于它是齐次坐标下的矩阵,所以可以任意缩放,这意味着有一个自由度是冗余的。因此,单应矩阵实际上有8个自由度。为了求解这8个自由度,我们需要至少4对匹配点来建立8个线性方程。
3. 平面方程: 在某些推导过程中,可能会引入平面方程作为约束条件。例如,假设我们有一个平面nTx+d=0,其中 n是平面的法向量,x 是平面上的点,d 是常数。在某些情况下,可以将这个平面方程中的 d 替换为1,从而简化计算或引入额外的约束。

平面方程:在讨论单应矩阵时提到的平面方程,通常指的是图像中的某个平面在三维空间中的方程。具体来说,当我们在处理单应矩阵时,我们关注的是两个图像之间对应点的关系,这些点通常位于同一个平面上。这个平面可以是场景中的任何一个平面,例如墙面、地面或者任何具有平面结构的物体表面。平面方程nTx+d=0中的x = (X,Y, Z)指的是三维世界坐标系中的点,世界坐标系是一个固定的参考坐标系,用于描述三维空间中的物体位置和方向。在这个坐标系中,每个点的位置可以用三个坐标(X,Y, Z)来表示。如下图:
在这里插入图片描述

下面给出代码:

#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;

struct userdata {
    Mat im;
    vector<Point2f> points;
};

void mouseHandler(int event, int x, int y, int flags, void* data_ptr) {
    if (event == EVENT_LBUTTONDOWN) {
        userdata* data = (userdata*)data_ptr;
        circle(data->im, Point(x, y), 3, Scalar(0, 255, 255), 5, LINE_AA);
        imshow("Image", data->im);
        if (data->points.size() < 4) {
            data->points.push_back(Point2f(x, y));
        }
    }
}

int main(int argc, char** argv) {
    // Read in the logo and the image with the billboard
    Mat im_logo = imread("cy.png");
    Mat im_ad = imread("tm.jpg");

    if (im_logo.empty() || im_ad.empty()) {
        cout << "Could not open or find the images!" << endl;
        return -1;
    }

    // Define the four corners of the logo in the logo image (source points)
    Size logo_size = im_logo.size();
    vector<Point2f> pts_logo = {
        Point2f(0, 0),
        Point2f(logo_size.width - 1, 0),
        Point2f(logo_size.width - 1, logo_size.height - 1),
        Point2f(0, logo_size.height - 1)
    };

    // Destination image
    Mat im_temp = im_ad.clone();
    userdata data;
    data.im = im_temp;

    // Show the image and set mouse callback
    imshow("Image", im_temp);
    cout << "Click on four corners of the billboard and then press ENTER" << endl;
    setMouseCallback("Image", mouseHandler, &data);
    waitKey(0);

    // Check if we have exactly four points
    if (data.points.size() != 4) {
        cout << "You need to click exactly four points!" << endl;
        return -1;
    }

    // Define the four corners of the billboard in the destination image (destination points)
    vector<Point2f> pts_ad = data.points;

    // Compute the perspective transform matrix
    Mat H = findHomography(pts_logo, pts_ad);

    // Warp the logo image to fit the billboard area in the destination image
    Mat im_warped;
    warpPerspective(im_logo, im_warped, H, im_ad.size());

    // Create a mask for the warped logo
    Mat mask = Mat::zeros(im_ad.size(), CV_8UC1);
    vector<Point> mask_points(pts_ad.begin(), pts_ad.end());
    fillConvexPoly(mask, mask_points, Scalar(255));

    // Blend the warped logo with the destination image
    Mat im_ad_masked;
    im_ad.copyTo(im_ad_masked, ~mask);  // Copy the background
    im_warped.copyTo(im_ad_masked, mask);  // Overlay the warped logo

    // Display the final result
    imshow("Result", im_ad_masked);
    waitKey(0);

    return 0;
}

最后出图是一位绝顶大帅哥(不是秃头):
在这里插入图片描述

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

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

相关文章

一起搭WPF界面之View的简单设计一

一起搭WPF界面之View的简单设计一 1 前言2 界面预期设想3 基础的实现步骤3.1 界面划分3.1.1 基础框架代码&#xff1a;3.1.2 实现效果 4 界面花样设计4.1 花样设计4.2 界面源代码4.3 错误提醒4.3.1 错误14.3.2 错误2 总结 1 前言 基于上一篇的window、Gird、Border的简单介绍&…

XSS LABS - Level 13 过关思路

关注这个靶场的其他相关笔记&#xff1a;XSS - LABS —— 靶场笔记合集-CSDN博客 0x01&#xff1a;过关流程 进入靶场&#xff0c;老样子&#xff0c;右击&#xff0c;查看页面源码&#xff0c;找找不同&#xff1a; 可以看到&#xff0c;本关又多了一个新字段 t_cook&#xf…

关于 Vue/React 的 cli 中运用 webpack 打包的原理简单解析

webpack、webpack-cli的打包 关于 webpack 对前端工程中进行资源文件进行打包处理的过程中&#xff0c;运用到的核心插件主要是 webpack 和 webpack-cli&#xff0c;在 react 和 vue 对于打包各自工程中的 cli 则是进行了自定义的构建&#xff0c;专门用于项目打包的 …

【MySQL-25】万字总结<锁>——(全局锁&行级锁&表级锁)【共享锁,排他锁】【间隙锁,临键锁】【表锁,元数据锁,意向锁】

前言 大家好吖&#xff0c;欢迎来到 YY 滴MySQL系列 &#xff0c;热烈欢迎&#xff01; 本章主要内容面向接触过C的老铁 主要内容含&#xff1a; 欢迎订阅 YY滴C专栏&#xff01;更多干货持续更新&#xff01;以下是传送门&#xff01; YY的《C》专栏YY的《C11》专栏YY的《Lin…

Bytebase 2.22.2 - 允许在工作空间为群组分配角色

&#x1f680; 新功能 允许在工作空间给群组分配角色。 支持禁用邮箱密码登录&#xff0c;仅允许 SSO 登录的设置项。 新增 Postgres SQL 审核规则&#xff1a;禁止在列上设置会变化的默认值。 &#x1f514; 重大变更 下线项目内的变更历史页面&#xff1b;所有变更历史仍可…

Phoenix

Apache Phoenix 是一个开源的关系数据库层&#xff0c;运行在 Apache HBase 之上&#xff0c;旨在为 HBase 提供 SQL 查询能力和优化的存储引擎。它允许用户使用标准的 SQL 查询和事务语义来管理 HBase 中的数据&#xff0c;并且可以与现有的大数据生态系统无缝集成。Phoenix 通…

IOS开发 铃声制作(库乐队)

IOS开发&#xff0c;实现铃声制作功能。 在IOS端&#xff0c;要设置铃声都是通过库乐队来制作的。 先看一下库乐队中铃声的文件结构。下面是弄的一个示例的文件&#xff0c;文件信息如下&#xff1a; 我们右击文件&#xff0c;点击显示包内容如下&#xff1a; 能看到一个aiff格…

解决ssl certificates updated-生成环境中的实例

应原来小伙伴的要求&#xff0c;生产环境出错了&#xff0c;是harbor的ssl cert过期了&#xff0c;也因为使用的是免费的ssl证书&#xff0c;现在无法正常使用harbor&#xff0c;所以贴来了2023年1月曾经搭建的文档&#xff0c;希望能解决问题。^v^. -------------------------…

25 filedialog组件

Tkinter filedialog 组件使用指南 Tkinter 的 filedialog 组件提供了一个图形界面&#xff0c;用于打开和保存文件。它允许用户通过标准的文件选择对话框来选择文件&#xff0c;非常适合需要文件操作的GUI应用程序。以下是对 filedialog 组件的详细说明和一个使用案例。 file…

爆改YOLOv8 |YOLOv8融合SEAM注意力机制

1&#xff0c;本文介绍 SEAM&#xff08;Spatially Enhanced Attention Module&#xff09;是一个注意力网络模块&#xff0c;旨在解决面部遮挡导致的响应损失问题。通过使用深度可分离卷积和残差连接的组合&#xff0c;SEAM模块增强未遮挡面部的响应。深度可分离卷积在每个通…

Xshell 连接 Ubuntu 服务器失败问题(Connection failed)

目录 Xshell 连接 Ubuntu 服务器失败问题&#xff08;Connection failed&#xff09; 1.查看Ubuntu中是否安装 sshd 2.在Ubuntu中安装sshd 3.需要打开Ubuntu中新安装的sshd 4.在检查Ubuntu中sshd是否安装成功 5.临时关闭Ubuntu中的防火墙 6.Xshell 连接 Ubuntu 服务器成…

认知杂谈24

今天分享 有人说的一段争议性的话 I I 《人生逆袭的关键&#xff1a;开窍带来的转变》 在女人的生活里啊&#xff0c;最宝贝的东西可不是那些金银首饰啥的&#xff0c;也不只是那些起起落落的经历&#xff0c;更不是偶尔碰到的贵人帮忙。真正无价的&#xff0c;是在某个瞬间…

构建buildroot根文件系统

目录 1.确定gcc工具版本2.下载Buildroot源码并编译2.1 下载Buildroot源码2.2 配置Buildroot2.2.1 配置 Target options2.2.2 配置交叉编译工具链2.2.3 配置 System configuration2.2.4 配置 Filesystem images2.2.5 禁止编译 Linux 内核和 uboot2.2.6 编译Buildroot源码2.2.7 查…

Bootloader中的PBL、SBL的区别

从0开始学习CANoe使用 从0开始学习车载车身 相信时间的力量 星光不负赶路者&#xff0c;时光不负有心人。 目录 1.概述2.BootloaderPBLSBL3.SBL存在意义4.PBL存在意义 1.概述 应用软件和应用数据可以同时编程或者相互独立编程&#xff0c;不允许Boot Loader在软件运行时被非法…

透明度测试

&#xff11;、透明测试是用于处理哪种透明需求 在游戏开发中对象的某些部位完全透明而其他部位完全不透明,这种透明需求往往不需要半透明效果,相对比较极端&#xff0c;只有看得见和看不见之分比如树叶、草、栅栏等等。&#xff08;即一张图除了主要物体有颜色&#xff0c;其…

<WPF> xaml代码如何使用c#编写

<Window x:Class"grid面板的使用.MainWindow"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x"http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d"http://schemas.microsoft.com/expression/blend/2008&…

【Java】—— Java面向对象基础:编程实例(学生信息管理)

目录 场景描述 定义学生类 创建学生对象并处理需求 代码解析 总结 在Java中&#xff0c;面向对象编程&#xff08;OOP&#xff09;是一种常用的编程范式&#xff0c;它允许我们创建基于现实世界的模型&#xff0c;通过类和对象来模拟这些模型。今天&#xff0c;我们将通过…

MySQL 集群技术全攻略:从搭建到优化(上)

目录 一.Mysql在服务器中的部署方法 1.在Linux下部署mysql 二.mysql的组从复制 1.当有数据时添加slave2 2.延迟复制 3.慢查询日志 4.mysql的并行复制 5.原理架构图 5.1三个线程 5.2复制三步骤 6.架构缺陷 三.半同步模式 1.半同步模式原理 2.gtid模式 3.启用半同…

数组、向量与矩阵

问题缘起 在看《矩阵力量》的时候&#xff0c;写到 利用 a numpy.array([4,3]). 严格说&#xff0c;此代码产生的不是行向量&#xff0c;运行 a.ndim 发现 a 只有一个维度。因此&#xff0c;转置 numpy.array([4,3]).T 得到的仍然是一维数组&#xff0c;只不过默认展示方式为…

腾讯提出一种新的针对风格化角色和逼真服装动画的生成3D运动转移方法,生成效果逼真!

来自腾讯XR视觉实验室的研究团队提出了一种创新的3D运动转移方法&#xff0c;专门针对风格化角色和逼真服装动画的生成。该方法能够将源动作准确地映射到目标角色上&#xff0c;同时考虑了角色身体的刚性变形和服装的局部物理动态变形。 与现有技术相比&#xff0c;这技术不仅…