yolov5训练自己的数据集,OpenCV DNN推理

news2024/11/26 10:42:14

学更好的别人,

做更好的自己。

——《微卡智享》

43ab8185e851bd73daf72254f6a33e2d.jpeg

本文长度为4238,预计阅读9分钟

前言

上一篇《OpenCV--自学笔记》搭建好了yolov5的环境,作为目标检测在应用中,最重要的还是训练自己的数字集并推理,所以这一篇就专门来介绍使用yolov5训练自己的数据集,并且用OpenCV的DNN进行推理。

e0441379e3d9135cb895498d675567bf.png

实现效果

f29dea4c6ea6d3ee4228575c42bae135.png

e9bda444fb78d9294ba05cde603467fc.png

cc897625c2b4725c4cfeb4365dcf2e3b.png

4a53e41df78403f2b94e5676a6316685.png

5c0177e8473b487c173decb4c00fb32e.png

实现yolov5训练自己数据并识别的核心是什么?

A

实现yolov5训练自己数据集,最核心的是怎么标注文件,像上图中我们就是做的数字华容道的识别,每个数字分类标注时,用到的第三方库labelimg.

然后因为最终我们通过C++ OpenCV 的DNN进行推理,所以还要安装一个onnx的库,用于把模型转成onnx。

安装labelimg和onnx

##激活上篇中搭建的yolov5虚拟环境
conda activate yolov5
##安装labelimg
 pip install labelimg

a4078fef818610fe984482f3a627e7e2.png

我这已经安装好了,所以再运行时提示已经安装完成。

##接着再安装onnx
pip install onnx

6c9c245b8ab17612cb84b6b52b5943fb.png

下载训练图片

从上面的实现效果可以看到,我们还是做了华容道的数字识别,所以首先要搜集我们的训练图片,先创建我们的训练目录

ad2d43a8b43e4dc3ab5f791210aaae13.png

e4b0d58638dbe877526910c697c4ffe8.png

25a7752e16b1e84ee47d87194883f162.png

68a1d2ba7f97f7855804421343724593.png

上几个图可以看出,我们建了一个numpuzzles的文件夹,里面加入了images(图片路径)和labels(标签路径)两个文件夹,两个文件夹下面又分别 创建了train(训练集)和val(验证集)文件夹,这样文件夹就创建好了,接下来就是下载训练图片,我这里在网上找了50张数字华容道的图片存放到images/train的文件夹下

44a1879e4cd9b0a5556234366100ad12.png

images/val里面是以前保存的两张图片,验证的图片有点少,不过也无所谓了

416c31cfe703b26e646c92b59de6e2f7.png

这样准备工作就完成了,接下来就是核心的步骤,标注数据。

标注数据

9761ead1852121084698d868f3a8f2aa.png

在命令行中运行labelimg,打开标注软件

578e765dc5f5002c1eb31b304123a629.png

打开OpenDir找到我们下载的图片文件夹

6181f800d0375de249c319e0768145ca.png

点击上面的Yolo按钮进行切换,默认有可能不是Yolo,所以我们经常点击后切换到Yolo即可。

然后点击CreateRectBox,在需要标注的位置鼠标划矩形后,会弹出label的标签提示框,第一次手动输入标签值,后面相同的可以直接输入或选择,点击确定后,当前类别就标注成功了,右边会显示出来分类和画的矩形框位置,具体操作如下面GIF动图。

f3fd028a02b238bf06563e98eeec6bfb.gif

当所有类型都标注完后,点击保存,会生成一个txt的文件,我们将其保存到最初创建的labels/train目录下

bd19c30282d7acfffcccda460528166e.png

图片001对应的也生成了标注后的001.txt的文件,打开001.txt后可以看到一堆文件数字,每一行第一个是代表的标注的序号,后面4个值代表的矩形框的四个顶点的坐标位置。

37ef35e0149c6369a43ac790c22647aa.png

相应的生成classes.txt里面就是我们第一个序号对应的值名称,由于我第一张图的华容道顺序是乱的,第一个是10,所以我按我标注的顺序来做的,没有做到序号和值一样,相对的后面标注时查找稍麻烦的,不过这倒无所谓。

a98f61d488c860a9247bd55c30a37558.png

按上面的方法将50张图片全部标注完,并且保存后,我们的训练数据集就完成了,当然验证集中的两张图片也要按这个方法标注完成,下一步就要开始训练了。

