拓冰建站拓冰建站
首页 / 资讯中心 / 正文

基于YOLO的车辆目标检测MATLAB仿真实现与调参指南

简介面向高校本硕博及科研人员的基于YOLO网络的行驶车辆目标检测Matlab仿真方案可用于车辆检测算法编程学习、课题复现与教学演示。资源完整覆盖数据准备、网络构建、模型训练和检测输出等关键环节包含338张车辆图像样本、4个Matlab脚本、4个mat数据文件及说明文档运行主程序Runme_.m即可观察检测效果结合操作录像能直观理解YOLO网络结构、特征提取与边界框回归过程。压缩包共349个文件约213.79MB其中mp4和avi双版本操作视频提供了从环境配置到调试排错的完整演示可避免初学者在路径设置、函数调用等环节反复踩坑。目前已有1881人学习使用资源目录结构清晰既适合刚接触YOLO的本科生快速上手也方便研究生在高阶实验中直接扩展是一份实用性与教学性兼备的车辆目标检测素材。1. 一份 YOLO 车辆检测的 MATLAB 工程先别急着双击 Runme_.m我拿到过不少标着基于 YOLO 的行驶车辆目标检测 MATLAB 仿真的压缩包里面通常是一段Runme_.m、一个操作录像0023.avi以及image006.jpg到image041.jpg一类的样本帧。多数人第一反应是双击主程序看效果但真正值得花时间的反而是后两个文件操作录像能告诉你工程路径依赖样本帧决定了 anchor 和输入尺寸该怎么配。这篇文章把 YOLO 目标检测流程从原理、数据准备、训练参数到运行排错拆开讲适合需要交课程设计、复现论文或想在纯 MATLAB 环境里把车辆检测跑通并改成自己数据的读者。文中代码以 MATLAB R2021a 为基准低版本需要先确认工具箱函数是否支持。2. YOLO 目标检测核心网格、anchor 与损失函数在车辆场景下的取舍YOLO 从第一代到现在已经跨了很多版本但车辆检测这类中尺度目标任务里真正要理解的不是网络层数而是三个机制网格回归、锚点框和损失函数。这三个点直接决定你后面改参数时是瞎调还是有的放矢。2.1 一次回归的网格机制YOLO 把输入图划分成 S x S 的网格每个网格负责预测中心落在该网格内的目标。和 Faster R-CNN 式的两阶段检测不同YOLO 用一次前向传播直接输出边界框坐标、置信度和类别概率所以目标检测流程被压缩成了一个回归问题。以车辆为例假设输入图是 416x416网格数是 13x13那么每个网格的感受野覆盖约 32x32 像素。一辆在画面里占 120x90 像素的轿车中心点落在某个网格内该网格需要预测出(x, y, w, h)四个量其中 x、y 是相对网格左上角的偏移w、h 是相对整张图宽高的比例。这里有个容易忽略的点网格只能决定谁来负责这个目标而目标大小是否合适要看 anchor 与真实框的 IoU。2.2 anchor 先验框选多大取决于车辆在图像中的占比anchor 是 YOLO 给每个网格预设的一组宽高模板。对行驶车辆这种水平方向占主体、比例集中在 0.8:1 到 2.5:1 的目标先验框选得像正方形会让训练初期损失很高。我一般会先统计数据集里所有真实框的宽高分布然后用 k-means 在归一化宽高上聚出 6 个中心作为 anchor。MATLAB 的训练接口允许直接传 anchor 矩阵例如% 输入尺寸 416x416anchor 为宽高像素值 anchorBoxes [ 20 32; 45 60; 80 90; 120 150; 180 220; 280 300];每行对应一个先验框宽高单位是像素顺序没有硬性要求。车辆目标在画面边缘或远处时小 anchor 会优先负责小目标近处的大车由大 anchor 负责。如果训练样本里目标普遍在 100x100 以上却给了一堆 20x32 的 anchor网络训练时大部分负样本会集中在小 anchor 上导致召回率偏高但定位精度下降。2.3 损失函数拆开看YOLO 损失函数分为位置、置信度、分类三块但不同版本处理方式差异很大。YOLOv2 用的是简单的均方误差YOLOv3 把分类损失改成二值交叉熵YOLOv4 进一步引入了 CIoU 和焦点损失的思想。下表是一个常见对比版本位置回归置信度损失分类损失适用场景YOLOv2MSEMSEsoftmax目标尺度相对统一YOLOv3MSEBCEBCE多尺度小目标明显改善YOLOv4CIoUBCE focalBCE密集、遮挡场景更好在 MATLAB 里运行的是 YOLOv4 检测器时损失函数变化主要体现在宽高回归不再直接用 w、h 的平方误差而是计算 CIoU。下面这段是用于理解损失构成的简化代码不是可以直接替换进训练循环的实现function loss vehicleYoloLoss(pred, target, objectMask) % pred: 网络输出的边界框参数 % target: 真实框参数 % objectMask: 1 表示该网格负责正样本 xyLoss sum(sum((pred.xy - target.xy).^2, 3) .* objectMask); whLoss sum(sum((sqrt(abs(pred.wh)) - sqrt(abs(target.wh))).^2, 3) .* objectMask); confLoss sum(sum((pred.conf - target.conf).^2, 3) .* objectMask); classLoss sum(sum(crossentropy(pred.class, target.class), 3) .* objectMask); loss xyLoss whLoss confLoss classLoss; endobjectMask是关键只有真实目标中心点所在的网格才会反向传播位置和分类梯度其余网格只参与置信度损失计算。这样做的目的是让网络把大部分表达能力留给真实目标区域。sqrt开根号处理是因为宽高跨度大直接算差值会让小目标的值被大目标淹没。实际 YOLOv4 使用 CIoU把重叠面积、中心距离和长宽比统一进一个指标训练曲线更稳定但概念上仍是这四个部分。3. 数据准备与标注格式把 image016.jpg 变成可训练的 boxLabelDatastore进入 MATLAB 实现前数据准备排在第一位。YOLO 训练不认文件夹里有图片就行它需要图片和对应的边界框标签成对出现。这个工程里能看到image006.jpg、image016.jpg、image033.jpg等文件但没有单独列出标签文件常见做法是把标签放在每个图片同名.txt里或者集中在一个 labels 目录。先从目录加载开始。3.1 当前文件夹与工程目录组织运行要求里专门强调matlab 左侧当前文件夹窗口必须是当前工程所在路径这一点不是废话。MATLAB 的函数搜索路径和文件读取路径并不总是一致如果你的工作目录切到了别的文件夹Runme_.m里的相对路径会立刻失效。代码开头可以用一段防御性判断兜底if ~isfile(Runme_.m) error(当前文件夹不是工程根目录请在 MATLAB 主界面的当前文件夹窗口切换过来); end判定依据是当前目录下是否存在Runme_.m这比检查某个图片文件更可靠。实际操作时打开 MATLAB 后直接进到工程压缩包解压出的目录再运行Runme_.m。操作录像操作录像0023.avi里演示的也是这个动作。3.2 把 YOLO 格式标签转成 boxLabelDatastore 需要的 tableMATLAB 的检测器训练需要boxLabelDatastore它要求输入是一个两列表格第一列是图片路径第二列是边界框元胞数组。YOLO 的 txt 标签通常保存的是归一化后的[class_id, x_center, y_center, width, height]需要转换一下。下面是一个通用转换函数假设图片在images/下标签在labels/下文件同名function trainingData loadVehicleData(imageDir, labelDir) imds imageDatastore(imageDir); labelFiles string(imds.Files); labelFiles replace(labelFiles, imageDir, labelDir); labelFiles replace(labelFiles, .jpg, .txt); numImages numel(imds.Files); boxesByImage cell(numImages, 1); labelsByImage cell(numImages, 1); for i 1:numImages fid fopen(labelFiles(i), r); raw textscan(fid, %f%f%f%f%f); fclose(fid); classIDs raw{1}; xc raw{2}; yc raw{3}; w raw{4}; h raw{5}; % 归一化坐标转像素坐标 I readimage(imds, i); imgW size(I, 2); imgH size(I, 1); boxes zeros(numel(xc), 4); for j 1:numel(xc) x1 (xc(j) - w(j) / 2) * imgW; y1 (yc(j) - h(j) / 2) * imgH; boxes(j, :) [x1, y1, w(j) * imgW, h(j) * imgH]; end boxesByImage{i} boxes; labelsByImage{i} repmat(vehicle, size(classIDs)); end trainingData table(imds.Files, boxesByImage, ... VariableNames, {imageFilename, vehicle}); end这段代码里textscan按空格读取 YOLO 五行数据x_center和y_center是相对整张图的归一化值所以要乘以图片宽高得到像素坐标。MATLAB 的边界框格式是[x, y, width, height]注意不是 xmin、ymin、xmax、ymax。转换后每一行对应一张图boxesByImage是一个 Nx4 矩阵N 是该图的目标数。如果某个图片没有目标这一行必须是空数组[]否则训练时报错。3.3 数据增强与训练集划分车辆检测最容易遇到的增强手段是随机水平翻转、色彩抖动和随机缩放。MATLAB R2021a 里可以用transform对 combined datastore 做增强但要注意边界框要跟着图片一起变换。翻转后x 坐标变成imgWidth - x - width。常见的写法是自定义一个增强函数再传给transform。训练集与验证集的划分我一般按 8:2 做rng(2024); numImages height(trainingData); idx randperm(numImages); trainIdx idx(1:floor(numImages * 0.8)); valIdx idx(floor(numImages * 0.8) 1:end); trainData trainingData(trainIdx, :); valData trainingData(valIdx, :);划分时用randperm固定随机种子保证复现性。对于这项工程的图片数量如果只有十来张训练时数据量不够模型很容易过拟合到具体图片后面会讲到用数据增强和早停来缓解。4. Runme_.m 主流程拆解YOLOv4 训练与测试代码怎么改这一步是整个工程的主干。运行前先确认已经安装了 Computer Vision Toolbox、Deep Learning Toolbox、Image Processing Toolbox以及可选的 Parallel Computing Toolbox。MATLAB R2021a 中的 YOLO 目标检测器接口是yolov4ObjectDetector不要自己从零搭 darknet这个函数已经把网络结构和 COCO 预训练权重封装好了。4.1 主程序与子函数的边界工程目录里除了Runme_.m还有其他子函数文件运行要求写明不要直接运行子函数文件。原因是子函数依赖主程序里已经赋值的变量单独运行会出现Undefined function or variable。主程序的逻辑是加载图片、构造数据、设置 anchor、训练、测试。子函数只负责其中一小步。4.2 训练参数与 anchor 的设定在Runme_.m中训练部分核心代码如下% 输入尺寸416x416车辆目标多为中尺度不推荐偏小 inputSize [416 416]; % 根据车辆宽高统计得到的 anchor anchorBoxes [ 20 32; 45 60; 80 90; 120 150; 180 220; 280 300]; % 使用 COCO 预训练权重类别改为 vehicle baseDetector yolov4ObjectDetector(tiny-yolov4-coco, vehicle, ... anchorBoxes, inputSize); % 训练选项 options trainingOptions(sgdm, ... InitialLearnRate, 0.001, ... LearnRateSchedule, piecewise, ... LearnRateDropFactor, 0.1, ... LearnRateDropPeriod, 10, ... MiniBatchSize, 8, ... MaxEpochs, 30, ... Shuffle, every-epoch, ... VerboseFrequency, 20, ... Verbose, true, ... Plots, training-progress, ... ExecutionEnvironment, cpu); % 训练 detector trainYOLOv4ObjectDetector(baseDetector, trainData, options);说明几个参数。InitialLearnRate是 0.001 在城市道路、白天光照这类样本上比较稳如果损失曲线反复震荡改 0.0005。LearnRateDropPeriod设为 10意思是每 10 轮学习率降到原来的 0.1这样后期参数更新步长变小。MiniBatchSize取决于显存或内存CPU 训练时 8 是安全值批量再大内存可能吃紧。ExecutionEnvironment设为cpu时训练速度会比较慢但在没有 NVIDIA GPU 的普通笔记本上能跑通如果机器有显卡并装了 CUDA可以把cpu改成gpu训练时间能缩短一个数量级。4.3 测试阶段与检测可视化训练完成后Runme_.m会读取测试图片并画框。这里注意detect返回的 bboxes 是 Nx4 矩阵每行[x, y, width, height]和第三章转换格式保持一致。示例代码testImage imread(image033.jpg); [bboxes, scores, labels] detect(detector, testImage, Threshold, 0.5); if ~isempty(bboxes) annotatedImage insertObjectAnnotation(testImage, Rectangle, ... bboxes, cellstr(labels), FontSize, 12, LineWidth, 2); else annotatedImage testImage; end imshow(annotatedImage); title(sprintf(检测到 %d 辆车, size(bboxes, 1)));Threshold是置信度阈值0.5 表示置信度高于一半的框才保留。想看到更多候选框就降到 0.3但这时误检也会增多。insertObjectAnnotation的scores可以以第 5 个参数传入显示出每个框的置信度数字方便判断检测器是没找到还是找到了但置信度低。检测阶段还有一个容易踩的地方detect函数默认会把输入图片 resize 到训练时设置的inputSize所以你直接传入一张 1920x1080 的图也能跑但检测框坐标会自动映射回原图尺寸不需要自己写坐标变换。车辆密集时YOLO 会输出大量重叠框selectStrongestBbox可以在检测后做 NMS 合并[bboxes, scores] selectStrongestBbox(bboxes, scores, ... RatioType, Min, OverlapThreshold, 0.5);OverlapThreshold越大允许保留的重叠框越多对贴得很近的车辆0.4 到 0.5 之间表现比较合理。太小会漏掉并排的车太大则会出现一个目标两个框。5. 运行验证与进阶调参从损失不降到小目标漏检真正把Runme_.m跑起来只是第一步后面验证效果和调参才是重点。这里给出我在车辆检测任务里常用的检查顺序和几个坑。5.1 运行前检查与常见报错现象原因处理方式Undefined function yolov4ObjectDetector版本低于 R2021a 或工具箱缺失安装 Deep Learning Toolbox 和 Computer Vision ToolboxInvalid training databoxLabelDatastore 中有空标签检查boxesByImage是否为空 cell损失停在负数或 NaN学习率过大或输入包含 NaN 像素调低InitialLearnRate确认图片读取正常训练不收敛损失不下降anchor 完全脱离目标尺寸重新统计真实框宽高聚类出 anchor检测结果全为 0 个框置信度阈值太高、目标过小降低Threshold到 0.3检查输入尺寸第一种报错最常见。MATLAB 的版本号在网上经常被讨论但工程本身只需要matlab2021a 或者更高版本。运行前在命令行输入ver(deep)可以查看 Deep Learning Toolbox 版本如果显示不存在说明安装不完整。5.2 验证检测精度的量化方法光看一两张图不够工程里提供了多帧图片可以把所有测试图片跑一遍并计算平均精度。常见做法是detectionResults detect(detector, valData, Threshold, 0.2); [ap, recall, precision] evaluateDetectionPrecision(detectionResults, valData); fprintf(车辆检测平均精度 AP %.3f\n, ap);valData必须是和训练数据相同格式的 table也就是第三章构造的那种两列表。Threshold在评估时通常设置得较低因为 NMS 之后只保留最优框低阈值可以在召回率层面看到模型真实能力。AP 在 0.6 以上算可用低于 0.4 时不要急着加网络深度先回去看 anchor 和训练样本数量。5.3 小目标漏检怎么调行驶车辆目标检测的小目标通常指远处车道上的车辆在 416x416 输入下可能只有 25x25 像素左右。遇到这类漏检优先把输入尺寸从 416 提到 608比如设置inputSize [608 608]。这会增加计算量但小目标的分辨率直接翻倍AP 往往有可观提升。如果目标还是偶尔丢失第二个有效手段是调整 anchorBoxes 的最小一行把最小的 anchor 改成更贴近小车的尺寸。比如把第一行从20 32改成10 18让网络在小候选框上有更多回归能力。我通常在训练 20 轮后跑一次验证集统计漏检目标的真实框宽高和当前最小的 anchor 对比差距超过 1.5 倍就需要更新。第三个手段是检查图片标注是否准确。如果标注框比目标实际轮廓大了一圈CIoU 损失里长宽比惩罚项会让网络预测出偏大的框小目标之间又容易互相覆盖。对image006.jpg这类远处小车的样本标注框收紧到车体轮廓比换网络更有效。改动完标注后删除保存的 checkpoint重新从第四章第 4 行的trainYOLOv4ObjectDetector开始训练即可。本文还有配套的精品资源点击获取
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门