基于YOLOv4的车辆检测 MATLAB实现

news2024/11/26 23:16:32

目录

摘要

研究背景

算法设计及实现过程

车辆目标数据集的构建

基于YOLOv4的目标检测

对YOLOv4模型进行改进

实验结果及分析

结论与展望

代码实现


摘要

       针对车辆检测,本文提出了一种基于YOLOv4车辆检测算法。制作了一个多天侯、多时段、多场景的车辆目标数据集,对车辆数据集进行手工标注,将其划分为训练集和测试集以便模型使用,经过DarkNet53网络框架进行训练,发现实验结果良好,可满足实际应用的需求。

研究背景

       随着经济的发展,交通拥堵问题凸显,严重影响人民生活水平的提高,构建智能化的交通监测系统对减少交通拥堵、 提高交通运输效率具有重要意义。对车辆目标进行准确、实时的检测是智能交通系统的核心,在现有车辆检测算法研究中,基于深度学习的检测算法成功引起了学者们的关注,特别是针对复杂场景中多个车辆的检测更具挑战性。

算法设计及实现过程

图1  算法设计框图

       深度学习技术主要是对输入的图像进行卷积处理,对特征进行提取并确定目标位置,其在目标识别领取有很好的成效。基于深度学习的目标识别算法主要代表算法有R-CNN、SSD、YOLO等,本文采用的是YOLOv4算法,该算法是one-stage检测中是典型代表,实时性表现良好,且检测速度较快,综合以上优点,我们最终选用它。

车辆目标数据集的构建

       我们考虑到道路上的车辆以及所处的环境均比较复杂,会影响车辆检测的正确率,所以

       我们认为构建一个合适的实时监测数据集是非常重要的。在网上收集到COCO的车辆数据集,并从中找到车辆数据集,储存之后进行图像组合和边界框的创建,框标签数据一同储存。

图2 车辆数据集

基于YOLOv4的目标检测

       YOLOv4算法是在YOLO系列先前版本的目标检测算法的基础上面优化而来且在目标识别领域中比较热门,主要采用的是CSPDarknet53作为主干特征提取网络,其中共有五个大残差块,每个大残差块中所包含的小残差单元个数为1、2、8、8、4,而SPP网络用在YOLOv4中的目的是增强网络的感受野,PANet是在上采样过程之后又加入了下采样的操作,YOLOv3作为Head,最终实现整个YOLOv4算法。

 

图3  YOLOv4 网络结构图

设置训练超参数如下,numEpochs = 90;miniBatchSize = 4;learningRate = 0.001;warmupPeriod = 1000;l2Regularization = 0.001;penaltyThreshold = 0.5;

采用随机梯度下降法(Stochastic Gradient Descent, SGD)。训练过程是在 YOLOv4 权重下进行微调,对其迭代100次完成训练过程。

之后运行测试集中的图像运行检测器,并收集结果,使用平均精度度量评估对象检测器,得到测试集训练后的平均精准度为86%,并保存训练模型和训练后的参数。

最后创建一个检测文件,下载预先下载好的网络,获取COCO数据集的类名和用于训练和预训练模型的anchors,然后进行检测和可视化,结果如下。

图4 检测结果1

       在我们得到结果之后,我们发现在检测过程中检测的速度较慢,在运行程序后30s左右才会出现检测结果,且后面的小型车辆在检测过程中并不能被框选并识别,不能够识别车辆视频流。我们针对发现的问题把模型进行改进。

对YOLOv4模型进行改进

       我们通过第一轮的训练之后,发现在小目标识别的准确率和检测的速度这两个地方,我们的模型会有一些缺陷。所以我们对YOLOv4模型进行优化改进。

      首先是在检测速度这方面,我们想要使YOLOv4模型轻量化来解决。CSPDarknet53是YOLOv4主干特征提取网络,轻量化该结构中两个卷积层的计算结果直接进行通道融合,再共用一BN层和激活函数,这样可以减少网络的计算量,避免这两个卷积模块都单独的计算激活值和批量归一化。使模型轻量化的同时,不会影响最终的实验结果。

       在小目标识别的过程中,我们考虑到可能是在数据集中更多的是单个车辆或者单个环境下导致的,所以我们采用数据增强的方法来进行数据扩充,数据增强是指在图片送入网络前的预处理阶段,通过对输入图片进行一些微小的改变操作如随机擦除、调整饱和度等,使得神经网络认为这是一张全新的图片达到增加数据量的效果。这样做不仅可以增大目标检测的数据量,还能够丰富数据集中检测目标的背景,减少背景被误判为检测目标的概率。 