训练数据

创建.yaml文件

第一步优先创建我们的.yaml文件,通过这个来设置训练集及验证集的图片和标签位置,并且要将标签对应的类型也设定进去。

在yolov5/data文件夹下,我们创建一个numpuzzles.yaml的文件

42fc055c6b5df07cfc32811413e1d384.png

cc6ab5ba0aff68e59609906bba1462db.png

  • path:数据集的根目录

  • train:训练集与path的相对路径

  • val:验证集与path的相对路径

  • nc:类别数量,因为这个数据集只有一个类别(fire),nc即为1。

  • names:类别名字。

# Train/val/test sets as 1) dir: path/to/imgs, 2) file: path/to/imgs.txt, or 3) list: [path/to/imgs1, path/to/imgs2, ..]
path: ../datasets/numpuzzles  # dataset root dir
train: images/train  # train images (relative to 'path')
val: images/val  # val images (relative to 'path')
test:  # test images (optional)


# Classes
nc: 15  # number of classes
names: ['10','3','6','1','9','15','14','4','7','5','2','13','11','12','8']  # class names

修改train.py开始进行训练

使用VS Code找开yolov5的文件夹,找到train.py文件,在parse_opt中修改几个参数,一个是初始使用的yolov5的模型,一个是刚才创建的numpuzzles.yaml文件,还有一个就是训练轮数。

11f52dfbdd19ceb6d76e147d8d621a87.png

上图中可以看到,weights我用的是yolov5.pt模型,data已经指定到我们刚才创建的'data/numpuzzles.yaml',并且训练轮数改到了500轮,我这里是直接改的文件用调试方法运行,当然也可以直接在命令行中输入命令加参数的方式直接训练即可。

运行开始就是漫长的训练等待了,因为我这里只有50张图片,最初训练了100轮,但是推理效果很差,后面就改到了训练500轮,主要我的机器没有显卡,所以用的CPU训练,500轮整整用了 6个小时才训练完。

dce699627649055daa11726c88507b5d.png

训练完成后,在runs/train的文件夹下面可以看到我们的训练效果,weight里面有best.pt和last.pt两个训练模型,将best.pt拷贝到yolov5的默认目录下

推理测试

用VS Code打开detect.py文件,修改parse_opt中weights的模型为best.pt

5103587bf7d2266abafc0049e5fc5159.png

然后直接运行推理,可以在runs/detect文件夹下看到推理的效果

67cb4b5ad4c8659f7afb78a73da094c5.png

c06df5e782d33a37639a907c3106c2f1.png

可以看到,经过500轮训练后的效果还是挺不错的,接下来就是使用OpenCV DNN进行推理了。

60bae76ee74625039bd5c684e7eae4e2.png

微卡智享

使用OpenCV进行推理

01

转出onnx模型

文章开始时就说了要转出onnx的模型,所以我们安装了onnx第三方工具,在export.py中转出使用,还是用VS Code打开export.py的文件,parse_opt中修改转出的模型文件为best.pt,还有一个include为onnx

848bbb5ff45295f214ea80bb3220c62c.png

或是直接运行

python export.py --weights runs/train/exp3/weights/best.pt --include onnx

2883a554e8c73b7936defde77b21dd8d.png

转出后就生成了best.onnx的模型文件,如果想要查看onnx的模型文件,推荐下载Netron进行查看,效果如下:

f6c187bb21278298d1c270722f2ca997.png

可以看到模型文件的输入输出及类型都显示在上面。

02

C++ OpenCV推理

49167b933aa2e774978c65e0835b4b53.png

定义好模型文件目录,类别数组,里面的ClassName顺序和前面numpuzzle.yaml的顺序要一致,直接上代码:

#pragma once
#include<iostream>
#include<opencv2/opencv.hpp>
#include<opencv2/dnn/dnn.hpp>


using namespace cv;
using namespace std;


dnn::Net net;




