十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

MATLAB车辆检测实战:从背景差分到YOLO的完整指南

MATLAB车辆检测实战:从背景差分到YOLO的完整指南 简介一套基于MATLAB的车辆检测系统源码资源包面向图像处理与计算机视觉初学者与开发者帮助读者理解车辆目标检测的完整技术链路。资源共一百零四个文件以一百零一张BMP图像、两个M脚本、一段AVI视频为核心压缩包约十三点五三MB目录整理清晰可按脚本、图像、视频三类材料对照学习。目前已有二千三百四十四人学习浏览适合作为课程设计或入门实践的参考资料。内容覆盖图像读取、灰度化、直方图均衡化、噪声去除等预处理方法Canny边缘检测与Harris角点检测等经典特征提取算子以及阈值分割、区域生长、背景建模、光流计算等目标定位与运动分析技术同时讨论了数据集标注、模型训练思路以及利用MATLAB Coder进行实时性优化的可行方案。通过结合代码、图像样本和视频素材读者能够掌握车辆检测各环节的编程实现细节包括视频帧序列处理、检测结果评估指标如精度、召回率、F1分数等实用技能为后续深入学习基于深度学习的检测模型打下坚实基础。 前几天有个朋友跑来问我“想用MATLAB做车辆检测网上代码看了一堆还是不知道从哪下手这东西到底靠不靠谱”我当时就回了一句靠谱但你要是想靠复制粘贴跑通一个能用的检测程序八成要卡在半路。车辆检测这个需求听起来很具体真做起来从视频读入、背景建模、前景提取到最后的框选和误检过滤每一步都有讲究而且每一步都可能让你怀疑人生。这篇就把“车辆检测MATLAB”这套组合的完整链路拆开讲一遍顺便把我实际踩过的坑和一些不太会写进文档里的细节都交代清楚。适合刚接触视觉或是目标检测的初学者也适合正在做课程设计、毕业设计或者只想快速验证一个车辆检测想法的人。不管你最后选传统方法还是深度学习这套流程都能帮你少走不少弯路。1. 先想清楚车辆检测在MATLAB里到底怎么落地1.1 三条路线怎么选车辆检测的核心任务就是“在图像或视频里把车找出来”。在MATLAB里做这件事主流路线大致有三条传统图像处理、手工特征加机器学习、深度学习目标检测。很多人一上来就问“有没有现成代码”其实代码是最末端的东西真正决定项目难度和工作量的是你选哪条技术路线。传统图像处理路线背景差分、帧差法。适用固定摄像头、背景基本不变的场景实现最快也最容易理解。手工特征加机器学习路线HOG、Haar特征配合SVM或级联分类器。适用于目标形态相对固定、数据量可控的场景。深度学习路线YOLO、Faster R-CNN、SSD这类目标检测网络。适合光照多变、遮挡多、背景复杂的真实道路环境效果最好但对数据和算力都有要求。我给的建议一直没变第一版先做传统方法把整个流程跑通。因为后续做特征提取和深度学习时视频读取、预处理、后处理这些代码几乎都能复用而且你调试传统方法时形成的直觉对你理解深度学习里那些参数非常有帮助。很多人一上来直接上YOLO出了问题连从哪排查都不知道。1.2 动手之前先搞清楚三件事第一相机是固定的还是移动的。固定监控视角最幸福背景差分直接事半功倍要是车载相机那种移动视角背景差分基本失效你只能靠特征或深度学习。第二你要做的是“判断路上有没有车”还是“给出每辆车的位置”。前者简单很多后者才是真正的目标检测难度差一个量级。第三你有没有标注数据。深度学习训练前需要给每辆车画框我说句实在话数据标注经常是整个项目里最耗时的环节很多人把成本全算在训练上结果三个框的标注做了一周。我在实际项目里的习惯是接到需求先问这三个问题再决定技术方案。方案定错了后面再努力也是南辕北辙。2. 传统方法完整流程从视频到车辆框2.1 视频帧读取和预处理先用MATLAB自带的VideoReader把视频读进来。这个函数比很多人想象中好用视频格式兼容性也不错MP4、AVI基本都没问题。读取帧的常规写法是v VideoReader(traffic.mp4); while hasFrame(v) frame readFrame(v); % 每帧处理 end接下来是预处理。我强烈建议第一件事就是把彩色图转灰度用im2gray而不是rgb2gray新版本里im2gray是推荐用法能避免一些警告。处理之前把分辨率降到一半甚至更小也很关键grayFrame imresize(im2gray(frame), 0.5); grayFrame imgaussfilt(grayFrame, 2);imresize到0.5不是随便定的。像素少四分之三后续所有运算都快很多而车辆检测对分辨率没有那么敏感降到一半对准确率影响很小。imgaussfilt是高斯滤波用来削弱传感器噪声尤其是低光照环境下不滤波的话背景差分结果会特别脏全是噪点。滤波半径我一般取1.5到2之间太大容易把车辆边缘也模糊掉。另外一个细节是不要对每一帧都做完整处理。视频每秒几十帧车辆在相邻帧里几乎没有位移隔几帧跑一次检测效果几乎没差别但速度能翻几倍。这个优化在第5章还会再讲。2.2 背景建模与前景提取背景建模是传统方法的核心。最简单的做法是取视频前30帧的平均值作为背景模型然后把当前帧跟背景做差分差值超过阈值的像素就是前景。代码大概是这个思路v.CurrentTime 0; % 回到视频开头 numInitFrames 30; count 0; bg []; while hasFrame(v) count numInitFrames frame im2gray(imresize(readFrame(v), 0.5)); if isempty(bg) bg zeros(size(frame), double); end bg bg double(frame); count count 1; end bg uint8(bg / count);这里有个小坑如果你已经用readFrame读到过视频末尾直接用v对象再次readFrame会报错或者返回空必须先把CurrentTime重置为0让视频从头开始。我当时第一次写就卡在这以为是程序逻辑问题查了半天才发现是视频流位置不对。背景建好之后前景提取很简单fg abs(double(grayFrame) - double(bg)) 30;阈值30是经验值光照好的场景可以调到25画面噪点多就调到40或50。这个阈值是整个算法里最值得花时间调节的参数。平均背景法最大的问题是一旦光照变化就崩。最简单的升级是让背景持续更新alpha 0.05; bg (1 - alpha) * bg alpha * double(grayFrame);alpha就是背景学习率0.05表示每一帧有5%的信息被替换成新的。这样背景能慢慢适应光照变化不会因为几秒钟的云影整个系统就失灵。我从固定背景切到动态背景之后误检率肉眼可见地下降强烈建议你直接用动态版本。2.3 形态学处理、候选框生成与筛选差分出来的前景图经常会有很多空洞和碎点直接提取BoundingBox会得到一堆残缺框。这时候需要用形态学操作整理一下fg imopen(fg, strel(disk, 2)); % 去掉小噪声 fg imclose(fg, strel(disk, 5)); % 填补车身内部空洞 fg bwareaopen(fg, 200); % 删除面积小于200像素的区域imopen先腐蚀再膨胀作用是消除细小噪点imclose正好相反能把车身内部纹理造成的空洞填上。disk半径怎么选要根据你的图像分辨率来分辨率降为0.5后2和5这两个值比较稳妥。接下来用regionprops提取候选框stats regionprops(table, fg, BoundingBox, Area); areas stats.Area; boxes stats.BoundingBox; % 面积筛选 validIdx areas 500; boxes boxes(validIdx, :);面积筛选之后还要做形状筛选。车辆的宽高比一般在0.8到2.5之间太扁太窄的基本都是噪声或阴影区域。可以用宽高比过滤一遍for i size(boxes, 1):-1:1 w boxes(i, 3); h boxes(i, 4); ratio w / h; if ratio 0.8 || ratio 2.5 boxes(i, :) []; end end注意循环一定要从后往前删行否则删掉一行之后索引就全乱了这是MATLAB操作里特别容易犯的错。到这里一个能工作的车辆检测流程就已经完整了。我当时第一次跑通这个流程看见检测框整整齐齐框住马路上的车那种成就感真的难以形容。3. 从HOG特征到深度学习精度不够时的升级路径3.1 HOG加SVM的检测器搭建背景差分对付固定场景很好用但换个视角或者路上有行人走动误检就会明显增多。这时候第二道菜该上场了HOG特征加SVM分类器。HOG方向梯度直方图本质上是统计图像局部区域内边缘方向的分布车辆的外形轮廓相对规整HOG特征能很好地描述这种结构。在MATLAB里提取HOG特征很直接[features, visualization] extractHOGFeatures(img, CellSize, [8 8]);CellSize取8是比较平衡的选择太小特征维度爆炸太大又丢失细节。实际搭建检测器时你需要准备正样本车辆图和负样本非车辆图全部缩放成固定大小比如64乘64提取特征之后用fitcecoc或者fitcsvm训练一个二分类器。滑动窗口检测是HOG方法里最绕不开的痛你需要在图像上以不同缩放比例、不同位置不断截取窗口每个窗口都提取特征再分类计算量非常大。MATLAB其实提供了trainCascadeObjectDetector可以用级联分类器的方式加速但训练参数多新手容易翻车。我的建议是如果你的业务场景就是固定摄像头背景差分已经够用真要换场景直接上深度学习性价比更高。中间路线适合你有明确需求比如只检测车尾、只检测某一类车型数据量又不大的情况。3.2 用YOLO做车辆检测迁移学习是捷径如果场景复杂到传统方法Hold不住那就别硬撑了直接用深度学习。MATLAB的Computer Vision Toolbox从R2022a开始内置了YOLO v4的支持用起来比很多人想象中简单。尤其香的是MATLAB可以直接加载在COCO数据集上预训练好的YOLO模型类别里本来就包含“car”做迁移学习非常顺手detector yolov4ObjectDetector(coco);这一行代码能让你直接检测出视频里的车辆不需要任何训练。当然直接用预训练模型在特定场景下可能有偏差毕竟是通用模型。想进一步优化你需要自己的标注数据。标注工作用MATLAB自带的Image Labeler App就能做导出一个groundTruth对象作为训练数据imds imageDatastore(trainingImages); blds boxLabelDatastore(gTruth); trainingData combine(imds, blds); options trainingOptions(adam, ... InitialLearnRate, 0.001, ... MiniBatchSize, 4, ... MaxEpochs, 10); detector trainYOLOv4ObjectDetector(trainingData, detector, options);注意几个参数的学习路径初始学习率0.001是迁移学习的常规起点太大loss会震荡太小收敛太慢MiniBatchSize设小是因为显存有限如果你有12G以上的显存可以调到8或16。MaxEpochs从10开始跑先用小迭代数验证整个训练流程没问题再加大迭代数跑正式训练。我刚开始做的时候直接设了100个Epoch跑了三天发现数据加载环节写错了白白浪费一周时间。后来学乖了先跑个1个Epoch确认流程通畅再上完整参数。3.3 检测结果怎么评估才靠谱很多初学者跑通检测之后就直接录屏交差了这其实不够。判断检测器好不好不能只看“看起来能不能框住”要用指标说话。目标检测里最核心的是IoU交并比就是预测框和真实框重叠面积除以合并面积。MATLAB里有现成的bboxOverlapRatio函数不需要自己手写。评估代码大致是[precision, recall, info] evaluateDetectionPrecision(detectionResults, gTruth, 0.5);阈值0.5表示预测框和真实框的IoU超过0.5就算检测成功这是目标检测领域最常用的判定标准。用evaluateDetectionPrecision画出来的PR曲线能直观看到检测器在不同置信度下的精度和召回率表现。我记得第一次认真做评估时发现自己以为效果很好的检测器mAP其实只有0.6左右远低于我的预期。这就是为什么要做评估——直观感受会骗人指标不会。4. 踩坑实录车辆检测最常见的5个问题这部分我直接整理了我在做车辆检测项目时遇到的典型问题很多是网上教程不会写但实操几乎必踩的坑做成速查表方便你对照排查。问题典型现象排查方向解决思路车辆阴影误检车底下多出一大块前景前景区域面积异常大用HSV空间的色度信息抑制阴影光照突变画面闪一下检测框乱跳背景更新跟不上实时亮度提高背景学习率加梯度差分辅助判断多车粘连两辆车连成一个框BoundingBox宽度明显偏大尝试分水岭分割或换深度学习小目标漏检远处车辆检测不到前景面积过小被过滤掉调整面积阈值做多尺度检测训练不收敛Loss不降或震荡学习率太高样本过少降低学习率用预训练权重扩充负样本阴影误检是传统方法里最顽固的问题。车体在地面的阴影和车辆本身是连在一起的区域props会把阴影也框进去导致检测框严重偏大。处理思路是利用HSV色彩空间阴影只让亮度V明显降低但色度H和饱和度S变化不大。所以可以构造一个规则把“变暗但色度接近”的像素从前景中扣除。这个策略能干掉大部分阴影误检。需要注意HSV空间的计算比灰度差分慢不少实时性要求高的话可以考虑只在候选框区域内做阴影抑制而不是全图处理。光照突变比渐变恶劣得多。渐变光照用动态背景能适应但如果是整片云影突然扫过路面背景根本来不及更新整幅画面都可能被判定为前景。我当时的解决办法是引入梯度信息辅助判断光照突变虽然让亮度大幅变化但图像的边缘结构变化很小。用Sobel算子算当前帧和背景的梯度再结合亮度差分综合判定前景能明显减少光照突变导致的虚警。多车粘连靠传统方法很难根治分水岭分割能改善但车辆挨得太近时效果也有限。如果这个需求是常态我建议直接转到深度学习检测器YOLO这类网络天然不会把两个目标框成一个。小目标漏检调试起来有点技巧。车辆在远处就很小前景面积可能只有几十像素直接被bwareaopen删掉。排查时要先把面积过滤和宽高比过滤全部关掉把提取到的候选框全部画出来看先确认“候选框确实生成了”再考虑是不是被过滤规则误删了。这个排查顺序能省很多时间。5. 工程化落地界面封装和实时性优化5.1 用App Designer把检测代码包装成小工具如果你把检测算法跑通了但代码还停留在“Run一下就出一张图”的阶段那只能算完成了一半。做课程汇报、项目交付或者给同事演示一个可视化界面会专业很多。MATLAB的App Designer我强烈推荐它比老旧的GUIDE好用太多控件拖拽即可回调函数清晰。你可以用designer命令打开界面编辑器拖一个坐标轴控件和一个“开始检测”按钮。按钮的回调函数里调用你写好的检测主函数把结果用rectangle函数画在坐标轴上function ButtonPushed(app, event) boxes detectVehicles(app.VideoPath); % 你自己的检测函数 imshow(im); hold on; for i 1:size(boxes, 1) rectangle(Position, boxes(i, :), EdgeColor, g, LineWidth, 2); end hold off; end界面本身不复杂但能让你的程序从“代码能跑”变成“工具能用”。我见过不少项目算法水平差不多最后演示效果好的人总能把关键结果用界面展示得明明白白。这件事的投入产出比很高。5.2 性能优化三板斧车辆检测如果要在视频上实时运行性能优化绕不开。我自己实测下来按投入产出比排序这三招最有效第一降分辨率。这招前面提过imresize到0.5倍速度直接提升三到四倍准确率损失很小。第二跳帧处理。车辆在连续两帧之间的移动通常只有几个像素完全没必要每帧都检测。我的习惯是每2到3帧检测一次中间跳过的帧直接用上一帧的检测结果在人眼看起来几乎没有差别。第三用MATLAB Coder把检测函数转成C代码并编译成MEX。传统图像处理的检测流程纯MATLAB跑的耗时大概在120毫秒每帧降采样加跳帧之后能压到40毫秒左右再把核心函数MEX编译一下基本能到10到15毫秒。第三条优化对纯算法逻辑的改动不大主要是工程层面的操作。实时性优化一定要用profiler先定位瓶颈不要凭感觉优化。我曾花一个下午优化了一个形态学函数结果profiler一跑发现瓶颈在视频解码而不是形态学计算白白浪费了时间。先测量再动手这是性能优化的铁律。最后再说几句掏心窝的话。做车辆检测这类视觉项目最忌讳一上来就追求最先进的算法。我第一次做这个项目时也是老老实实从平均背景做起然后一步步换成动态背景、加形态学优化、上HOG等把原理都吃透了再切YOLO整个过程顺理成章。另外一个我觉得特别实用的习惯是所有预处理和过滤参数单独建一个config.m文件集中管理阈值、面积范围、宽高比都写在文件顶部。这样调参的时候不用满屏找数字出问题时也能快速判断是哪个环节的参数不合理。现在拿到一段新视频我的第一件事永远是看五帧原图确认背景的稳定程度和车辆的大小尺度再决定走哪条技术路线——这个习惯帮我避开了很多无效工作你也可以试试。本文还有配套的精品资源点击获取
返回列表