利⽤OpenCV实现对车流量的统计
⽬录
闲话少絮。开始正题——OpenCV的车流量统计。
调试平台
OpenCV 4.2
VS 2019
汽车识别原理——背景/前景分割算法
如今,检测和提取车辆时候,常⽤的⽅法有MOG2算法和KNN算法。MOG算法是以⾼斯混合模型(GMM)为基础的背景/前景分割算法。它是以2004年和2006年Z.Zivkovic的两篇⽂章为基础的。这个算法的⼀个特点是它为每⼀个像素选择⼀个合适数⽬的⾼斯分布。其主要原理为:在⼀个固定位置和⾓度固定的视频或图像中,提取分割图像或视频中运动的成分。此算法使⽤背景建模的⽅式,将整张图⽚或⼀帧视频分为前景和后景。此算法运⾏时,会将动态的前景与静⽌的后景相减,得出结果即为徐提取的运动物体的图像。
K最近邻算法(KNN)是属于机器学习的⼀种算法。其主要原理为:给定⼀个已训练数据集,对新的输⼊实例,在训练数据集中到与该实例最邻近(注:衡量邻近的标准以具体选取的某个特征⽽⾔,例如下⾯⽰意图中使⽤的特征为欧式距离)的K个实例,这K个实例的多数属于某个类,则判定该输⼊实例同属此类。如下图所⽰:训练者取k值,计算以欧⽒距离k为半径的圆内其他类别的个数,图中中⼼⼩红点以k 为半径的圆内三⾓形个数最多,则判定中⼼⼩红点为三⾓形。
整体结构
整体流程框架图
本程序的主要运⾏流程为:程序运⾏开始,⾸先从⽂件中获取上次保存的光流量检测矩形框数据(顶点坐标和矩形的长宽);其后,分别初始化背景提取对象,使⽤MOG2和KNN两种算法。与此同时,建⽴⼀个⿏标回调函数,⽤于捕获⿏标左键(绘制矩形框)、中键(取消操作)和右键(保存矩形框数据到⽂件)的操作。
此后,程序进⼊主循环状态。程序循环从视频中获取⼀帧的图像,先进⾏压缩处理,以提⾼后续运算速度。之后,将这⼀帧图⽚从RGB转为灰度图⽚。为了祛除灰度后可能出现的⼩⽑刺杂点,再进⾏平滑滤波处理。此后,分别通过MOG2和KNN算法提取前景,并将提取后的视频显⽰出来。与此同时,获取每个矩形框中积分后的亮度和。
最后,两个算法中,分别将实时得到的亮度和与所预设的阈值进⾏⽐较,当满⾜条件后,便认为⼀辆汽车通过矩形框,使得计数器加⼀。如此重复,统计整个视频中的车流量。
主要参数
1. int detectTHD
此参数为预设的亮度阈值。确定是否有汽车经过检测框中,其需要联合上⼀帧积分亮度和本次积分亮度后综合做出决定。
2. cv::Size ls / 2, ws / 2);
此参数可以储存⼀帧视频缩⼩后的⼤⼩。
3. cv::Mat showMat;
此参数⽤于储存最终显⽰的图像矩阵。
主要函数
1. static void onMouse(int event, int x, int y, int flags, void\*)
此函数主要⽤于检测⿏标左键、滑轮(中键)和右键的⼀些操作,⽤于绘制矩形检测框。
2. cv::resize(frame, newframe, newSize);
此函数主要⽤于缩⼩原视频⽐例,提⾼计算机运算速度。
3. bgMOG2-\>apply(greyFrame, mog2RES, update_bg_model ? -1 : 0);以及bgKNN-\>apply(greyFrame, KNN, update_bg_model ? -1 : 0);
apply函数主要⽤于两种算法的前景提取。此后,前景提取后的这帧视频保存于bgMOG2和bgKNN之中。
4. cv::rectangle(showMat, myLanneRect.at(k), cv::Scalar(255, 255, 255), 3);
此函数主要⽤于前景提取后在其上⾯绘制矩形框。
5. cv::integral(subMat, sumMat, CV_32S);
计算车道矩形框亮度积分图。
6. cv::putText();
此函数可以按照要求,在视频图像上显⽰⽂字和统计数字。
测试结果
1. 功能测试
进⾏车流量统计前,应当⾸先根据矩形框中出现车辆时,估算其亮度平均值作为亮度阈值,使其设定为⼀个较为合适的值,增强检测的灵敏性。由下图可知,当程序运⾏后,通过⼿动标记车道检测区域,得到2个矩形检测区。每次获得矩形中的积分亮度结果,当上从亮度结果⼤于阈值,且此次亮度结果⼩于阈值时,使车辆统计结果加⼀。
2. 算法处理时间
由测试结果可知,相较于MOG2算法,KNN算法在运算处理上花费更多的时间,KNN算法时间约为MOG2时间的2倍。同时,算法处理总时间也相对较长,除了两个算法所带来的开销外,仍有其他附加代码所花费的时间。
3. 缩放图⽚前后⽐较
程序中,可以使⽤cv::resize();函数进⾏图⽚的压缩,缩放图⽚对于检测速度有较⼤的影响。不使⽤缩放时,将视频中原始⼀帧的图像进⾏计算,经测试发现,处理速度很慢,显⽰的图⽚有明显的脱帧和卡顿现象,CPU占⽤率相当⾼,与压缩后(上图)相⽐,⽆论使⽤MOG2还是KNN算法,其处理时间均成倍增加。下图为不使⽤缩⼩图⽚尺⼨条件下的处理时间。
4. 矩形检测区亮度阈值的影响
阈值设置的合理性也是车流量检测准确性的⼀个重要指标。过⾼或过低的阈值均不能很好地反映车辆的经过和实现的统计。阈值过低,将会把视频中环境⼲扰噪声和其他运动对象(如三轮车和⾏⼈)当做汽车统计,使得统计结果偏⼤;同理,阈值过⾼,将很难检测到车辆的通过,当车辆进过矩形检测区时,⽆法实现车辆的统计。本程序中,经过检测矩形框内平均值的⼤致估算,将阈值detectTHD设置为900000。
下图中显⽰了当阈值设定过⼩时的状况。右端矩形框(右车道)经过了⼀辆电动车,程序误认为汽车,并错误地将统计结果L1的值从1加为2。
同理,当阈值设置过⼤,也会造成统计的不准确。下图显⽰了当阈值设定过⼤时的状况。可以发现,即使是车辆经过了矩形框,车辆统计变量L0和L1仍为0。
rectangle函数opencv
结论
由以上分析可知,汽车流量的统计可以借助设定矩形区域内的亮度阈值来确定。为识别运动对象(汽车)的状态,可使⽤背景提取算法,如本软件中使⽤到的MOG2和KNN算法。通过⽐较不同算法间的处理时间,我们应当合理选择⼀种耗时短且提取车辆准确性⾼的⼀种算法。此外,识别统计车流量较为重要的⼀环便是设置合理的亮度阈值,亮度阈值设置的合理性直接关系到车流量统计准确性。
附:程序源代码
#include"stdafx.h"
#include<Windows.h>
#include<string>
#include<opencv2/core.hpp>
#include<opencv2/imgproc.hpp>
#include<opencv2/highgui.hpp>
#include<opencv2/features2d.hpp>
#include<opencv2/video.hpp>
#ifdef _DEBUG
#pragma comment(lib, "opencv_world420d.lib")
#else
#pragma comment(lib, "opencv_world420.lib")
#endif
//===【⿏标事件回调函数】===
int detectTHD =900000;//亮度阈值:有车辆经过的;
std::vector<int>  myLanneLightSum_Last;//车道亮度和:上⼀帧的
std::vector<int>  myLanneVihicleCnt;//车道车辆计数器
std::vector<cv::Rect>  myLanneRect;//车道矩形框;显⽰为红⾊;

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。