图5 数据增强过程图

实验结果及分析

       经过我们的改进,我们在运行程序之后得到测试集的准确率为91%,20s左右即可得到检测结果,并且小型车辆也可以进行较好的识别检测,并且我们将视频按照每帧分开,同样也实现了视频流的识别。通过对模型进行训练并验证发现,改进的模型在精准度和检测速度方面比原模型都要好。

图6 检测结果2

结论与展望

       我们完成了对交通视频图片的车辆的识别,对车辆识别原理进行了分析,对车辆检测算法进行了改进,改良后的 YOLOv4 模型 的性能得到了大幅提升,车辆检测准确性较高。通过试验测试发现可以满足实时检测的要求,但是该车辆检测模型还有改进优化的空间。还可以对以下几个方面进行优化:

       用于车辆识别的图片大多为白天拍摄的,对白天车辆统计效果较好, 后续研究方向会将下雪天、雨天、夜晚等环境进行比较分析。

       我们在识别过程中发现,很多小型车辆仍有检测不到的情况,需要对模型继续进行优化,训练精度更好的模型才能避免这种情况的发生。

代码实现

clc;
clear;
close all;
warning off;
addpath(genpath(pwd));

%% 下载预训练网络
% 设置上述模型名称以下载该预训练模型。
modelName = 'YOLOv4-coco';
model = helper.downloadPretrainedYOLOv4(modelName);
net = model.net;

%% 加载数据
%解压缩车辆图像并加载车辆地面实况数据。
unzip vehicleDatasetImages.zip
data = load('vehicleDatasetGroundTruth.mat');
vehicleDataset = data.vehicleDataset;

% 将完整路径添加到本地车辆数据文件夹。
vehicleDataset.imageFilename = fullfile(pwd, vehicleDataset.imageFilename);


rng('default')
shuffledIndices = randperm(height(vehicleDataset));
idx = floor(0.6 * length(shuffledIndices));
trainingDataTbl = vehicleDataset(shuffledIndices(1:idx), :);
testDataTbl = vehicleDataset(shuffledIndices(idx+1:end), :);

% 创建用于加载图像的图像数据存储.
imdsTrain = imageDatastore(trainingDataTbl.imageFilename);
imdsTest = imageDatastore(testDataTbl.imageFilename);
 
% 为地面真相边界框创建数据存储。
bldsTrain = boxLabelDatastore(trainingDataTbl(:, 2:end));
bldsTest = boxLabelDatastore(testDataTbl(:, 2:end));

% 组合图像和框标签数据存储。
trainingData = combine(imdsTrain, bldsTrain);
testData = combine(imdsTest, bldsTest);

helper.validateInputData(trainingData);
helper.validateInputData(testData);

%% 数据扩充
augmentedTrainingData = transform(trainingData, @helper.augmentData);
 
% 增强后的图片
augmentedData = cell(4,1);
for k = 1:4
    data = read(augmentedTrainingData);
    augmentedData{k} = insertShape(data{1,1}, 'Rectangle', data{1,2});
    reset(augmentedTrainingData);
end
figure
montage(augmentedData, 'BorderSize', 10)

%% 预处理训练数据
% 指定网络输入大小。 
networkInputSize = net.Layers(1).InputSize;
 

preprocessedTrainingData = transform(augmentedTrainingData, @(data)helper.preprocessData(data, networkInputSize));
 
% 读取预处理的训练数据。
data = read(preprocessedTrainingData);

% 显示带有边界框的图像。
I = data{1,1};
bbox = data{1,2};
annotatedImage = insertShape(I, 'Rectangle', bbox);
annotatedImage = imresize(annotatedImage,2);
figure
imshow(annotatedImage)

