(全程记录yolov7入门到实现训练)跟着炮哥yolov5教程自学yolov7,接触yolov7半天,成功实现训练

本文主要是介绍(全程记录yolov7入门到实现训练)跟着炮哥yolov5教程自学yolov7,接触yolov7半天,成功实现训练,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

       最近跟着学长一起做项目,需要用到yolo实现蜜蜂图像检测,网上找资料,最先在b站看到炮哥的yolov5,非常详细,成功实现yolov5目标检测。但是yolov5在蜜蜂(小目标)检测上并没有达到我们的预期,于是我们打算用yolov7实现蜜蜂图像检测。

       网上找了很多yolov7教程,发现yolov7跟yolov5差别不大,我就跟着炮哥yolov5的教程自学了yolov7,并成功实现了蜜蜂图像检测,目前是466张数据集按照82比例划分正确率达到80%以上。

       本文记录我自学yolov7的全过程,找数据集->筛选照片并重命名->labelimg打标签->voc转txt并按比例划分数据集->github下载yolov7模型和yolov7.pt参数文件->配置模型、数据yaml文件->修改train文件运行并通过tensorboard查看

一、前言

我用的学长的电脑,他的电脑已经配好了环境。
Anaconda3(虚拟环境pytorch37)+cuda11.1+torch1.8.1+torchvision0.9.1+python3.7.15

 考虑到部分没有配置经验的朋友,下面简单说一下环境配置的步骤。

步骤主要是:查看cuda版本

(1)win+R,输入cmd,输入ncvv --version,查看cuda版本

如上图,学长电脑的cuda是11.1

上网百度查找与cuda相匹配的pytorch版本,网页地址:PyTorch和CUDA版本对应关系 - 墨莲玦 - 博客园

cuda与pytorch版本对应关系

 (2)这里选择与cuda11.1对应的pytorch1.8.1,然后再去找python、torch之间的对应关系。

地址:torch、torchvision、python、cuda 版本对应关系_来一碗锅巴洋芋的博客-CSDN博客_torch和cuda版本对应

python和torch对应关系

 (3)最终确定配置torch1.8.1+torchvision0.9.1+python3.7的环境。

        安装就很简单了,去pytorch官网找下载命令就可以了,然后到anaconda中指定python版本创建新的虚拟环境,激活虚拟环境然后下载pytorch就可以啦。(如果有需要,后面再单独补一期配置环境的博客)

二、找数据集+下载解压+创建项目文件夹+筛选所需图片并重命名

        我都是在ai studio平台寻找公开的数据集,搜索关键字“蜜蜂”找到如下数据集,哪一个都可以。

        点击上图箭头标出的进入到数据集详细界面,下拉点击“下载查看更多”就开始下载了。

        下载好后,我在D盘建了一个空文件夹,名为honeybee,存放我们要用到的数据集、yolov5等等。把下载好的压缩包放入到项目文件夹中,并解压。文件结构如下图所示。

        我们查看解压后的数据集文件结构,如下图所示。

        我们点击去看一看,选择我们需要的就可以啦。

        这里我最终选择的是bee1和wasp2。

        简单说一下为什么选择这两个文件夹,bee1不同地方不同环境不同状态下的蜜蜂图片多,但是bee1只有单个蜜蜂;wasp2中有多个蜜蜂的照片。

        然后在项目根文件夹创建如下结构的文件目录:

        ——VOCdevkit

        ————VOC2007

        ————————Annotations

        ————————JPEGImages

        ————————predefined_classes.txt

        创建好后,我们把需要的图片放到JPEGImages文件夹中。

        这里我没有选择太多,500张照片,其中包含几十张多蜜蜂的图片。

        (左边是JPEGImages文件夹,右边是我们从网上下载解压后的数据集文件,把网上的剪切到我们的JPEGImages文件夹)

        从bee1剪切了490张,然后再去swap2里面找10张包含多个蜜蜂的图片

        最终,500张图片

        然后,我们给它排序,从1到500

        执行rename.py文件夹,修改好路径,执行就可以了。

        rename.py是我写好的,文件重命名,我把rename.py放在项目根目录下。

        rename.py代码如下:

