MOD算法

3 阅读1分钟

MOD算法

前言

MOD的全称是移动目标障碍物检测,目前手里有一套古老的代码来实现的,用的是MOG2和VIBE算法这些,这些算法用不到神经网络,还是我在学校打比赛,做岗哨机器人使用的。可惜组内人员有限,也没有足够的动力转成采用神经网络来实现这个MOD功能。所以用大模型简单的调试一下吧。

正文

这里会这里的代码核心逻辑和细节写在这里。

首先,要梳理出整个算法的输入和输出。输入包括:BEV的鸟瞰图、汽车速度、时间戳、汽车挡位信息。输出就是某个方向的报警信息。

具体流程来说,运动状态的判断:

1、第一步进行图像预处理,a、对于输入的环视拼接图转成灰度图;b、通过当前汽车速度、时间戳、汽车的两次瞬移变化来判断当前的图像是否合理。c、判断图像是否模糊,这里主要通过梯度辐值、通过幅值的均值和方差判断是否在合理的范围内。

//用来评估模糊的经典组合
cv::Laplacian(matImageGray, dst, CV_16S, 3);
cv::convertScaleAbs( dst, abs_dst );
cv::meanStdDev(abs_dst, mu, stddev);  

2、第二步需要通过光流法计算汽车的运动状态。主要还是依赖opencv库中的特征金字塔实现(docs.opencv.org/4.x/db/d7f/…

a、主要接口:calcOpticalFlowPyrLK(prevGray, imgGray, points[0], points[1], status, err, winSize, 3, termcrit, 0, 0.001);

prevGray​ : 上一时刻的图片;

imgGray​: 当前时刻的图片;

points[0]​: 需要追踪的特征点;

points[1]​:追踪后的特征点;

status​: 表示追踪的点是否成功;

winSize​:表示特征金字塔检索窗口

maxlevel​: 如果是0,则表示在原始分辨率;如果是3,则是表示搜索三层。

termcrit​: 表示终止条件;

b、cv::Mat homography = cv::findHomography(pt2, pt1, homoMask, cv::RANSAC);​ 根据上一步的特征点计算二者的单应性矩阵。

根据可以计算出单应性矩阵的点和所有的光流特征点的比例0.33, 则是判断汽车是运动状态。通过归一化单应性矩阵的位移判断汽车的状态。

c、这里还有一个工作,原本的逻辑是选择固定位置的点作为特征点,我这里修改了一下,改成用代码寻找特征点。

cv::goodFeaturesToTrack(imgGray, corners, 300, 0.01, 10, mask);

输入灰度图,输出是角点corners, 300是输出的最多角点数, 0.01是角点质量判断,10是欧氏距离判断(类似nms), MASK是不参于的掩码区域。这里输出的特征点实际上作为每次计算单应性的初始特征点,每次都会重新更新。

到了这一步骤后,整个KIL的过程算是完成了

3、这步主要获取底盘数据,通过前后帧挡位、静止状态位(轮速传感器、IMU等)、车速等信息判断车辆的静止状态。通过光流法和底盘信息协同判断汽车的状态,分为三种静止、运动、转弯。

前后景的筛选,这里主要用了两种前景分割算法,第一种是MOG2;第二种是VIBE算法

MOG2算法,首先默认设置,也就是汽车一直处于一种状态的时候使用。

     pMOG2 = cv::createBackgroundSubtractorMOG2(100, 25, false); // 默认 100 帧历史,25 阈值,false 表示不开启阴影检测
    pMOG2->setVarThreshold(25.0);
    pMOG2->setHistory(int(100));

MOG2其核心思想是:用概率模型去“学习”每一个像素点的历史变化,从而区分什么是背景,什么是运动前景。

高斯分布有三个关键值,均值(记忆中的颜色),方差(允许活动的范围),权重(这个权重的可靠度)。这里每个像素点最多有5个分布。

所以接口中的100的意思就是,大概经过100帧之后才会把新物体固定成背景,25表示的是方差阈值,也就是varthreshold

(CurrentPixelμ)2σ2>varThreshold\frac{(CurrentPixel - \mu)^2}{\sigma^2} > varThreshold

其次,会根据前后帧状态的变化,设定不同的参数,这里不贴具体的参数了。

pMOG2->apply(frameGray, fgMask);​ 更新成二值化背景图,然后通过开闭运算去除背景噪音点,获得最终的效果。

VIBE算法:它为每个像素点存储了一个样本库(Sample Set) 。当你判断一个新像素是否为背景时,直接去样本库里“比对”,如果长得像的样本够多,你就是背景。

分三种考虑啊,第一种剧烈状态进入平稳期,第二种是持续剧烈运动中;第三种则是其他可能

第一部分代码的核心:补偿机制(类似透明底盘),将底盘区域置黑,不要进行干扰。这里主要考虑的是汽车运动的状态。

第二部分则是自己实现的VIBE算法,a、单帧初始化,将原始BEV图中随机8邻域缓存在样本库中;b、判断当前的像素与样本库的距离是否符合阈值,当匹配的次数大于设定的阈值时候,该像素则为背景,芣则为前景像素,但是当连续50帧时候则更新为背景因素。c、更新样本库,分为两次更新,第一次是时间上,直接替换,第二次是空间上,替换相邻像素的样本库。

最后,将两者算法得到的前景进行融合,如果车辆是静止的,要进行阴影去除算法,得到最终的结果。然后通过一些开闭的图像处理算法进行去除噪音点。

4、检测功能

a、首先会把上一步骤的各种小模块进行合并。主要通过欧式距离合并,只考虑合并大框和小框。

b、NMS操作,过滤噪音目标。

5、目标匹配与kalman 追踪

卡尔曼滤波器使用7维状态向量 [x, y, s, r, vx, vy, vs]:
• x, y:边界框中心坐标
• s:尺度(面积 = width × height)
• r:宽高比(aspect ratio = width / height)
• vx, vy, vs:x、y方向和尺度的速度

观察量是:矩形框的对角点。

总结

目前的显示效果是如下图所示,可以看到行人走到某个区域,某个区域进行报警。归根到底,这里实际上就是分为几个步骤,1、通过光流法判断汽车的状态;2、通过MOG2和VIBE算法进行前景提取;3、对前景进行框取,通过匈牙利匹配算法和CV运动kalman 算法进行追踪平滑;4、通过前景的结果进行报警。

image