void deal_pred(Mat& img, Mat& preds, vector<Rect>& boxes, vector<float>& confidences, vector<int>& classIds, vector<int>& indexs)
{
    float w_ratio = img.cols / 640.0;
    float h_ratio = img.rows / 640.0;


    cout << "size1:" << preds.size[1] << endl;
    cout << "size2:" << preds.size[2] << endl;


    Mat data(preds.size[1], preds.size[2], CV_32F, preds.ptr<float>());
    for (int i = 0; i < data.rows; i++)
    {
        float conf = data.at<float>(i, 4);
        if (conf < 0.45)
        {
            continue;
        }


        //第二个参数为5+种类数,数字华容道15个种类,所以后面参数为5+15=20
        Mat clsP = data.row(i).colRange(5, 20);


        Point IndexId;
        double score;
        minMaxLoc(clsP, 0, &score, 0, &IndexId);
        if (score > 0.25)
        {
            float x = data.at<float>(i, 0);
            float y = data.at<float>(i, 1);
            float w = data.at<float>(i, 2);
            float h = data.at<float>(i, 3);


            int nx = int((x - w / 2.0) * w_ratio);
            int ny = int((y - h / 2.0) * h_ratio);
            int nw = int(w * w_ratio);
            int nh = int(h * h_ratio);


            Rect box;
            box.x = nx;
            box.y = ny;
            box.width = nw;
            box.height = nh;
            boxes.push_back(box);
            classIds.push_back(IndexId.x);
            confidences.push_back(score);


        }


    }


    dnn::NMSBoxes(boxes, confidences, 0.25, 0.45, indexs);


}


int main(int argc, char** argv) {
  //定义onnx文件
  string onnxfile = "D:/Business/DemoTEST/pyTorch/yolov5/best.onnx";


  //测试图片文件  D:/Business/DemoTEST/pyTorch/yolov5/data/images
  string testfile = "D:/Business/DemoTEST/pyTorch/yolov5/data/images/h001.jpeg";
    //string testfile = "D:/Business/DemoTEST/pyTorch/yolov5/data/images/bus.jpg";
  //测试图片文件
    string classNames[] = { "10","3","6","1","9","15","14","4","7","5","2","13","11","12","8" };




  net = dnn::readNetFromONNX(onnxfile);
  if (net.empty()) {
    cout << "加载Onnx文件失败!" << endl;
    return -1;
  }
    net.setPreferableBackend(dnn::DNN_BACKEND_OPENCV);
    net.setPreferableTarget(dnn::DNN_TARGET_CPU);




  //读取图片
  Mat src = imread(testfile);
  Mat inputBlob = dnn::blobFromImage(src, 1.0 / 255, Size(640, 640), Scalar(), true, false);


  //输入参数值
  net.setInput(inputBlob);
  //预测结果 
  Mat output = net.forward();




    vector<Rect> boxes;
    vector<float> confidences;
    vector<int> classIds;
    vector<int> indexs;
    deal_pred(src, output, boxes, confidences, classIds, indexs);




    for (int i = 0; i < indexs.size(); i++)
    {
        rectangle(src, boxes[indexs[i]], (0, 0, 255), 2);
        rectangle(src, Point(boxes[indexs[i]].tl().x, boxes[indexs[i]].tl().y - 20),
            Point(boxes[indexs[i]].tl().x + boxes[indexs[i]].br().x, boxes[indexs[i]].tl().y), Scalar(200, 200, 200), -1);
        putText(src, classNames[classIds[indexs[i]]], Point(boxes[indexs[i]].tl().x + 5, boxes[indexs[i]].tl().y - 10), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 0, 0));
        ostringstream conf;
        conf << confidences[indexs[i]];
        putText(src, conf.str(), Point(boxes[indexs[i]].tl().x + 60, boxes[indexs[i]].tl().y - 10), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 0, 0));


    }
    imshow("img", src);
    waitKey();




    return 0;
}

e6b1c43b2410a684b6c9a1c78c61d426.png

处理分类识别这里,截取的Mat区域,第二个参数20,是根据我们的分类数再加5设置的,数字华容道中设置了15个分类,再加5就等于20,所以这里的参数就是20

85a09703bc19f23b0c05f926b7b6e7d3.png

在blobFromImage中,因为我们直接用的彩色图像,在yolov5中默认的是RGB,而OpenCV的顺序返过来的默认为BGR,所以将swapRB这个参数设置为true,转换过来

OpenCV推理效果

9ad70e8ac081b8c880edee965fae0c89.png

这里使用C++ OpenCV推理的效果,这样一个Yolov5自己训练加OpenCV DNN推理的Demo就完成了。

f7734ce51f0bf1653b1a345d44a60ddc.png

f787342dd0b7597d8f30ed0b1c4ce582.png