import os
oldpath = os.listdir(r"D:\honeybee\VOCdevkit\VOC2007\JPEGImages")
path = r"D:\\honeybee\\VOCdevkit\\VOC2007\\JPEGImages\\"
for i in range(len(oldpath)):oldimg = path + oldpath[i]newimg = path + str(i+1)+".jpg"os.rename(oldimg,newimg)

        右键通过记事本打开文件,修改几处地方

        修改oldpath、path

        oldpath:我们JPEGimages绝对路径

        path:oldpath把后面的JPEGimages去掉,并把\改成\\就可以啦

        使用anaconda,激活进入虚拟环境,然后进入项目根目录,执行rename.py文件

        查看重命名后的JPEGimages文件夹:

三、打voc(xml)标签,转为yolo(txt)格式并按照比例划分训练集和测试集

        把我们的图像检测类别名称写进去

        有多个名称就换行写

        这里我们只有一个honeeybee,就按照下图写

        然后进入虚拟环境,再进入到我们的JPEGImages文件夹,执行下面的命令:

labelimg JPEGImages predefined_classes.txt

        就打开labelimg标注软件了

        打开后第一次见的话,不要慌,我们在左侧边栏检查源文件路径更改目标文件路径就可以了。

        源文件路径就是我们存放照片的JPEGImages文件夹,标签信息存放文件就是我们的Annotations文件夹。(下图左确认源文件夹对不对,下图右选择标签保存文件夹)

        选择完后,就会显示我们的第一张图片,然后我们按下W键标注信息,标注完后按下D键再标注下一张照片,同理,按住A键返回上一张照片。

        (有几个蜜蜂就打几个标签,下图有两个那就打两个)

        打完后,右边侧边栏会显示打了多少标签

        按下D键跳转到下一张图片,如果提示是否保存,点击确认就可以了。

        如果不想每次都提示,可以设置默认保存。

        每次保存的文件都放在了我们的标签存储文件夹下。

        然后就可以开心的打标签了,打完最后一张,点击右上角关闭推出就可以了。

        最后是466张图片和466张标签文件,标注过程中有一些图片不是很好就给删除掉了,如果删除图片的话,标签和原图片都删掉。

        把voc文件转成yolo并划分训练集和测试集

        这里用的是炮哥的源代码,把源代码文件2.py放在项目根目录下运行就可以啦:

        炮哥数据集划分文章链接:

