当前位置: 首页 > news >正文

【MATLAB】目标检测初探

文章目录

  • 0 前言
  • 1 目标检测概述
  • 2 算法实践
    • 2.1 YOLO v2
    • 2.2 YOLO v3
  • 3 项目实践
    • 3.1 项目背景和数据集
    • 3.2 实践结果
    • 3.3 算法对比
  • 4 工具箱与数据标注
  • 5 总结

0 前言

  之前因为项目原因,做了一个基于YOLOv5实现目标检测的程序,是基于Python做的,直接使用YOLOv5开源库,只需要导入数据训练再运行特定文件即可,简单的操作得到优秀的结果。因此当时没有仔细研究代码,更没有深究目标检测相关理论。最近学习了一些MATLAB中目标检测相关的内容,于是想结合官方文档和demo重新实现之前那个项目,作为一个入门参考。

1 目标检测概述

  所谓目标检测(Object Detection),其核心任务是从图像或视频中识别并定位感兴趣的对象,这不仅要求高准确率的分类,还需要精确的位置预测。相比于图像分类(Classification)只需要知道图片中是什么(what),目标检测既要知道“what”,也要知道“where”。

  目标检测经过二十多年的发展,从最初基于传统机器学习先提取特征,再进行图像分类,到现在使用卷积神经网络直接“端到端”,使特征提取自动化,同时也提高了目标检测的准确率。

  目前基于深度学习实现目标检测主要有两类做法,一种称为两段式目标检测,即先通过一个网络筛选出感兴趣的区域(ROI),或者说存在目标可能性较大的区域,这一步叫做region proposal,然后再根据这些筛选出的region,判断其属于哪种类别,即图像分类,两段式的代表算法有R-CNNSPPNetFast R-CNNFaster R-CNN等;另一种方法叫做一段式目标检测,即将上述两个步骤合并到一起进行,没有单独的region proposal的步骤,两段式最具代表性的算法就是YOLO系列算法,目前已经发展出多个版本,从YOLO v1到YOLO v8(来自不同的研究团队),比较知名的还是YOLO v5.

所谓YOLO,即You Only Look Once,顾名思义,必然是一段式的

  从研究情况来看,YOLO系列算法更受欢迎,各个YOLO系列算法也有各自的开源仓库(当然,都是Python的),目前MATLAB中已经支持YOLO v2,YOLO v3,YOLO v4,但没有和python开源仓库那种比较完善的,因此想基于帮助文档进行代码实践,对已有函数进行再次封装,提高其易用性的情况下测试一下我之前一个项目的数据集,并比较各算法优劣。

参考链接

2 算法实践

2.1 YOLO v2

  首先来看MATLAB自带的一个示例,在命令行输入help help,打开帮助文档,直接搜索YOLO,找到这个链接:

在这里插入图片描述

点开之后可以得到一个训练检测车辆目标的demo:

在这里插入图片描述

上述demo链接直达

依次运行该代码,可以发现其实核心主要有三个步骤:准备数据,导入模型,设置训练参数,这也是训练核心函数trainYOLOv2ObjectDetector的必要参数。

trainYOLOv2ObjectDetector详解

接下来依次实现。其带注解代码如下所示

clear,clc
% 导入训练数据
data = load('vehicleTrainingData.mat');
trainingData = data.vehicleTrainingData;
% 对数据进行处理——相对路径转换成绝对路径
dataDir = fullfile(toolboxdir('vision'),'visiondata');
trainingData.imageFilename = fullfile(dataDir,trainingData.imageFilename);
% 对数据进行处理——打乱数据,便于训练
rng(0); % 固定随机种子,保证运行结果可复现
shuffledIdx = randperm(height(trainingData));
trainingData = trainingData(shuffledIdx,:);
% 构建数据结构——datastore
imds = imageDatastore(trainingData.imageFilename); % 图片数据存储
blds = boxLabelDatastore(trainingData(:,2:end)); % 标注数据存储
ds = combine(imds, blds); % 将两个结合起来
% 导入网络
net = load('yolov2VehicleDetector.mat');
lgraph = net.lgraph;
% 设置训练选项
options = trainingOptions('sgdm',...    % 算法选择'InitialLearnRate',0.001,...  % 初始学习率'Verbose',true,...            % 是否输出训练信息'VerboseFrequency',30,...     % 输出训练信息的频率'MiniBatchSize',16,...        % 批量大小'MaxEpochs',30,...            % 最大迭代次数'Shuffle','never',...         % 训练前是否打乱数据'CheckpointPath',"./yolov2-checkpoint");    % 检查点保存所在位置
% 开始训练
[detector,info] = trainYOLOv2ObjectDetector(ds,lgraph,options);
% 显示训练过程损失变化曲线
figure
plot(info.TrainingLoss)
grid on
xlabel('Number of Iterations')
ylabel('Training Loss for Each Iteration')
% 运行推理,进行检测
img = imread('detectcars.png');
[bboxes,scores] = detect(detector,img);
if(~isempty(bboxes)) % 如果检测到目标,就将标注框加上img = insertObjectAnnotation(img,'rectangle',bboxes,scores);
end
figure
imshow(img)