% 重置数据存储。
reset(preprocessedTrainingData);

%% 修改预训练YOLO v4网络

rng(0)
trainingDataForEstimation = transform(trainingData, @(data)helper.preprocessData(data, networkInputSize));
numAnchors = 9;
[anchorBoxes, meanIoU] = estimateAnchorBoxes(trainingDataForEstimation, numAnchors);

% 指定培训中要使用的className。
classNames = {'vehicle'};


[lgraph, networkOutputs, anchorBoxes, anchorBoxMasks] = configureYOLOv4(net, classNames, anchorBoxes, modelName);

%% 指定超参数
numEpochs = 200;
miniBatchSize = 4;
learningRate = 0.01;
warmupPeriod = 1000;
l2Regularization = 0.001;
penaltyThreshold = 0.5;
velocity = [];

%% 训练模型
if canUseParallelPool
   dispatchInBackground = true;
else
   dispatchInBackground = false;
end

mbqTrain = minibatchqueue(preprocessedTrainingData, 2,...
        "MiniBatchSize", miniBatchSize,...
        "MiniBatchFcn", @(images, boxes, labels) helper.createBatchData(images, boxes, labels, classNames), ...
        "MiniBatchFormat", ["SSCB", ""],...
        "DispatchInBackground", dispatchInBackground,...
        "OutputCast", ["", "double"]);



% 将层图转换为dlnetwork。
net = dlnetwork(lgraph);

% 学习率和batch_size子图。
fig = figure;
[lossPlotter, learningRatePlotter] = helper.configureTrainingProgressPlotter(fig);

iteration = 0;
% 自定义训练循环。
for epoch = 1:numEpochs
      
    reset(mbqTrain);
    shuffle(mbqTrain);
    
    while(hasdata(mbqTrain))
        iteration = iteration + 1;
       
        [XTrain, YTrain] = next(mbqTrain);
        
        % 使用dlfeval和modelGradients函数评估模型梯度和损失。
        [gradients, state, lossInfo] = dlfeval(@modelGradients, net, XTrain, YTrain, anchorBoxes, anchorBoxMasks, penaltyThreshold, networkOutputs);

        % 应用L2正则化。
        gradients = dlupdate(@(g,w) g + l2Regularization*w, gradients, net.Learnables);

        % 确定当前学习率
        currentLR = helper.piecewiseLearningRateWithWarmup(iteration, epoch, learningRate, warmupPeriod, numEpochs);
        
        % 使用SGDM优化器更新网络可学习参数。
        [net, velocity] = sgdmupdate(net, gradients, velocity, currentLR);

        % 更新dlnetwork的状态参数。
        net.State = state;
        
        % 显示进度。
        if mod(iteration,10)==1
            helper.displayLossInfo(epoch, iteration, currentLR, lossInfo);
        end
            
        % 更新训练图。
        helper.updatePlots(lossPlotter, learningRatePlotter, iteration, currentLR, lossInfo.totalLoss);
    end
end

% 保存训练模型。
anchors.anchorBoxes = anchorBoxes;
anchors.anchorBoxMasks = anchorBoxMasks;

save('yolov4_trained', 'net', 'anchors');

%% 评估模型
confidenceThreshold = 0.5;
overlapThreshold = 0.5;

%创建一个表以保存返回的边界框、分数和标签检测器。
numImages = size(testDataTbl, 1);
results = table('Size', [0 3], ...
    'VariableTypes', {'cell','cell','cell'}, ...
    'VariableNames', {'Boxes','Scores','Labels'});

% 对测试集中的图像运行检测器并收集结果。
reset(testData)
while hasdata(testData)
    % 读取数据存储并获取图像。
    data = read(testData);
    image = data{1};
    
    % 运行预测器
    executionEnvironment = 'auto';
    [bboxes, scores, labels] = detectYOLOv4(net, image, anchors, classNames, executionEnvironment);
    
    % 收集结果。
    tbl = table({bboxes}, {scores}, {labels}, 'VariableNames', {'Boxes','Scores','Labels'});
    results = [results; tbl];
end

% 使用平均精度度量评估对象检测器。
[ap, recall, precision] = evaluateDetectionPrecision(results, testData);