往期精彩回顾

 

430f1dd66be4d1a4d9f2eca444638058.jpeg

目标检测yolov5的安装

 

 

77108e8964bb2f82cc4dec608b7b8536.jpeg

pyTorch入门(六)——实战Android Minist OpenCV手写数字识别(附源码地址)

 

 

13e9e8f54d71741b55af78ab7ec1d1e1.jpeg

pyTorch入门(五)——训练自己的数据集

 

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

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

相关文章

『Kubernetes』在Linux中快速安装K8S集群

&#x1f4e3;读完这篇文章里你能收获到 K8S安装全过程博主自己实操笔记带你跳过所有坑感谢点赞收藏&#xff0c;避免下次找不到~ 文章目录一、基本环境配置1. 关闭selinux2. 关闭swap分区或禁用swap文件3. 修改网卡配置4. 关闭防火墙5. 设置机器HostName6. 更新系统时间二、k…

Vue 2.x源码学习:数据响应式改造

众所周知&#xff0c;Vue是以数据驱动视图展示的&#xff0c;即Vue会监听数据的变化&#xff0c;从而自动重新渲染页面的结构。 Vue主要通过三步走来实现这个功能&#xff1a; 第一步是对数据进行响应式改造&#xff0c;即对数据的读写操作进行劫持&#xff1b; 第二步是对模…

字符数组编程题(C语言)

文章目录1、用字符%c的形式给一个字符数组赋初值&#xff0c;然后以字符串%s的形式输出2、用字符getchar&#xff08;&#xff09;的形式给一个字符数组赋初值&#xff0c;然后以字符串puts&#xff09;的形式输出4、从键盘上输入一串字符gets&#xff0c;然后输出%s5、从键盘输…

Mysql导出100万条数据,9种导出方法优缺点和速度、文件大小测试

这里写目录标题1.DBase文件2.文本文件3. CSV文件4.HTML文件5.Excel数据表低版本6.Excel文件2007年以后版本7.SQL脚本文件8.XML文件9.JSON文件总结这一次我主要就是想针对mysql导出的速度和文件大小进行优缺点测试&#xff0c;这次主要就是用上之前生成的天气表这是表里面的数据…

除夕New Year Eve,祝大家团圆幸福!

除夕&#xff0c;为岁末的最后一天夜晚,意为旧岁至此而除&#xff0c;另换新岁。New years Eve is the last night at the end of the year.which means that the old year will be removed and a new year will be replaced.除夕&#xff0c;在国人心中是具有特殊意义的&#…

第一章 TCP/IP 协议

作者简介&#xff1a;一名云计算网络运维人员、每天分享网络与运维的技术与干货。 座右铭&#xff1a;低头赶路&#xff0c;敬事如仪 个人主页&#xff1a;网络豆的主页​​​​​​ 目录 前言 一.什么是TCP/IP ​编辑 二.什么是协议 1.三要素 2.协议与标准区别 三.广…

中小型企业如何从企业内容管理 (ECM) 系统提供的工具中受益?

在当今快节奏的商业世界中&#xff0c;时间变得非常宝贵。团队越大&#xff0c;就越难有效地管理时间。但即使是中小型企业也可以从企业内容管理 (ECM) 系统提供的工具中受益。 ECM 系统使各种规模的企业能够通过数字化纸质文档、捕获电子文档和电子邮件、自动化文档驱动的流…

(转)Chrome的最小字体12px限制最终解决办法

相信不少做网站的用户会有这样一个问题&#xff0c;Chrome 默认最小字体是12px&#xff08;最新版英文也有此问题&#xff09;&#xff0c;这个是 Chrome 为了更好显示中文设计的&#xff0c;但是这样一来就会出现某些上标、下标字体过大&#xff0c;影响用户体验。之前在开发H…

ue4c++日记2(继承|设置位置|对象移动)

目录 语句速查 静态网格定义 创建静态网格对象 设置对象位置 编辑器可编辑 编辑器可见 仅类默认值处可见 速览定义可查剩下 对象移动 1继承 例子 1.创建actor 2.命名和填写路径 小插曲 3.新建一个蓝图类继承上面创建的actor 4.其可蓝图化是因为创建的c类可蓝图化 5…

【算法基础】1.8离散化

