当我们看火车轨道的时候总在某个距离上看到两条轨道重合到一起后消失。
原图四个点选择:
下面的代码是智能驾驶系统项目中的源码,这里把Opencv中的接口稍微封装了一下,其中有些与透视变换无关的参数,可以忽略不管;比较重要的一点是:这里的原图的四个点是通过车载摄像头的标定信息计算出来的,可以通过车载摄像头的标定信息计算出车载摄像头的消失点,找到消失点之后,四个点的选取就比较容易了;透视图的四个点就更好选取了,只要需要保证四个点构成一个正矩形就行了,四个点之间的像素距离可以根据标定信息计算,这样能够最大程度上让鸟瞰图的尺寸比例更接近现实世界的尺寸比例关系。
//参数为原图像、透视图、四个原图上的对应点
bool IpmTransform::executeipm(Mat& img,Mat& dst,Point2d P1,Point2d P2,Point2d P3,Point2d P4)
{
if (img.data)
{
Point2f corners[4];//原图四个点
Point2f corners_trans[4];//逆透视图四个点
//**车载场景图象的其他参数**//
float roi_x0=0;
float roi_y0=228;
float ROI_HEIGHT=30000;
float ROI_WIDTH=3750;
//************************//
corners[0] = P2;
corners[1] = P3;
corners[2] = P1;
corners[3] = P4;
//设定逆透视图的宽度
float IPM_WIDTH=500;
float N=5;
//保证逆透视图的宽度大概为N个车头宽
float sacale=(IPM_WIDTH/N)/ROI_WIDTH;
float IPM_HEIGHT=ROI_HEIGHT*sacale;
//逆透视图初始化
dst=Mat::zeros(IPM_HEIGHT+50,IPM_WIDTH,img.type());
corners_trans[0] = Point2f(IPM_WIDTH/2-IPM_WIDTH/(2*N),0); //P2
corners_trans[1] = Point2f(IPM_WIDTH/2+IPM_WIDTH/(2*N),0); //P3
corners_trans[2] = Point2f(IPM_WIDTH/2-IPM_WIDTH/(2*N),IPM_HEIGHT); //P1
corners_trans[3] = Point2f(IPM_WIDTH/2+IPM_WIDTH/(2*N),IPM_HEIGHT); //P4
//计算原图到逆透视图和逆透视图到原图的变换矩阵
warpMatrix_src2ipm = getPerspectiveTransform(corners, corners_trans);
warpPerspective(img, dst, warpMatrix_src2ipm, dst.size());
//标出两组点
for(int i=0;i<4;i++)
circle(img,corners[i],5,Scalar(0,255,255),4);
for(int i=0;i<4;i++)
circle(dst,corners_trans[i],5,Scalar(0,255,255),4);
imshow("img",img);
imshow("dst",dst);
}
else
{
cout << "NO IMAGE!!!" << endl;
return false;
}
return true;
}
参考: