任务描述
在给出上述待处理图像后,自定义选对应点作(逆)透视变换,使得道路呈俯视无透视状态(即路宽不再有近大远小效果)
透视投影介绍
透视投影指同样的景物在两个不同位置和角度的摄像机上形成的图像之间呈现一种透视关系,它是图形渲染流程中的非常重要的一个步骤,是将三维物体从相机空间变换到视锥体空间,然后再到规则观察体中。在得到相机坐标后,就相当于得到了人眼观察世界中物体的坐标,但是需要把物体映射到一个二维平面上用于显示,投影矩阵就起到把三维坐标映射到二维坐标的作用,同时因为三维空间有深度的概念,因此把Z轴转化成深度。
简单介绍一下将世界坐标系转化到像素坐标系的过程:首先是先将世界坐标系通过旋转平移转换到相机坐标系;然后通过透视投影将相机坐标系转化到图像坐标系,此步用到的三角形相似的关系;最后将图像坐标系通过单位换算以及平移操作转换到像素坐标系。
一、实现方法
在进行透视投影的时候,我并没有预先设定对应点的坐标,而是添加了一个交互功能,通过用户交互的方式进行标注,也就是用户需要先在窗口中通过鼠标点击的方式选择对应点的坐标,然后再将选取的区域进行透视投影,本任务要求对道路进行透视变换,所以我在选择对应点的时候在原图中选择了一段道路。
二、关键代码
1.自定义选对应点
代码如下(示例):
# 用鼠标点击的方式得到点的坐标,注意点要有顺序关系,左上、左下、右下、右上
def get_points():
def determine_point(event, x, y, flags, param):
if event == cv2.EVENT_LBUTTONDOWN:
global num
global p1
p1[num] = [x, y]
num += 1
cv2.circle(img, (x, y), 0, (0, 0, 255))
cv2.imshow("determine_point", img)
if num > 3:
cv2.destroyWindow('determine_point')
cv2.imshow("determine_point", img)
cv2.setMouseCallback("determine_point", determine_point)
2.进行透视变换
代码如下(示例):
M = cv2.getPerspectiveTransform(p1, p2)
newImg = cv2.warpPerspective(img, M, (row, col))
这里使用的函数是opencv的库函数,具体参数可进行自学
三、效果展示
得到的结果如下图所示,在图片下方可以很明显的看出城市道路并没有出现近大远小的效果,但是由于图像质量的问题会出现远处景物出现模糊的现象