文章目录离散化如何离散确定映射方式区间和当数据范围的跨度很大&#xff0c;但是数据很稀疏时&#xff0c;可以使用离散化。 离散化 如何离散 数据范围很大&#xff0c;但是并不是每个数字都会出现&#xff0c;就可以将原始数据按照顺序映射到一个小的数据范围。 确定映射方…

第五届字节跳动青训营 前端进阶学习笔记(二)JavaScript编码规范

文章目录1.前言2.写好JS的一些基本原则这是我参与「第五届青训营 」伴学笔记创作活动的第 2 天 1.前言 本次课程主要讲解了有关JavaScript编码原则和代码优化的相关问题。 重点内容&#xff1a; HTML、CSS、JS各司其责具备正确性、扩展性、复用性的组件封装函数式编程思想代…

进程、线程及python的多线程编程

目录 一.进程、线程和并行执行 1.什么是进程、线程 注意 2.什么是并行执行 二.python的多线程编程 threading模块 语法 多线程编程的传参 演示 三.总结 一.进程、线程和并行执行 1.什么是进程、线程 现代操作系统比如Mac OS X,UNIX, Linux, Windows等&#xff0c;都是…

CSC|2023年艺术类人才培养特别项目解读及建议

目前国家留学基金委&#xff08;CSC&#xff09;官网已经发布了2023年艺术类人才培养特别项目通知&#xff0c;知识人网小编现将其选派工作流程、选派办法、申请材料及说明&#xff08;访问学者、博士后&#xff09;原文转载并加以解读、提出建议。知识人网解读及建议一、2023年…

新产品Digi XBee RR无线模块迁移指南

&#xff08;咨询申请 - 上海皕科电子有限公司--专注物联网 登记后&#xff0c;可提供相关资料&#xff0c;购买XBee模块&#xff0c;有机会获得USB评估底板及相关中文资料&#xff0c;或者免费申请借用评估套件&#xff09; 目录 一、简介 1、MicroPython 2、蓝牙 3、文件…

SpringBoot+easypol前后端分离实现excel导出(保姆级教程)

本篇博文目录1.后端2.前端(采用axios)3.运行效果1.后端 导入easypoi的依赖 <!--用来处理POL相关的操作:easypol--><dependency><groupId>cn.afterturn</groupId><artifactId>easypoi-base</artifactId><version>4.2.0</version&…

Cadence OrCAD: 层次化设计中的电源和地符号

Cadence OrCAD: 层次化设计中的电源和地符号 层次化设计操作步骤&#xff1a;Cadence OrCAD: 层次化设计 Hierarchical Design 本文介绍一个小问题&#xff1a;分层设计中的电源和地符号的作用范围。 电源符号默认作用范围 OrCAD中电源和地符号默认是全局的&#xff0c;也就…

2023年1月中国数据库排行榜:OceanBase 持续两月登顶,前四甲青云直上开新局

一元复始&#xff0c;万象更新。 国产数据库在经历过耕获菑畲的一年后&#xff0c;产品、生态、人才队伍建设等都取得了重大的进展。2023年1月 墨天轮中国数据库流行度排行 火热出炉&#xff0c;本月排行榜“属性”列新增“多模型”&#xff0c;榜单前十名变动较小&#xff0c;…

基于springboot,vue影院订票系统

开发工具&#xff1a;IDEA服务器&#xff1a;Tomcat9.0&#xff0c; jdk1.8项目构建&#xff1a;maven数据库&#xff1a;mysql5.7系统用户前台和管理后台两部分&#xff0c;项目采用前后端分离前端技术&#xff1a;vue elementUI服务端技术&#xff1a;springbootmybatis项目功…

JAVA开发(Netty框架与NIO)

所谓IO即input和output的缩写&#xff0c;是对数据的流入和流出的一种抽象。其中NIONIO主要有三大核心部分&#xff1a;Channel&#xff08;通道&#xff09;&#xff0c;Buffer&#xff08;缓冲区&#xff09;,Selector&#xff08;选择器&#xff09;。Channel(通道)&#xf…

Day54 跨域CORS资源JSONP回调域名接管劫持

前言&#xff1a; #知识点&#xff1a; 1、子域名接管-检测&探针&利用 2、COSP跨域资源-检测&探针&利用 3、JSONP跨域回调-检测&探针&利用 #前置知识点&#xff1a; -同源策略(SOP)-“同源”包括三个条件&#xff1a;同协议 同域名 同端口 同源策…