%精确召回(PR)曲线显示了检测器在变化时的精度召回水平。理想情况下,所有召回级别的精度均为1。

% 绘制精度召回曲线。
figure
plot(recall, precision)
xlabel('Recall')
ylabel('Precision')
grid on
title(sprintf('Average Precision = %.2f', ap))

%% 使用经过训练的YOLO v4检测对象
reset(testData)
data = read(testData);

% 选取图片
I = data{1};

% 运行预测
executionEnvironment = 'auto';
[bboxes, scores, labels] = detectYOLOv4(net, I, anchors, classNames, executionEnvironment);

% 预测图片
if ~isempty(scores)
    I = insertObjectAnnotation(I, 'rectangle', bboxes, scores);
end
figure
imshow(I)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/167087.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

怎么拆分PDF文件,教你用最简单的方法

PDF文档拆分是一种很常见的需求。因为有时候文档页数过多,打开和阅读都不太方便,我们可以通过拆分把想要的部分提取出来。拆分PDF的时候可以借助一些工具更快更有效地达成目的,这里就给大家介绍几款比较受欢迎的处理工具,它们在辅…

Linux——系统管理篇

1、、Linux 中的进程和服务 计算机中、一个正在执行的程序或命令,叫进程(process)。 启动之后一直存在、常驻内存的进程,一般称为“服务”(Service) // 我更喜欢叫它守护进程 Daemon 比如windows的那一堆…

软件测试面试,如何自我介绍?

01 如何自我介绍 面试过程中一定要放慢语速,做到条理清晰。特别是做自我介绍时,可以适当多介绍自己会什么,有哪些重要经验。 例如: 面试官,上午/下午好。 我是XXX,今天来面试贵公司的软件测试工程师岗位&a…

利用QT 的 Graphics View 系统实现一个 简易的 Graph Editor

QT 中的 Graphics View 系统. 是一个相对成熟的渲染引擎的上层框架,通常也可以会叫做 Scene - View。 通常会有 QGraphicsView, QGraphicsScene, QGraphicsItem 这几个类构成。 view是视口(viewport);scene是一个场景,负责容纳各种item&…

JS语言基础

目录 语法 关键字与保留字 变量 var关键字 let声明 暂时性死区 全局变量 for循环中的let声明 条件声明 const声明 语法 1. 区分大小写 无论是变量、函数名还是操作符,都区分大小写。 2. 标识符 所谓标识符,就是变量、函数、属性或函数参数的名…

centos7配置(nvidia+cuda+cudnn+anaconda+tensorflow)gpu开发环境

一、安装准备 1、查看nvidia显卡,我的是T4显卡 lspci | grep -i nvidia2、查看linux系统版本 uname -m && cat /etc/redhat-release3、安装依赖 yum install gcc kernel-devel kernel-headers二、安装nvidia驱动 1、禁用nouveau lsmod | grep nouveau…

Powershell渗透框架

文章目录Powershell基础Powershell简介什么是 Windows PowerShell为什么使用 Windows PowerShell如何启动 Windows PowerShellPowerShell和Cmd命令提示符的区别PowerShellcmd管理员运行 PowerShellWindows PowerShell ISE创建并运行脚本文本编辑器创建脚本集成脚本环境创建脚本…

第二章.线性回归以及非线性回归—特征缩放,交叉验证法,过拟合

第二章.线性回归以及非线性回归 2.9 特征缩放 1.数据归一化 1).作用: 把数据的取值范围处理为0-1或者-1-1 2).数据范围处理为0-1之间的方法: newValue(oldValue-min)/(max-min) 例如:数组:(1,3,5),value1:(1-1)/(5-1)0…

MyBatis-Plus分析打印SQL(开发环境)

项目创建POM依赖 <!-- https://mvnrepository.com/artifact/p6spy/p6spy --> <dependency><groupId>p6spy</groupId><artifactId>p6spy</artifactId><version>3.9.1</version> </dependency> YML配置 spring:datasource…

silicon labs Gateway HOST-NCP MQTT网关搭建