运行该代码,训练时间约3min(CPU),最终得到示例图片的检测结果:

在这里插入图片描述

在这里插入图片描述

从结果上来看,效果还是挺不错的,识别准确度较高,而且LOSS曲线下降也非常快速。

2.2 YOLO v3

  和YOLO v2相比,YOLO v3的基本步骤也差不多,也是上面提到的关键三步:准备数据,导入模型,设置训练参数,其中,准备数据基本是一致的,二者的数据结构基本差不多。只是在模型选择和训练参数设置上有差异。此处不再赘述,可以直接参考官方文档

需要注意的是,实测发现YOLO v3不支持较低版本的MATLAB,如2019b,至少是2020a及以上的才行。

3 项目实践

3.1 项目背景和数据集

  在工厂生产瓶装水的流水线中,最后将瓶装水打包为一箱的这一步也是通过流水线完成的,但是在实际运行中可能会出现一个问题,那就是有倒下的水瓶,目前针对该问题的解决方式是依靠整理水瓶的最后一步如果有倒下的水瓶,机器就会卡住并报警,通知员工来将倒下的水瓶给扶起来,等待正常之后继续运行。这样就耽误了生产时间,生产效率大大下降。如何提高生产效率,避免出现打包机遇到倒瓶自动暂停的现象,有一个解决思路就是在流水线的上游设置一个倒瓶检测装置,当检测到倒瓶时,发出报警,达到提前警示,节约时间的效果,从而提高生产效率。

  为了节约成本,肯定是不能随便修改生产线的,所以最佳的方式是用视觉传感器,即通过摄像头检测有没有倒瓶,有就发出报警,通知员工来调整。因此这个问题本质上是一个目标检测的问题。

  实践过程中,首先需要固定摄像头,运行流水线,并采集有倒瓶的照片,并进行标注,再基于标注完成的数据集进行训练,得到训练好的模型再部署到设备当中,完成算法开发。

  数据集一共有236张照片,照片基于工业相机拍摄,像素较高,是1624×1240,也存在几张照片中不含有待检测目标,即负样本。数据集如下图所示。

在这里插入图片描述

当时为了满足YOLO v5对于数据集结构的要求,因此也将该数据集整理成YOLOv5的格式:

YOLO Data
|-- test_data
|   |-- 0.bmp
|   |-- 1.bmp
|   |-- ...
`-- train_data|-- bottle.yaml|-- images|   |-- train|   |   |-- IMG_1.bmp|   |   |-- IMG_10.bmp|   |   |-- ...|   `-- val|       |-- IMG_101.bmp|       |-- IMG_103.bmp|       |-- ...`-- labels|-- classes.txt|-- train|   |-- IMG_1.txt|   |-- IMG_10.txt|-- val|   |-- IMG_101.txt|   |-- IMG_103.txt|   |-- ...

3.2 实践结果

  参考上述YOLO v2的demo,只需要更换数据集以及检测样例即可,代码如下所示。

clear,clc
% 图片数据
filename = mfilename('fullpath'); % 返回当前脚本文件所在路径,直接运行节不可行
imgdir = fullfile(pwd, "./YOLOData/train_data/images/train");
imglist = dir(fullfile(imgdir, "*.bmp"));
lbldir = fullfile(pwd, "./YOLOData/train_data/labels/train");
lbllist = dir(fullfile(lbldir, "*.txt"));
len = length(imglist);  % 数据个数
img = cell(len,1);
label = cell(len,1);
k = 1;
for i=1:lenimg_tmp = fullfile(imglist(i,:).folder, imglist(i,:).name);info = imfinfo(img_tmp);width1 = info.Width; height1 = info.Height;label_i = fullfile(lbllist(i,:).folder, lbllist(i,:).name);a = load(label_i);if isempty(a)continue;enda = a(:,2:end);a(:,[1,3]) = round(a(:,[1,3])*width1);a(:,[2,4]) = round(a(:,[2,4])*height1);a(:,1) = round(a(:,1) - a(:,3)/2);  % 中心点转换为左上角点a(:,2) = round(a(:,2) - a(:,4)/2);img{k} = img_tmp;label{k} = a;k = k + 1;
end
img = img(1:k-1,:);  % 用圆括号索引,得到的还是cell
label = label(1:k-1,:);
trainingData = table(img, label, 'VariableNames',{'Image','Label'});
% 对数据进行处理——打乱数据,便于训练
rng(0); % 固定随机种子,保证运行结果可复现
shuffledIdx = randperm(height(trainingData));
trainingData = trainingData(shuffledIdx,:);
% 构建数据结构——datastore
imds = imageDatastore(trainingData.Image); % 图片数据存储
blds = boxLabelDatastore(trainingData(:,2:end)); % 标注数据存储
ds = combine(imds, blds); % 将两个结合起来
% 导入网络
net = load('yolov2VehicleDetector.mat');
lgraph = net.lgraph;   % 这个网络来自预训练好的模型,和训练数据关联不大
% 设置训练选项
options = trainingOptions('sgdm',...    % 算法选择'InitialLearnRate',0.001,...  % 初始学习率'Verbose',true,...            % 是否输出训练信息'VerboseFrequency',30,...     % 输出训练信息的频率'MiniBatchSize',16,...        % 批量大小'MaxEpochs',30,...            % 最大迭代次数'Shuffle','never',...         % 训练前是否打乱数据'CheckpointPath',"./yolov2-checkpoint");    % 检查点保存所在位置
% 开始训练
[detector,info] = trainYOLOv2ObjectDetector(ds,lgraph,options);
% 显示训练过程损失变化曲线
figure
plot(info.TrainingLoss)
grid on
xlabel('Number of Iterations')
ylabel('Training Loss for Each Iteration')
%% 运行推理,进行检测
testfilename = "783.bmp";
testfiledir = 'F:\MATLAB\YOLOData\test_data';
img1 = imread(fullfile(testfiledir, testfilename));
[bboxes,scores] = detect(detector,img1);
if(~isempty(bboxes)) % 如果检测到目标,就将标注框加上img1 = insertObjectAnnotation(img1,'rectangle',bboxes,scores);
end
figure
imshow(img1)

由于这个图片数量更多,size也更大,所以训练时间更长一点,一共是10min(CPU),检测结果如下图所示,效果还算可以,但是置信度不高。
在这里插入图片描述

在这里插入图片描述

3.3 算法对比

  YOLOv2和YOLOv3在相对简单的数据集(大小适中,目标清晰)性能差别不明显,效果都比较好,从给出的demo就能看出,但是在相对复杂的数据集中表现一般。
  另外,和YOLO v5相比,其性能差别也比较明显,如下图所示是YOLO v5识别的效果

请添加图片描述

4 工具箱与数据标注

  以上是直接利用现成的标注好的数据,如果是未标注的数据,也可以利用MATLAB自带的工具箱进行标注,且既可以标注图片,也可以标注视频。使用方式比较简单,直接在APP页面找到对应功能按钮打开即可。
在这里插入图片描述
而且对于视频标注,还可以利用其内置算法实现全自动或半自动标注,非常快捷,具体可以参考这个视频。

不过需要尤为注意的是,标注文件数据的格式问题。之前使用YOLOv5,用labelimg进行标注,得到的标注文件是五列:[类别编号 中心点x坐标 中心点y坐标 目标宽度 目标长度],且体现的数值是归一化之后的,即除以图片的长或宽。但是在MATLAB中的标注是[类别编号 左上角x坐标 左上角y坐标 目标宽度 目标长度],因此二者差了一半长/宽,一定注意,否则会产生报错。

5 总结

  本文从理论出发,介绍了目标检测的几种类别以及其各自的算法理念,并基于MATLAB平台实践了当下热门的YOLO算法,并总结出如何将python下的数据集转换成MATLAB下需要的数据集。为了检验其模型的性能,分别训练并测试了不同的数据集,发现YOLOv2版本的模型检测准确度等性能指标在复杂数据集面前偏低,参考官方的介绍,重新构建深度学习网络,可以在一定程度上提高模型的性能。

相关文章:

【MATLAB】目标检测初探

文章目录 0 前言1 目标检测概述2 算法实践2.1 YOLO v22.2 YOLO v3 3 项目实践3.1 项目背景和数据集3.2 实践结果3.3 算法对比 4 工具箱与数据标注5 总结 0 前言 之前因为项目原因,做了一个基于YOLOv5实现目标检测的程序,是基于Python做的,直接…...

SpringCloud 微服务消息队列灰度方案 (RocketMQ 4.x)

目录 背景遇到的问题 RocketMQ 基础基础消息模型扩展后的消息模型部署模型相关概念点 方案对比影子Topic的方案Tag的方案UserProperty的方案影子Group的方案灰度分区的方案方案对比 灰度分区方案设计适配只有部分灰度的情况所做的功能扩展消费者(无灰度)…...

厘清标准差和标准误:因果推断的统计学基础

标准差,指 一次抽样中 个体取值间的离散程度,反映了 个体取值对样本均值的代表性。 标准误,指 多次抽样中 样本均值间的离散程度,反映了 样本均值对总体均值的代表性。 公众号原文-厘清标准差和标准误:因果推断的统计…...

GESP4级考试语法知识(贪心算法(二))

排队接水2代码&#xff1a; #include<iostream> #include<cstdio> #include<algorithm> using namespace std; struct people {int num;int time; }; people s[1001]; int n,r,a[1001]; double sum,ave; bool cmp(people x,people y) {return x.time<y.t…...

MATLAB 使用教程 —— 命令窗口输入命令,工作区显示变量

命令在命令窗口输入变量在工作区显示 MATLAB 桌面包含的面板如下&#xff1a; 当前文件夹 - 此面板允许访问项目文件夹和文件。命令窗口 - 这是主要区域&#xff0c;用户在命令行中输入命令&#xff0c;命令提示符(>>).工作区 - 工作区显示所有变量&#xff0c;无论是创…...

LeetCode 热题100(八)【二叉树】(3)

目录 8.11二叉树展开为链表&#xff08;中等&#xff09; 8.12从前序与中序遍历序列构造二叉树&#xff08;中等&#xff09; 8.13路径总和III&#xff08;中等&#xff09; 8.14二叉树的最近公共祖先&#xff08;中等&#xff09; 8.15二叉树中的最大路径和&#xff08;困…...

uniapp h5实现录音

使用npm安装 npm install recorder-core引入Recorder库 可以使用import、require、html script等你适合的方式来引入js文件&#xff0c;下面的以import为主要参考&#xff0c;其他引入方式根据文件路径自行调整一下就可以了。 //必须引入的Recorder核心&#xff08;文件路径是…...

字节跳动Android面试题汇总及参考答案(80+面试题,持续更新)

Android 四大组件是什么? Android 四大组件分别是 Activity、Service、Broadcast Receiver 和 Content Provider。 Activity 是 Android 应用中最基本的组件,用于实现用户界面。它可以包含各种视图控件,如按钮、文本框等。一个 Activity 通常对应一个屏幕的内容。用户可以通…...

【go从零单排】通道select、通道timeout、Non-Blocking Channel Operations非阻塞通道操作

&#x1f308;Don’t worry , just coding! 内耗与overthinking只会削弱你的精力&#xff0c;虚度你的光阴&#xff0c;每天迈出一小步&#xff0c;回头时发现已经走了很远。 &#x1f4d7;概念 select 语句是 Go 的一种控制结构&#xff0c;用于等待多个通道操作。它类似于 s…...

PSRR仿真笔记

1.首先打开bandgap的testbench电路&#xff0c;选择schematic 2.打开电路后,选择VDD模块&#xff0c;然后按键盘Q&#xff0c;进行编辑&#xff0c;将AC magnitude改为1 V 3.修改完成后&#xff0c;点击左上角Launch > ADE Explorer 4.在出现的窗口中&#xff0c;选择Creat…...

AUTOSAR_EXP_ARAComAPI的7章笔记(3)

☞返回总目录 相关总结&#xff1a;AutoSar AP简单多绑定总结 7.3 多绑定 如在 5.4.3 小节中简要讨论的&#xff0c;某个代理类 / 骨架类的不同实例之间的技术传输是不同的&#xff0c;多绑定描述了这种情况的解决方案。多种技术原因都可能导致这种情况出现&#xff1a; 代…...

WSADATA 关键字详细介绍

WSADATA 是 Windows Sockets API&#xff08;Winsock&#xff09;中用于存储 Winsock 库的初始化信息的结构体。在使用 Winsock API 之前&#xff0c;必须通过调用 WSAStartup() 函数进行初始化&#xff0c;WSADATA 结构体用于接收有关 Winsock 库版本的信息。Winsock 是 Windo…...

Day44 | 动态规划 :状态机DP 买卖股票的最佳时机IV买卖股票的最佳时机III

Day44 | 动态规划 &#xff1a;状态机DP 买卖股票的最佳时机IV&&买卖股票的最佳时机III&&309.买卖股票的最佳时机含冷冻期 动态规划应该如何学习&#xff1f;-CSDN博客 本次题解参考自灵神的做法&#xff0c;大家也多多支持灵神的题解 买卖股票的最佳时机【…...

Area-Composition模型部署指南

一、介绍 本模型可以通过输入不同的提示词&#xff0c;然后根据各部分提示词进行融合生成图片。如下图&#xff1a; 此图像包含 4 个不同的区域&#xff1a;夜晚、傍晚、白天、早晨 二、部署 环境要求&#xff1a; 最低显存&#xff1a;10G 1. 部署ComfyUI 本篇的模型部署…...

策略模式、状态机详细解读

策略模式 (Strategy Pattern) 策略模式 (Strategy Pattern) 是一种行为型设计模式&#xff0c;旨在将一组算法封装成独立的类&#xff0c;使得它们可以相互替换。这种模式让算法的变化不会影响到使用算法的客户&#xff0c;减少了类之间的耦合。策略模式通常用于处理一类问题&…...

OpenWrt广播DNS到客户端

OpenWrt广播DNS到客户端 Network -> Interfaces -> lan ->DHCP Server -> Advanced Settings -> DHCP-Options 设置 6,dns1,dns2 如下图 也可以直接编辑 /etc/config/dhcp config dhcp lan list dhcp_option 6,119.29.29.29,223.5.5.5 #ipv4 option dns 2402:4…...

C++编程技巧与规范-类和对象

类和对象 1. 静态对象的探讨与全局对象的构造顺序 静态对象的探讨 类中的静态成员变量(类类型静态成员) 类中静态变量的声明与定义&#xff08;类中声明类外定义&#xff09; #include<iostream> using namespace std;namespace _nmspl {class A{public:A():m_i(5){…...

AutoHotKey自动热键AHK-正则表达式

在这个软件的操作中,基本都是需要即时的解决一些问题,所以对字符串的操作是比较多的,所以正则的使用还是比较重要的,接下来我们用一个例子来了解正则表达式的使用 str "7654321" RegExMatch(str, "65(43)(21)", SubPat)str ( str %str% SubPat %SubPa…...

【3D Slicer】的小白入门使用指南四

开源解剖影像浏览工具Open Anatomy Browser使用及介绍 和3D slicer米有太大关系,该工具是网页版影像数据的浏览工具(可以简单理解为网页版的3D slicer) 介绍 ● 开放解剖(OA)浏览器是由神经影像分析中心开发的,基于网络浏览器技术构建的图谱查看器。 ● OA浏览器将解剖模…...

flink同步mysql数据表到pg库

1.关闭防火墙和selinux systemctl stop firewalld systemctl disable firewalld systemctl status firewalldvi /etc/selinux/config 修改为disabled2.安装java8 yum list java-1.8* yum install java-1.8.0-openjdk* -yjava -version3.下载和部署postgresql 下载地址&#…...

AndroidStudio-常用布局

一、线性布局LinearLayout 线性布局内部的各视图有两种排列方式: 1.orientation属性值为horizontal时&#xff0c;内部视图在水平方向从左往右排列。 2.orientation属性值为vertical时&#xff0c;内部视图在垂直方向从上往下排列。 如果不指定orientation属性&#xff0c;…...

Vue全栈开发旅游网项目(10)-用户管理后端接口开发

1.异步用户登录\登出接口开发 1.设计公共响应数据类型 文件地址&#xff1a;utils/response404.py from django.http import JsonResponseclass BadRequestJsonResponse(JsonResponse):status_code 400def __init__(self, err_list, *args, **kwargs):data {"error_c…...

[Android]查找java类中声明为native方法的具体实现方法

在android代码中&#xff0c;经常可以看到native方法&#xff0c;需要查看其对应的C方法&#xff0c;这些方法是一一对应的&#xff0c;对应关系是在jni注册里关联起来的。 比较直观的是这样的例子&#xff0c; Parcel.java //Java层的方法里调用了native方法nativeWriteInt…...

Exploring Defeasible Reasoning in Large Language Models: A Chain-of-Thought A

文章目录 题目摘要简介准备工作数据集生成方法实验结论 题目 探索大型语言模型中的可废止推理&#xff1a;思路链 论文地址&#xff1a;http://collegepublications.co.uk/downloads/LNGAI00004.pdf#page136 摘要 许多大型语言模型 (LLM) 经过大量高质量数据语料库的训练&…...

uniapp在app模式下组件传值

在 UniApp 编译成 App 后&#xff0c;传递参数可以通过多种方式实现&#xff0c;常见的方式有以下几种&#xff1a; 1. 通过 URL 参数传递&#xff08;适用于 WebView&#xff09; 如果你的 App 页面通过 WebView 渲染&#xff0c;可以像在 Web 端一样通过 URL 传递参数。例如…...

Docker解决暴露2375端口引发的安全漏洞

docker的暴露api端口2375&#xff0c;没有任何安全防护&#xff0c;我们通过linux系统防火墙&#xff08;iptables&#xff09;来进行ip访问限制 # 查看iptables所有规则 iptables -L -nv # 只允许某个ip访问2375端口 iptables -I INPUT -s 127.0.0.1 -p tcp --dport 2375 -j A…...

HTML5+CSS前端开发【保姆级教学】+新闻文章初体验

Hello&#xff0c;各位编程猿们&#xff01;上一篇文章介绍了前端以及软件的安装&#xff0c;这一篇我们要继续讲解页面更多知识点&#xff0c;教大家做一篇新闻题材的文章 新闻文章 当我们点开浏览器经常看到各种各样的文章&#xff0c;今天我们就来看看大家最喜欢关注的体育…...

『VUE』26. props实现子组件传递数据给父组件(详细图文注释)

目录 本节内容示例代码总结 欢迎关注 『VUE』 专栏&#xff0c;持续更新中 欢迎关注 『VUE』 专栏&#xff0c;持续更新中 本节内容 父组件传子组件–props 子组件传父组件–自定义事件 本节讲子组件传父组件–通过props里的方法传递,就是父亲写了一个函数,给子组件调用,然后…...

RHCE-DNS域名解析服务器

一、DNS简介 DNS &#xff08; Domain Name System &#xff09;是互联网上的一项服务&#xff0c;它作为将域名和 IP 地址相互映射的一个分布式 数据库&#xff0c;能够使人更方便的访问互联网。 DNS 系统使用的是网络的查询&#xff0c;那么自然需要有监听的 port 。 DNS 使…...

移民统计年鉴(1996-2021年)

年鉴中包含了以下几个方面的数据&#xff1a; 移民数量&#xff1a;记录了每年全球移民的总数&#xff0c;以及不同国家和地区的移民流入和流出情况。 移民类型&#xff1a;区分了经济移民、难民、家庭团聚等不同类型的移民。 移民原因&#xff1a;分析了推动移民的各种因素&…...