(四)单应矩阵

单应矩阵原理

  单应(透射变换)是射影几何中的概念,又称为射影变换。他把一个射影平面上的点映射到另一个平面对应的位置,并且把直线映射为直线,具有保线性质。与对极几何不同的是,对极几何将点映射到线上,而单应矩阵是点对点的关系。要注意的是单应矩阵的适用场景为:当场景中的特征点都落在同一平面上,比如墙、地面等,此时可用单应性估计运动。

  单应(透射变换)可以看成是仿射变换的拓展。仿射变换在图形中的变换包括:平移、缩放、旋转、斜切及它们的组合形式。这些变换的特点是:平行关系和线段的长度比例保持不变,即保持物体的平直性。而单应中也存在上述多种变换的组合形式,但是差别在于单应并不一定能保持平行关系和线段的长度比例不变。单应的特点是共面点成像,即单应变换是将某一块共面的地方变换到另外一个地方,但是多数情况下都会彻底改变物体位置和形状。

平面表示方法

  首先需要确定一个平面法向量为 $\mathbf{\vec{n}} = [n_{1}, n_{2}, n_{3}]^{T}$,但是确定法向量并不能唯一确定一个平面。我们会得到无数多的相互平行的平面。为了唯一确定一个平面,我们还需要一个点,若平面上有一个定点 $\mathbf{x} = [x_{1}, x_{2}, x_{3}]^{T}$, 那么我们即可确定一个平面。

    假设平面上任意一点为 $\mathbf{m} = \{x, y, z\}$,平面方程为

$$Ax + By + Cz + D = 0$$

由于法向量已知,则上述方程可以表示成:

$$\mathbf{\vec{n}^{T}} \mathbf{m} + D = 0$$

显然上述的方程表示的是无数组平行的平面,确定 $D$ 即可确定唯一平面。则利用上述所说的平面上的任意动点 $x$,则有:

$$D = -\mathbf{\vec{n}^{T}}\mathbf{x} = -(n_{1}x_{1} + n_{2}x_{2} + n_{3}x_{3})$$

则平面的唯一表示方法为:

$$Ax + Bx + Cz = (n_{1}x_{1} + n_{2}x_{2} + n_{3}x_{3})$$

综上,为了表示一个平面,我们需要一个法向量,以及一个平面上的点(目的是为了求偏置)。

单应矩阵

由上述可知平面的表示方法可以写成:

$$\mathbf{\vec{n}}^{T}\mathbf{x} = d$$

参考对极几何及单应矩阵这篇文章,我们可以得到单应约束图像:

假设左边为第一个相机坐标系 $C_{1}$,右边为第二个相机坐标系 $C_{2}$。并且平面 $\pi$ 在第一个相机坐标系的法向量为 $\mathbf{\vec{n}}$,$C_{2}$ 到平面 $\pi$ 的距离为 $d$。假设平面中任意一个点 $\mathbf{X}$ 在第一个相机坐标系中的表示为 $\mathbf{X_{1}}$,则平面 $\pi$ 的表示方法为:

$$\mathbf{\vec{n}}^{T} \mathbf{X_{1}} = d$$

显然,上面的表示方法满足我们前面介绍的平面表示方法的约束条件,即一个法向量以及平面内有一个已知点。接着我们将平面 $\pi$ 的表示方法改变一下:

$$\frac{1}{d}\mathbf{\vec{n}}^{T} \mathbf{X_{1}} = 1$$

假设平面 $\pi$ 中有一空间点 $X$,对应两个相机的投影像素分别为 $\mathbf{p_{1}}, \mathbf{p_{2}}$,相机内参矩阵为 $\mathbf{K},$归一化平面中的坐标系为 $\mathbf{x_{1}},\mathbf{{x_{2}}}$,并且满足条件 $s_{1}\mathbf{x_{1}} = \mathbf{X_{1}}$,其中 $s_{1}$ 为 $X_{1}$ 的深度值。若已知两个坐标系之间的相对变换为 $\mathbf{R}, \mathbf{t}$,表示从相机坐标系 $1$ 变换到相机坐标系 $2$,则有:

$$\mathbf{x_{1}} = \mathbf{K}^{-1}\mathbf{p_{1}}$$

$$\mathbf{x_{2}} = \mathbf{K}^{-1}\mathbf{p_{2}}$$

$$s_{2}\mathbf{x_{2}} = s_{1}\mathbf{R}\mathbf{x_{1}} + \mathbf{t}$$

$$s_{2}\mathbf{K}^{-1}\mathbf{p_{2}} = s_{1}\mathbf{R}\mathbf{K}^{-1}\mathbf{p_{1}} + \mathbf{t}$$

将平面 $\pi$ 的信息代入上述方程中得到:

$$s_{2}\mathbf{K}^{-1}\mathbf{p_{2}} = s_{1}\mathbf{R}\mathbf{K}^{-1}\mathbf{p_{1}} + \frac{s_{1}}{d}\mathbf{t}\mathbf{\vec{n}}^{T} \mathbf{K}^{-1} \mathbf{p_{1}} = s_{1}(\mathbf{R} + \frac{1}{d}\mathbf{t}\mathbf{\vec{n}}^{T})\mathbf{K}^{-1} \mathbf{p_{1}} $$

两边左乘相机内参矩阵:

$$s_{2}\mathbf{p_{2}} = s_{1} \mathbf{K}(\mathbf{R} + \frac{1}{d}\mathbf{t}\mathbf{\vec{n}}^{T})\mathbf{K}^{-1} \mathbf{p_{1}}$$

其中 $\mathbf{H} = \mathbf{K}(\mathbf{R} + \frac{1}{d}\mathbf{t}\mathbf{\vec{n}}^{T})\mathbf{K}^{-1}$ 称为单应矩阵。再进一步简化为:

$$\mathbf{p_{2}} = \frac{s_{1}}{s_{2}}\mathbf{H}\mathbf{p_{1}}$$

在上述的式子当中,我们发现除了单应约束以外,还有一个常系数 $\frac{s_{1}}{s_{2}}$。实际上该系数影响并不大,因为在实际求解当中,我们需要将得到的三个方程同时除以第三个方程,才能得到两个有用的约束关系。(笔者以为:之所以需要这么做,是因为我们输入的数据,均是归一化的点,因此,在最终的结果上也应保持左右两边最后一维的数值应该为 $1$)。显然,上述方程对于尺度的变化是不敏感的,因为没有任何作用。

通过将约束条件 $\mathbf{p_{2}} = \mathbf{H}\mathbf{p_{1}}$ 展开,我们可以得到两个方程。并且我们由上面的分析可以知道,单应矩阵 $\mathbf{H}$ 并非是有 $9$ 维自由度的矩阵,因为其对尺度不敏感。所以我们将单应矩阵最后一维置为 $1$。(或者可以强制单应矩阵所有参数的平方和为 $1$)最后我们需要求解的单应矩阵一共有 $8$ 个维度。而每一对匹配点可以提供两个约束方程,那么我们至少需要四对匹配点才可以求解八个参数。在上一讲的对极约束中,我们求解的问题同样也是一个齐次方程。因此求解方法仍是采用SVD分解来得到。

拾遗

  其实回顾上一讲中的本质矩阵,再关联一下基础矩阵。我们可以知道这两个矩阵之间相差的只是相机内参矩阵。而上述的单应矩阵其实也可以有两种解法。一种是如上的解法,也就是将相机内参矩阵融入问题结构中,与相机位姿一起求解,最后再分解出来,这种方法类对极约束中的基础矩阵的求法。另外一种就是去除相机内参,但是输入参数需要是归一化平面上的点,也就是说我们在第一步就将相机内参用了,无需再用它,那么求解单应矩阵的时候相应的就不需要求解相机内参了,这种方法类对极约束中的本质矩阵的求法。

   由于OpenCV提供的求解函数是基于像素点的,因此单应矩阵中包含相机内参和相对位姿。为了能够和代码对得上,笔者就将内容修改为如上的内容。代码可以参考我的github

参考材料

1.对极几何及单应矩阵

2. 对极约束

3. 仿射变换与投影变换

4. SLAM之特征匹配(一)————RANSAC-------OpenCV中findFundamentalMat函数使用的模型

5.findHomography()函数详解

6. 单应性(Homograph)估计——从传统算法到深度学习

7. 图像拼接(六):OpenCV单应变换模型拼接两幅图像

8. OpenCV 单应矩阵应用:全景图像融合原理

原文地址:https://www.cnblogs.com/yepeichu/p/12612273.html

时间: 2024-07-28 14:26:52

(四)单应矩阵的相关文章

OpenCV,计算两幅图像的单应矩阵

平面射影变换是关于其次3维矢量的一种线性变换,可以使用一个非奇异的$3 \times 3$矩阵H表示,$X' = HX$,射影变换也叫做单应(Homography).计算出两幅图像之间的单应矩阵H,那么应用这个关系可以将一个视图中的 所有点变换到另一个视图中. 上图,最右边图像是将最左边图像进行了一次射影变换,变换到中间图像视图后的图像. 使用OpenCV可以调用库函数findHomography计算两幅图像的单应矩阵,其声明如下 Mat findHomography(InputArray sr

从零开始一起学习SLAM | 神奇的单应矩阵