一、背景 目前正在开发一款中控网关,网关mcu跑Android系统,NCP采用EFR32MG21开发板,需要跑MQTT协议控制zigbee的网络。基于以上需求,下载了simplicity studio V5版本和最新的EmberZNet 7.2.0.0协议栈进行验证,发现新的GSDK已经不再支持MQTT功能,官方回答是EmberZNet 6.7…

论文解读 - 城市自动驾驶车辆运动规划与控制技术综述 (第2部分)

文章目录&#x1f697; II. Overview of the decision-making hierarchy used in driverless cars&#xff08;无人驾驶汽车的决策层综述&#xff09;&#x1f534; A. Route Planning&#xff08;路径规划&#xff09;&#x1f7e0; B. Behavioral Decision Making&#xff08…

论文工具大全+软件简介

文章目录**1.使用说明用哪个文库就打开&#xff0c;****2.在软件中复制粘贴网址点下载**3.点已下载文件右击鼠标另外保存**腾讯微云-https://share.weiyun.com/5U3fAjF**1.安装并上传论文点检测2.检测等待时间3.打开检测报告查看回复[文献]&#xff1a;参考文献自动生成器参考文…

贪心算法专题

1.Acwing 1055. 股票买卖 II 题目链接&#xff1a;1055. 股票买卖 II - AcWing题库 思路&#xff1a;逢涨就买 #include<iostream> using namespace std;int main() {int n;long long ans0;int a[100005];cin>>n;cin>>a[0];for(int i1;i<n;i){cin>&…

C语言—动态内存管理

专栏&#xff1a;C语言 个人主页&#xff1a;HaiFan. 专栏简介&#xff1a;本专栏主要更新一些C语言的基础知识&#xff0c;也会实现一些小游戏和通讯录&#xff0c;学时管理系统之类的&#xff0c;有兴趣的朋友可以关注一下。 动态内存管理前言一、为什么会存在动态内存分配二…

磨金石教育分享||CG特效技术主要应用在哪几个领域

前面我们介绍了很多关于CG特效的知识&#xff0c;我们知道CG特效发展的历史以及重大意义。那么我们今天再来详细讨论一下CG特效主要应用的几个领域。近几年文化艺术的发展伴随着互联网信息技术高速传播。文化艺术产业变得多元&#xff0c;动漫、3A大作游戏、商业大片、虚拟现实…

Java 元注解

​ 元注解是负责对其它注解进行说明的注解&#xff0c;自定义注解时可以使用元注解。Java 5 定义了 4 个注解&#xff0c;分别是 Documented、Target、Retention 和 Inherited。Java 8 又增加了 Repeatable 和 Native 两个注解。这些注解都可以在 java.lang.annotation 包中找到…

前端压缩图片为指定宽高

压缩图片原理 通过原生的input标签拿到要上传的图片文件将图片文件转化成img元素标签在canvas上压缩绘制该HTMLImageElement将图片转化为一个包含图片展示的data URI&#xff0c;即图片被转换成base64编码的字符串 实现 通过原生的input标签拿到上传的图片文件 css部分<…

Linux 通过监控监控系统内存并定时重启指定服务

一、使用Free命令监控系统内存 1.1 查看系统内存情况 free -m1.1.1 获取空闲物理内存 echo Mem-free: `free -m | grep Mem | awk {print $4}`M1.1.2 获取缓冲区内存

php 安装curl扩展支持sftp协议

原因&#xff1a;php默认安装的依赖的libcurl.so中不支持sftp 协议 解决方法&#xff1a;先安装libssh2&#xff0c;curl安装时编译参数带–with-libssh2&#xff0c;这样可以支持sftp 一.编译安装libssh2-1.8.0 1.下载源码 地址: https://github.com/libssh2/libssh2 2.编译…

requests页面常用操作(post、put、get、head、patch、delete方法)

1 requests主要方法2 请求返回信息3 应用3.1 登录页面3.2 退出登录3.3 修改参数3.4 上传文件Requests 是一个 Python 的 HTTP 客户端库。每次调用 requests 请求之后&#xff0c;会返回一个 response 对象&#xff0c;该对象包含了具体的响应信息。可以通过requests模拟提交请求…