as you seen,在一些场景下,比如交通监控、道路参数获取、港口码头监控等,需要将相机架设在高处,此时,鉴于复杂的场景环境,基于传统的相机标定方法--即铺设标定板,利用张正友或者Tsai标定方法进行标定,是不现实的。(通俗的说:总不能在马路上摆个标定板,告诉来往的车辆:你等一下,我拍二十张照片你再走,哦,不行,这个角度不行,那个棋盘格角点虚焦了要重拍,你再等一下,估计没标定完,也会被群殴或者被交警抓起来了)。所以,需要开发一套适用于复杂场景的、不需要任何辅助合作目标(比如标定物)的标定方案。
首先,需要准备以下基础知识:
1、科普一下正交消失点的概念。
消失点的概念搞视觉的应该都懂,就是两条平行的直线经透视变换会相交成一点。入门知识,在此不展开。在本方案中,正是用到了三个方向、正交的消失点。
struct VashingPoints
{
cv::Point2d vp1;
cv::Point2d vp2;
cv::Point2d vp3;
};
VP1表示第一个VP,车辆运动方向。
VP2表示第二个VP,地平面中垂直于车辆运动方向,即与VP1垂直。
VP3表示第三个VP,垂直于地平面。
2、需要回顾一下相机的成像模型,即小孔成像原理。入门知识,在此不展开。
下面,贴一下VP1及VP2的检测流程
对VP2的检测使用菱形空间的概念。 假设许多车辆边缘与第二个VP重合开始,它们在积累空间投票。
使用背景边缘模型检测移动车辆上的边缘。
模型每帧都会更新,以处理阴影和其他缓慢的变化。
背景模型用B1 = H1初始化,然后用公式(1)更新Bt,其中平滑系数接近1,此处a = 0.95。
Bt=αBt-1 +(1-α)Ht 公式(1)
Keys:a:<第一个消失点用于约束第二个消失点的位置>
b:<边缘检测采用canny边缘检测算法>
c:采用<级联霍夫变换>及平行空间理论
d:必须满足以下筛选条件:
1、必须由Canny边缘检测器检测。
2、该点属于背景的置信度必须低于预定值阈值(t2),即属于前景(移动车辆)。
3、梯度的大小必须高于预定阈值t1。
4、梯度的方向不能与VP1方向一致,也不得垂直于基线。
5、假设场景近似水平,具有公差水平(±45°)。
求解内参代码
cv::Mat TrafficCalibrationFromVP::getIntrinsicMat(cv::Point2d vp1, cv::Point2d vp2, cv::Point2d pp)
{
CalibrationInfos calinfos;
calinfos.focal = double(sqrt(-(vp1 - pp).dot(vp2 - pp)));//叉乘:.cross
calinfos.IntrinsicMat = (Mat_<double>(3, 3) << calinfos.focal, 0, pp.x, 0, calinfos.focal, pp.y, 0, 0, 1);
return calinfos.IntrinsicMat;
}
求解vp3代码
void TrafficCalibrationFromVP::getVP3(cv::Point2d vp1, cv::Point2d vp2, cv::Point2d pp,double focal, cv::Point2d& vp3)
{
cv::Point3d V1world(vp1.x, vp1.y, focal);
cv::Point3d V2world(vp2.x, vp2.y, focal);
cv::Point3d PPworld(pp.x, pp.y, 0);
cv::Point3d V3world = (V1world - PPworld).cross(V2world - PPworld);
vp3.x = V3world.x / V3world.z*focal+pp.x;
vp3.y = V3world.y / V3world.z*focal+pp.y;
//cout << vp3 << endl;
}
未完待更新……