之前都在做道路检测,逆向投影研究,发现openCV提供了简单的,可以直接通过地面上4个或4个以上的点的对应关系获得图像与地平面间相差一个比例系数的逆投影变换,按照openCV给出的测试程序,实验了一下,确实效果不错,但是对于其中几个重要的投影变换函数,以及比例系数的问题,遇到了点困惑,通过仔细阅读文档及实验,思路基本上清晰了。看到网上有多很多人对鸟瞰图的获取,也是不够清晰,因此,写了此篇文章,希望对大家有所启发。
重投影的概念--摘自网上
摄像机斜视拍摄一物体后,形成的图像会发生变形,如果将图像映射到拍摄物体平面上,相当于将相机垂直于拍摄平面,这样就会得到图像的真是形状,由于这种映射相当于将原图重新透视到另一个平面,这种称之为“重投影”。
其实,鸟瞰图的本质就是将图像平面中的信息“重投影”到地平面上,所以,首席要获取两个平面间的投影变换关系H。在程序中,是通过在地平面上放置标定板图像,然后获得地平面上棋盘格图像上四个顶点的坐标(0,0),(widht-1,0),(0,height -1),(wdith-1,height-1),这里一般假定棋盘格单位宽度为1,你可以输入已知的棋盘格宽度信息;同时,在图像平面提取角点,并获得与地平面上四个点对应的角点在图像空间中的坐标值,通过四个坐标点间的对应关系,基于getPerspectiveTransform()函数,获得地平面到图像平面间的投影变换关系H;最后,通过warpPerspective()函数对图像进行逆向映射到地平面空间中。
总结:
根据上述思路,就可以了解鸟瞰图获得的具体思路了。另外,在程序中有一行代码,就是设置Z=25,并将该数值赋值到H矩阵的右下角位置,这里这样做,按照我的理解和测试,我认为是因为之前在设置地平面上标定板的坐标信息时,假定的是每个棋盘格的宽度为1,这样H的意义就成了将图像平面空间一个占据了10~20个像素的棋盘格投影到1个像素上去,同时还考虑整幅图像的显示尺度问题(填充空格),所以,才设置尺度为25或者其他你想要的尺度,这样,相当于每个棋盘格放大了25倍,比较接近我们原始的图像平面空间所在的尺度,可视化会会好很多。
看到空间中,很多人转载了一篇对于鸟瞰图获取的过程有所质疑,但是又没有给出更多解释的博文,感觉转载一个带着疑问的文章不是解决问题的办法,深入了解问题本身,倒找答案才是真正解决了问题,而不是重复着别人存在的疑问,不求甚解。
ps,下面将程序中用到的连个重要函数的说明付在下面,有不解的可以仔细看下
cv::getPerspectiveTransform
Calculates the perspective transform from 4 pairs of the corresponding points
Parameters: |
|
---|
The function calculates the matrix of a perspective transform such that:
where
Comments from the Wiki
Applies a perspective transformation to an image.
Parameters: |
|
---|
The function warpPerspective transforms the source image using the specified matrix:
when the flag WARP_INVERSE_MAP is set. Otherwise, the transformation is first inverted with invert() and then put in the formula above instead of M . The function can not operate in-place.