小白最近在看文献时总是碰到一个奇怪的词叫"homography matrix",查看了翻译,一般都称作"单应矩阵",更迷糊了.正所谓:"每个字都认识,连在一块却不认识"就是小白的内心独白.查了一下书上的推导,总感觉有种"硬凑"的意味,于是又找到了师兄... 神奇的单应矩阵小白:师兄~单应矩阵是什么鬼啊?我看书上的推导,每一步勉强能看懂,但还是不太理解其背后的物理意义,感觉不能转化为自己理解的方式啊师兄:哦,我第一次看的时候也是

SLAM入门之视觉里程计(5):单应矩阵

在之前的博文OpenCV,计算两幅图像的单应矩阵,介绍调用OpenCV中的函数,通过4对对应的点的坐标计算两个图像之间单应矩阵\(H\),然后调用射影变换函数,将一幅图像变换到另一幅图像的视角中.当时只是知道通过单应矩阵,能够将图像1中的像素坐标\((u_1,v_1)\)变换到图像2中对应的位置上\((u_2,v_2)\),而没有深究其中的变换关系. 单应(Homography)是射影几何中的概念,又称为射影变换.它把一个射影平面上的点(三维齐次矢量)映射到另一个射影平面上,并且把直线映射为直线

特征提取与匹配、基础矩阵、单应矩阵、极限约束

Ubuntu16.04 + opencv2.4.9 一.特征提取与匹配 (以ORB特征为例) features.cpp 1 #include<iostream> 2 #include<opencv2/core/core.hpp> 3 #include<opencv2/highgui/highgui.hpp> 4 #include<opencv2/features2d/features2d.hpp> 5 #include<opencv2/calib3d/

线性求解单应矩阵 Homography

定义: 2D单应:给定图像$\mathbb{P}^{2}$中的特征点集$\mathbf{x}_i$和另一幅图像在$\mathbb{P}^{2}$ 中对应的特征点集$\mathbf{x}_{i}^{'}$,  将$\mathbf{x}_i$映射到$\mathbf{x}^{'}_{i}$的射影变换.在实际情况中,点$\mathbf{x}_{i}$和$\mathbf{x}^{'}_{i}$是两幅图像上的点,每幅图像都视为一张射影平面$\mathbb{P}^{2}$ $\mathbf{x}^{'}_{i

OpenCV仿射变换+投射变换+单应性矩阵

本来想用单应性求解小规模运动的物体的位移,但是后来发现即使是很微小的位移也会带来超级大的误差甚至错误求解,看起来这个方法各种行不通,还是要匹配知道深度了以后才能从三维仿射变换来入手了,纠结~ estimateRigidTransform():计算多个二维点对或者图像之间的最优仿射变换矩阵 (2行x3列),H可以是部分自由度,比如各向一致的切变. getAffineTransform():计算3个二维点对之间的仿射变换矩阵H(2行x3列),自由度为6. warpAffine():对输入图像进行仿射

单应性(homography)变换的推导

我们的目标是要得到单应性矩阵 $$ H= \begin{bmatrix} h_{11} & h_{12} & h_{13} \\ h_{21} & h_{22} & h_{23} \\ h_{31} & h_{32} & h_{33} \end{bmatrix}$$ 矩阵$H$会将一幅图像上的一个点的坐标$a=(x,y,1)$映射成另一幅图像上的点的坐标$b=(x_1,y_1,1)$,也就是说,我们已知$a$和$b$,它们是在同一平面上. 则有下面的公式:

李开复给中国学生的第四封信:大学四年应是这样度过(下)

培养兴趣:开拓视野,立定志向 孔子说:“知之者不如好之者,好之者不如乐之者.”我在“给中国学生的第三封信”中曾深入论述了快乐和兴趣是一个人成功的关键.如果你对某个领域充满激情,你就有可能在该领域中发挥自己所有的潜力,甚至为它而废寝忘食.这时候,你已经不是为了成功而学习,而是为了“享受”而学习了.在“第三封信”中,我也曾谈到我自己是如何在大学期间放弃了我不感兴趣的法律专业而进入我所热爱的计算机专业学习的. 有些同学问我,如何像我一样能找到自己的兴趣呢?我觉得,首先要客观地评估和寻找自己的兴趣所在:

webpack4 系列教程(四): 单页面解决方案--代码分割和懒加载

本节课讲解webpack4打包单页应用过程中的代码分割和代码懒加载.不同于多页面应用的提取公共代码,单页面的代码分割和懒加载不是通过webpack配置来实现的,而是通过webpack的写法和内置函数实现的. 目前webpack针对此项功能提供 2 种函数: import(): 引入并且自动执行相关 js 代码 require.ensure(): 引入但需要手动执行相关 js 代码 本文将会进行逐一讲解. >>> 本节课源码 >>> 所有课程源码 1. 准备工作 此次代码