图像到图像的映射
一、单应性变换
单应性(Homography)变换。可以简单的理解为它用来描述物体在世界坐标系和像素坐标系之间的位置映射关系。对应的变换矩阵称为单应性矩阵。在上述式子中,单应性矩阵定义为:
其中,M是内参矩阵
从单应矩阵定义式子来看,它同时包含了相机内参和外参。单应性在计算机视觉领域是一个非常重要的概念,它在图像校正、图像拼接、相机位姿估计、视觉SLAM等领域有非常重要的作用。
对于图像平面内(甚至是三维中的点,后面我们会介绍到)的点,齐次坐标是个非常有用的表示方式。点的齐次坐标是依赖于其尺度定义的,所以,x=[x,y,w]=[ax,ay,aw]=[x/w,y/w,1]都表示同一个二维点。因此,单应性矩阵H也仅依赖尺度定义,所以,单应性矩阵具有8个独立的自由度。我们通常使用w=1来归一化点,这样,点具有唯一的图像坐标x和y。这个额外的坐标是的我们可以简单地使用一个矩阵来表示变换。
实现对点进行归一化和转换齐次坐标的功能:
def normallize(points):
"""在齐次坐标意义下,对点集进行归一化,是最后一行为1"""
for row in points:
row /= points[-1]
return points
def make_homog(points):
"""将点集(dim×n的数组)转换为齐次坐标表示"""
return vstack((points,ones((1, points.shape[1]))))
下面让我们来一起探讨如何设计用于估计单应性矩阵的算法,然后看一下使用仿射变换进行图像扭曲,使用相似变换进行图像匹配,以及使用完全投影变换进行创建全景图像的一些例子:
1.1 直接线性变换算法
概念:
直接线性变换(DLT)是建立像点坐标仪和相应物点物方空间坐标之间直接的线性关系的算法。特点:不需要内外方位元素;适合于非量测相机;满足中、低精度的测量任务。
DLT(Direct Linear Transformation,直接线性变换)是给定4个或者更多对应点对矩阵,来计算单应性矩阵 H 的算法。
我们首先讨论由给定2D到4D的四组点对应
确定H的直接线性算法。变换由方程
给出。注意这是一个齐次矢量方程;因此3维矢量Xi’和HXi不相等,它们有相同的方向,但在大小上可能相差一个非零因子。该等式可以用矢量叉乘:
表示,由该表示式可推出H的一个简单线性解。
如果将矩阵H的第j行记为h^j*T,那么:
记
则叉积可以显示地写成:
因为对j=1,2,3,
皆成立,这就给出关于H元素的三个方程,并可以写成下列形式:
这些方程都有Ai*h=0形式,其中Ai 是3x9的矩阵,h是由矩阵H的元素组成的9维矢量。
其中hi是h的第i个元素。
求解H:每组点对应给出关于H元素的两个独立的方程。给定四组这样的点对应,便获得方程组 Ah=0,其中A是由每组点对应产生的矩阵行Ai构成的方程组的系数矩阵,h是H未知元素的矢量,我们只求h的非零解,因为我们对平凡解h=0毫无兴趣。变换矩阵H一般仅能确定到相差一个尺度,因此解h给出所要求的H。
具体代码如下:
def H_from_points(fp, tp):
"""使用线性DLT方法,计算单应性矩阵H,使fp映射到tp。点自动进行归一化"""
if fp.shape != tp.shape:
raise RuntimeError('number of points do not match')
# 对点进行归一化(对数值计算很重要)
# --- 映射起始点 ---
m = mean(fp[:2], axis=1)
maxstd = max(std(fp[:2], axis=1)) + 1e-9
C1 = diag([1/maxstd, 1/maxstd, 1])
C1[0][2] = -m[0]/maxstd
C1[1][2] = -m[1]/maxstd
fp = dot(C1,fp)
# --- 映射对应点 ---
m = mean(tp[:2