目标检测---数据集格式转化及训练集和验证集划分_炮哥带你学的博客-CSDN博客_xmlbuilder.writexml(f, indent='\t', newl='\n', add

        2.py源代码如下:

import xml.etree.ElementTree as ET
import pickle
import os
from os import listdir, getcwd
from os.path import join
import random
from shutil import copyfileclasses = ["honeybee"]
#classes=["ball"]TRAIN_RATIO = 80def clear_hidden_files(path):dir_list = os.listdir(path)for i in dir_list:abspath = os.path.join(os.path.abspath(path), i)if os.path.isfile(abspath):if i.startswith("._"):os.remove(abspath)else:clear_hidden_files(abspath)def convert(size, box):dw = 1./size[0]dh = 1./size[1]x = (box[0] + box[1])/2.0y = (box[2] + box[3])/2.0w = box[1] - box[0]h = box[3] - box[2]x = x*dww = w*dwy = y*dhh = h*dhreturn (x,y,w,h)def convert_annotation(image_id):in_file = open('VOCdevkit/VOC2007/Annotations/%s.xml' %image_id)out_file = open('VOCdevkit/VOC2007/YOLOLabels/%s.txt' %image_id, 'w')tree=ET.parse(in_file)root = tree.getroot()size = root.find('size')w = int(size.find('width').text)h = int(size.find('height').text)for obj in root.iter('object'):difficult = obj.find('difficult').textcls = obj.find('name').textif cls not in classes or int(difficult) == 1:continuecls_id = classes.index(cls)xmlbox = obj.find('bndbox')b = (float(xmlbox.find('xmin').text), float(xmlbox.find('xmax').text), float(xmlbox.find('ymin').text), float(xmlbox.find('ymax').text))bb = convert((w,h), b)out_file.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n')in_file.close()out_file.close()wd = os.getcwd()
wd = os.getcwd()
data_base_dir = os.path.join(wd, "VOCdevkit/")
if not os.path.isdir(data_base_dir):os.mkdir(data_base_dir)
work_sapce_dir = os.path.join(data_base_dir, "VOC2007/")
if not os.path.isdir(work_sapce_dir):os.mkdir(work_sapce_dir)
annotation_dir = os.path.join(work_sapce_dir, "Annotations/")
if not os.path.isdir(annotation_dir):os.mkdir(annotation_dir)
clear_hidden_files(annotation_dir)
image_dir = os.path.join(work_sapce_dir, "JPEGImages/")
if not os.path.isdir(image_dir):os.mkdir(image_dir)
clear_hidden_files(image_dir)
yolo_labels_dir = os.path.join(work_sapce_dir, "YOLOLabels/")
if not os.path.isdir(yolo_labels_dir):os.mkdir(yolo_labels_dir)
clear_hidden_files(yolo_labels_dir)
yolov5_images_dir = os.path.join(data_base_dir, "images/")
if not os.path.isdir(yolov5_images_dir):os.mkdir(yolov5_images_dir)
clear_hidden_files(yolov5_images_dir)
yolov5_labels_dir = os.path.join(data_base_dir, "labels/")
if not os.path.isdir(yolov5_labels_dir):os.mkdir(yolov5_labels_dir)
clear_hidden_files(yolov5_labels_dir)
yolov5_images_train_dir = os.path.join(yolov5_images_dir, "train/")
if not os.path.isdir(yolov5_images_train_dir):os.mkdir(yolov5_images_train_dir)
clear_hidden_files(yolov5_images_train_dir)
yolov5_images_test_dir = os.path.join(yolov5_images_dir, "val/")
if not os.path.isdir(yolov5_images_test_dir):os.mkdir(yolov5_images_test_dir)
clear_hidden_files(yolov5_images_test_dir)
yolov5_labels_train_dir = os.path.join(yolov5_labels_dir, "train/")
if not os.path.isdir(yolov5_labels_train_dir):os.mkdir(yolov5_labels_train_dir)
clear_hidden_files(yolov5_labels_train_dir)
yolov5_labels_test_dir = os.path.join(yolov5_labels_dir, "val/")
if not os.path.isdir(yolov5_labels_test_dir):os.mkdir(yolov5_labels_test_dir)
clear_hidden_files(yolov5_labels_test_dir)train_file = open(os.path.join(wd, "yolov5_train.txt"), 'w')
test_file = open(os.path.join(wd, "yolov5_val.txt"), 'w')
train_file.close()
test_file.close()
train_file = open(os.path.join(wd, "yolov5_train.txt"), 'a')
test_file = open(os.path.join(wd, "yolov5_val.txt"), 'a')
list_imgs = os.listdir(image_dir) # list image files
prob = random.randint(1, 100)
print("Probability: %d" % prob)
for i in range(0,len(list_imgs)):path = os.path.join(image_dir,list_imgs[i])if os.path.isfile(path):image_path = image_dir + list_imgs[i]voc_path = list_imgs[i](nameWithoutExtention, extention) = os.path.splitext(os.path.basename(image_path))(voc_nameWithoutExtention, voc_extention) = os.path.splitext(os.path.basename(voc_path))annotation_name = nameWithoutExtention + '.xml'annotation_path = os.path.join(annotation_dir, annotation_name)label_name = nameWithoutExtention + '.txt'label_path = os.path.join(yolo_labels_dir, label_name)prob = random.randint(1, 100)print("Probability: %d" % prob)if(prob < TRAIN_RATIO): # train datasetif os.path.exists(annotation_path):train_file.write(image_path + '\n')convert_annotation(nameWithoutExtention) # convert labelcopyfile(image_path, yolov5_images_train_dir + voc_path)copyfile(label_path, yolov5_labels_train_dir + label_name)else: # test datasetif os.path.exists(annotation_path):test_file.write(image_path + '\n')convert_annotation(nameWithoutExtention) # convert labelcopyfile(image_path, yolov5_images_test_dir + voc_path)copyfile(label_path, yolov5_labels_test_dir + label_name)
train_file.close()
test_file.close()

        2.py放在项目根目录,执行2.py,不用修改。

        运行完后,再来看我们的项目文件,发现多了一些文件

        根目录多了两个:yolov5_train.txt和yolov5_val.txt,里面放的是图片的绝对路径

        这两个没有什么用,想删就删

        进入VOCdevkit文件夹,多了两个文件夹,images和labels文件夹,这两个是我们要用到的。

        再进入到VOC2007文件夹,发现多了1个文件夹,YOLOLabels文件夹,里面放的是未分成训练和测试的yolo(txt)文件。

        我们一般不用这个文件, 我们用分成训练和测试的yolo(txt)文件,这两个文件就是上面图片中的images和labels文件夹。

四、github下载yolov7 0.1模型和yolov7.pt参数文件,并把数据集导入到yolov7项目中

        把从github上下载的yolov7 0.1和yolov7.pt参数文件放在项目根目录下。如下图所示:

        将模型文件解压到当前文件目录:

        用pycgarm将解压后的yolov7 文件夹打开

        打开后,在右下角选择解释器,根据自己的情况选择就可以啦。

        然后,我们把项目根目录的数据集文件 复制-粘贴 到项目根目录中。

        数据集粘贴过程中的截图:

        粘贴完后yolov7项目结构如下图所示:

五、 修改两个数据配置文件(yaml)

        大白话就是,cfg/deploy/第一个模型配置文件.yaml  和  data/第二个数据集配置文件.yaml

        如下图:

        到这步了,不要慌,配置文件不要我们写,只要复制粘贴改名简单修改就好了。

        修改模型配置文件:复制并粘贴yolov7.yaml,重命名(想取啥名取啥名)hb,如下图所示:

        修改hb文件,只修改nc就可以,目标检测有几类就写几类,我只识别蜜蜂,所以nc写1。

        再修改数据配置文件,复制粘贴coco.yaml,重命名(想怎么取怎么取)hb.yaml

        修改hb.yaml数据配置文件:

        修改4部分:

        (1)第4行注释掉

        (2)7-9行修改数据集图片引用路径,只引用images下的train和val,如果数据集分类时只分了train和val,没有test,可以选择注释掉test或者把test路径修改成val路径。(另外,最重要的是,这里只引用了images,没有引用labels,yolo会自动根据images寻找相对应的labels文件,所以我们只告诉yolo images下的train和val就可以了)

        (3)修改图像检测类别数nc

        (4)修改图像检测类别名称,最好是英文,中文会乱码(乱码也可以解决,这里先不提了)

六、 修改train文件,运行并通过tensorboard查看

        先把yolov7.pt参数文件导入到我们的模型根目录里(复制粘贴就可以)

        进入trian文件,直接往下拉就可以了

        依次修改default :

        --weights default 修改成我们项目根路径刚刚导入的yolov7.pt

        --cfg default 修改成我们的模型配置文件

        --data default 修改成我们数据配置文件

        --epochs 就是训练轮数 这里default我写成50,先跑50轮看一看

        --batch-size 就是每一次加载多少张照片,这台电脑的显卡是1650ti,我设置了4

        修改完后,如果你的电脑操作系统是windows,需要再设置num_workers为0,如下图

        修改完后,在train.py中右键单击运行就可以啦

        运行一段时间后,截图如下所示(1轮差不多15分钟,一小时能跑4轮)

        光看这个看不出啥东西,我们进入tensorboard看看如何。

        pycharm底部选择终端,激活并进入虚拟环境,执行下面语句:

tensorboard --logdir=runs/train

        弹出网址后,按住ctrl点击跳转就可以看到啦

        到此,训练就没有问题啦!

七、结尾

        以上就是我从收集数据集到训练成功的全过程

        下个文档我们再说如何使用训练好的参数去图像检测(detect)

这篇关于(全程记录yolov7入门到实现训练)跟着炮哥yolov5教程自学yolov7,接触yolov7半天,成功实现训练的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/405969

相关文章

Python pandas库自学超详细教程

《Pythonpandas库自学超详细教程》文章介绍了Pandas库的基本功能、安装方法及核心操作,涵盖数据导入(CSV/Excel等)、数据结构(Series、DataFrame)、数据清洗、转换... 目录一、什么是Pandas库(1)、Pandas 应用(2)、Pandas 功能(3)、数据结构二、安

Python使用Tenacity一行代码实现自动重试详解

《Python使用Tenacity一行代码实现自动重试详解》tenacity是一个专为Python设计的通用重试库,它的核心理念就是用简单、清晰的方式,为任何可能失败的操作添加重试能力,下面我们就来看... 目录一切始于一个简单的 API 调用Tenacity 入门:一行代码实现优雅重试精细控制:让重试按我

Redis客户端连接机制的实现方案

《Redis客户端连接机制的实现方案》本文主要介绍了Redis客户端连接机制的实现方案,包括事件驱动模型、非阻塞I/O处理、连接池应用及配置优化,具有一定的参考价值,感兴趣的可以了解一下... 目录1. Redis连接模型概述2. 连接建立过程详解2.1 连php接初始化流程2.2 关键配置参数3. 最大连

Python实现网格交易策略的过程

《Python实现网格交易策略的过程》本文讲解Python网格交易策略,利用ccxt获取加密货币数据及backtrader回测,通过设定网格节点,低买高卖获利,适合震荡行情,下面跟我一起看看我们的第一... 网格交易是一种经典的量化交易策略,其核心思想是在价格上下预设多个“网格”,当价格触发特定网格时执行买

Spring WebClient从入门到精通

《SpringWebClient从入门到精通》本文详解SpringWebClient非阻塞响应式特性及优势,涵盖核心API、实战应用与性能优化,对比RestTemplate,为微服务通信提供高效解决... 目录一、WebClient 概述1.1 为什么选择 WebClient?1.2 WebClient 与

java中pdf模版填充表单踩坑实战记录(itextPdf、openPdf、pdfbox)

《java中pdf模版填充表单踩坑实战记录(itextPdf、openPdf、pdfbox)》:本文主要介绍java中pdf模版填充表单踩坑的相关资料,OpenPDF、iText、PDFBox是三... 目录准备Pdf模版方法1:itextpdf7填充表单(1)加入依赖(2)代码(3)遇到的问题方法2:pd

python设置环境变量路径实现过程

《python设置环境变量路径实现过程》本文介绍设置Python路径的多种方法:临时设置(Windows用`set`,Linux/macOS用`export`)、永久设置(系统属性或shell配置文件... 目录设置python路径的方法临时设置环境变量(适用于当前会话)永久设置环境变量(Windows系统

Python对接支付宝支付之使用AliPay实现的详细操作指南

《Python对接支付宝支付之使用AliPay实现的详细操作指南》支付宝没有提供PythonSDK,但是强大的github就有提供python-alipay-sdk,封装里很多复杂操作,使用这个我们就... 目录一、引言二、准备工作2.1 支付宝开放平台入驻与应用创建2.2 密钥生成与配置2.3 安装ali

Spring Security 单点登录与自动登录机制的实现原理

《SpringSecurity单点登录与自动登录机制的实现原理》本文探讨SpringSecurity实现单点登录(SSO)与自动登录机制,涵盖JWT跨系统认证、RememberMe持久化Token... 目录一、核心概念解析1.1 单点登录(SSO)1.2 自动登录(Remember Me)二、代码分析三、

PyCharm中配置PyQt的实现步骤

《PyCharm中配置PyQt的实现步骤》PyCharm是JetBrains推出的一款强大的PythonIDE,结合PyQt可以进行pythion高效开发桌面GUI应用程序,本文就来介绍一下PyCha... 目录1. 安装China编程PyQt1.PyQt 核心组件2. 基础 PyQt 应用程序结构3. 使用 Q