在阅读本文之前,应该先阅读朱葛峻的《逆透视变换的一种方法》(下简称《方法》),本文的实现是基于这篇文章的推导的。


本文中提到的方法主要用于智能车竞赛。

虽然在智能车有限的视野和像素内,这种方法有时并不是一种很好的选择。

在谈逆透视变换之前,我们先谈一下真实世界和智能车上安装的摄像头所获取的照片的关系。

世界坐标系下的点要经历平移变换、旋转变换、缩放变换、投影变换而得到摄像头坐标系下的点。前三种变换都是一一映射的变换,即原坐标下的点唯一对应新坐标下的点。

只要知道规则,逆变换就可以完成。

投影变换不是一一映射的变换。

如图,B,C两点在以A点为投影点的变换中落到了屏上同一点。

B,C因为缺少深度的信息,在逆变换中无法区分。

在智能车的应用场景中,所有点都在地面,即Z=0。

就是说,深度信息没有丢失,所以逆透视变换是可以完成的。
在这里插入图片描述

如下图,一张矩形的由摄像头获得的照片,在逆透视变换后变换成了倒梯形,而蓝色阴影所表示的道路则通过变换呈现出俯视图的样子。

在这里插入图片描述

三、代码实现

下面的matlab代码,用来计算 H 和 H d  。

x=[30,30,119,119]  % 依次为A、B、D、C在摄像头获取的照片中的的纵坐标
y=[0,187,0,187] % 依次为A、B、D、C在摄像头获取的照片中的的横坐标
X=[4000,4000,5465,5465]  % 依次为A、B、D、C在逆透视变换后的照片中的的纵坐标
Y=[3000,5720,4132,4580] % 依次为A、B、D、C在逆透视变换后的照片中的的纵坐标

A = [X(1),Y(1),1,0,0,0,-x(1)*X(1),-x(1)*Y(1);
    0,0,0,X(1),Y(1),1,-y(1)*X(1),-y(1)*Y(1);
    X(2),Y(2),1,0,0,0,-x(2)*X(2),-x(2)*Y(2);
    0,0,0,X(2),Y(2),1,-y(2)*X(2),-y(2)*Y(2);
    X(3),Y(3),1,0,0,0,-x(3)*X(3),-x(3)*Y(3);
    0,0,0,X(3),Y(3),1,-y(3)*X(3),-y(3)*Y(3);
    X(4),Y(4),1,0,0,0,-x(4)*X(4),-x(4)*Y(4);
    0,0,0,X(4),Y(4),1,-y(4)*X(4),-y(4)*Y(4)];
B = [x(1);y(1);x(2);y(2);x(3);y(3);x(4);y(4)];

H=A\B;  % 求解H11到H18
H=H'  % 把列向量改成行向量
H=[H,1]  % 获得完整的H的行向量

H11 =H(1);H12 =H(2); H13 =H(3); H21 =H(4); H22 =H(5); H23 =H(6); H31 =H(7); H32 =H(8); H33=H(9);
H=[H11,H12,H13;H21,H22,H23;H31,H32,H33]  % 获得完整的H的矩阵
Hd=inv(H)  % 获得Hd矩阵

fprintf("[[%f, %f, %f], [%f, %f, %f], [%f, %f, %f]]",Hd(1,1),Hd(1,2),Hd(1,3),Hd(2,1),Hd(2,2),Hd(2,3),Hd(3,1),Hd(3,2),Hd(3,3));  % 把Hd矩阵以符合python列表的形式输出
def process(self,img):
    img = np.array(img)

    height = 10000  # 高度限制
    width = 8000  # 宽度限制
    output = np.full((height, width), 0, dtype=np.int)

    Hd=[[1075.629450, 0.000000, -19146.217384], [814.163487, 47.718786, -14582.905023], [0.186940, 0.000000, -2.327535]]
    #  这里把刚从matlab那里得到的
    for x in range(img.shape[0]):
        for y in range(img.shape[1]):
            X = round((x * Hd[0][0] + y * Hd[0][1] + Hd[0][2]) / (x * Hd[2][0] + y * Hd[2][1] + Hd[2][2]))
            Y = round((x * Hd[1][0] + y * Hd[1][1] + Hd[1][2]) / (x * Hd[2][0] + y * Hd[2][1] + Hd[2][2]))
            # 注意由于python的索引从0开始计数,这里的索引和公式里略有差别
            if X>=height:
                X = height-1
            if X<0:
                X=0
            if Y >= width:
                Y = width-1
            if Y<0:
                Y=0
            output[X,Y]=img[x,y]

    return output

效果展示如下。

原图:

在这里插入图片描述

逆透视变换后(因为没有填充,需要放大看):

在这里插入图片描述


————————————————
版权声明:本文为CSDN博主「east_fence」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/east_fence/article/details/106953970