目标检测实战(四):YOLOV4-Tiny 源码训练、测试、验证详细步骤

简介: 这篇文章详细介绍了使用YOLOv4-Tiny进行目标检测的实战步骤,包括下载源码和权重文件、配置编译环境、进行简单测试、训练VOC数据集、生成训练文件、准备训练、开始训练以及多GPU训练的步骤。文章还提供了相应的代码示例,帮助读者理解和实践YOLOv4-Tiny模型的训练和测试过程。

下载源码和权重文件

源码:https://github.com/AlexeyAB/darknet
权重:https://github.com/AlexeyAB/darknet/releases/download/darknet_yolo_v4_pre/yolov4-tiny.weights

编译环境

修改makefile(打开darknet目录下makefile文件),
根据具体情况修改

GPU=1        # 使用GPU
CUDNN=1        # 使用GPU
CUDNN_HALF=1        # 混合精度训练,用于加速
OPENCV=1        # 使用opencv
AVX=0
OPENMP=0
LIBSO=1        # 生成libdarknet.so,便于python调用darknet模型
ZED_CAMERA=0
ZED_CAMERA_v2_8=0

#ARCH= -gencode arch=compute_35,code=sm_35 \
#      -gencode arch=compute_50,code=[sm_50,compute_50] \
#      -gencode arch=compute_52,code=[sm_52,compute_52] \
#        -gencode arch=compute_61,code=[sm_61,compute_61]

OS := $(shell uname)

# GeForce RTX 3070, 3080, 3090
# ARCH= -gencode arch=compute_86,code=[sm_86,compute_86]

# Kepler GeForce GTX 770, GTX 760, GT 740
# ARCH= -gencode arch=compute_30,code=sm_30

# Tesla A100 (GA100), DGX-A100, RTX 3080
ARCH= -gencode arch=compute_80,code=[sm_80,compute_80]

# Tesla V100
# ARCH= -gencode arch=compute_70,code=[sm_70,compute_70]
NVCC=/usr/local/cuda-11.1/bin/nvcc

然后直接终端进行编译

sudo make

就会在当前文件夹生成libdarknet.so文件。

简单测试

./darknet detector test cfg/coco.data cfg/yolov4-tiny.cfg yolov4-tiny.weights data/dog.jpg    # 图片测试
./darknet detector demo cfg/coco.data cfg/yolov4-tiny.cfg yolov4-tiny.weights -ext_output test.mp4        # 视频测试
./darknet detector demo cfg/coco.data cfg/yolov4-tiny.cfg yolov4-tiny.weights -c 0        # 摄像头测试

训练VOC数据集

通过下面代码划分,创建一个data_spilt.py文件和对应的路径

import os
import random

trainval_percent = 0.8  # 所有数据中用来训练的比例 trainval/all  trainval=train+val
train_percent = 1     # trainval用来训练的比例 train/trainval
xmlfilepath = '/home/lqs/Downloads/dataset/VOC/VOC2007/Annotations'
txtsavepath = './VOCdevkit/main'
total_xml = os.listdir(xmlfilepath)

num=len(total_xml)
list=range(num)
tv=int(num*trainval_percent)
tr=int(tv*train_percent)
trainval= random.sample(list,tv)
train=random.sample(trainval,tr)

ftrainval = open(txtsavepath+'/trainval.txt', 'w+')    # 训练集数据+验证集数据
ftest = open(txtsavepath+'/test.txt', 'w+')    # 测试集
ftrain = open(txtsavepath+'/train.txt', 'w+')    # 训练集
fval = open(txtsavepath+'/val.txt', 'w+')    # 验证集

for i  in list:
    name=total_xml[i][:-4]+'\n'
    if i in trainval:
        ftrainval.write(name)
        if i in train:
            ftrain.write(name)
        else:
            fval.write(name)
    else:
        ftest.write(name)

ftrainval.close()
ftrain.close()
fval.close()
ftest.close()
print('Finished!')

生成训练文件

修改sets和classes以及里面的关键路径即可,这个代码可自己创建,得到2007_test.txt、2007_train.txt、2007_val.txt三个文件

#---------------------------------------------#
#   运行前一定要修改classes
#   如果生成的2007_train.txt里面没有目标信息
#   那么就是因为classes没有设定正确
#---------------------------------------------#
import xml.etree.ElementTree as ET
from os import getcwd

sets=[('2007', 'train'), ('2007', 'val'), ('2007', 'test')]
#-----------------------------------------------------#
#   这里设定的classes顺序要和model_data里的txt一样
#-----------------------------------------------------#
classes = ["aeroplane", "bicycle", "bird", "boat", "bottle", "bus", "car", "cat", "chair", "cow", "diningtable", "dog", "horse", "motorbike", "person", "pottedplant", "sheep", "sofa", "train", "tvmonitor"]

def convert_annotation(year, image_id, list_file):
    in_file = open('/home/lqs/Downloads/dataset/VOC/VOC%s/Annotations/%s.xml'%(year, image_id), encoding='utf-8')
    tree=ET.parse(in_file)
    root = tree.getroot()

    for obj in root.iter('object'):
        difficult = 0 
        if obj.find('difficult')!=None:
            difficult = obj.find('difficult').text
        cls = obj.find('name').text
        if cls not in classes or int(difficult)==1:
            continue
        cls_id = classes.index(cls)
        xmlbox = obj.find('bndbox')
        b = (int(float(xmlbox.find('xmin').text)), int(float(xmlbox.find('ymin').text)), int(float(xmlbox.find('xmax').text)), int(float(xmlbox.find('ymax').text)))
        list_file.write(" " + ",".join([str(a) for a in b]) + ',' + str(cls_id))

wd = getcwd()

for year, image_set in sets:
    image_ids = open('/home/lqs/Downloads/dataset/VOC/VOC%s/ImageSets/Main/%s.txt'%(year, image_set), encoding='utf-8').read().strip().split()
    list_file = open('%s_%s.txt'%(year, image_set), 'w', encoding='utf-8')
    for image_id in image_ids:
        list_file.write('/home/lqs/Downloads/dataset/VOC%s/JPEGImages/%s.jpg'%(year, image_id))
        convert_annotation(year, image_id, list_file)
        list_file.write('\n')
    list_file.close()

训练准备

  • 修改darknet-master/cfg/voc.data
classes= 20        # 改成自己的类别数
train  = /home/pjreddie/data/2007_train.txt    # 改成voc_label.py生成的2007_train.txt路径
valid  = /home/pjreddie/data/2007_test.txt    # 改成voc_label.py生成的2007_test.txt路径
names = data/voc.names    # 改成有自己类别的names文件
backup = backup/    # 改为backup/即可
  • 修改darknet-master/cfg/yolov4-tiny.cfg
[net]
# Testing
#batch=1
#subdivisions=1
# Training
batch=64    # 每64张图片更新一次参数
subdivisions=16    # 64张图片分16次放入显卡中,每次4张。因为一次放入过多会内存不足,根据自己显卡性能更改
width=416    # 将输入的图片resize到width×height后,放入网络中训练
height=416    # 只要是32的倍数即可
channels=3
momentum=0.9
decay=0.0005
angle=0
saturation = 1.5
exposure = 1.5
hue=.1
  • 找到如下位置(以yolo为关键字),修改filters和classes,整个文本共有2个filters和2个classes需要修改
[convolutional]
size=1
stride=1
pad=1
filters=255    # 改为3*(classes +5)。不过官网上不建议这种做法,具体可以查官方github 修改地方不止一处!
activation=linear

[yolo]
mask = 3,4,5
anchors = 10,14,  23,27,  37,58,  81,82,  135,169,  344,319
classes=80    # 改为自己的类别数
num=6
jitter=.3
scale_x_y = 1.05
cls_normalizer=1.0
iou_normalizer=0.07

开始训练

在darknet目录下,使用第一条命令生成预训练权重yolov4-tiny.conv.29,第二条命令开始训练

./darknet partial cfg/yolov4-tiny.cfg yolov4-tiny.weights yolov4-tiny.conv.29 29    # 生成yolov4-tiny.conv.29文件,用于迁移学习
./darknet detector train cfg/voc.data cfg/yolov4-tiny.cfg yolov4-tiny.conv.29 -map    # 训练模型
# -map参数可以在训练过程中对测试集计算map并在chart上显示)

Error in load_data_detection() - OpenCV

多GPU训练

./darknet detector train [.data] [.cfg] [.weight] -gpus 0, 1, 2    # 多GPU训练
相关实践学习
在云上部署ChatGLM2-6B大模型(GPU版)
ChatGLM2-6B是由智谱AI及清华KEG实验室于2023年6月发布的中英双语对话开源大模型。通过本实验,可以学习如何配置AIGC开发环境,如何部署ChatGLM2-6B大模型。
目录
相关文章
|
4天前
|
数据采集 JSON JavaScript
Cypress 插件实战:让测试更稳定,不再“偶尔掉链子”
本文分享如何通过自定义Cypress插件解决测试不稳定的痛点。插件可实现智能等待、数据预处理等能力,替代传统硬性等待,有效减少偶发性失败,提升测试效率和可维护性。文内包含具体实现方法与最佳实践。
|
1月前
|
存储 关系型数据库 测试技术
玩转n8n测试自动化:核心节点详解与测试实战指南
n8n中节点是自动化测试的核心,涵盖触发器、数据操作、逻辑控制和工具节点。通过组合节点,测试工程师可构建高效、智能的测试流程,提升测试自动化能力。
|
18天前
|
人工智能 自然语言处理 JavaScript
Playwright MCP在UI回归测试中的实战:构建AI自主测试智能体
Playwright MCP结合AI智能体,革新UI回归测试:通过自然语言驱动浏览器操作,降低脚本编写门槛,提升测试效率与覆盖范围。借助快照解析、智能定位与Jira等工具集成,实现从需求描述到自动化执行的闭环,推动测试迈向智能化、民主化新阶段。
|
1月前
|
人工智能 数据可视化 测试技术
AI 时代 API 自动化测试实战:Postman 断言的核心技巧与实战应用
AI 时代 API 自动化测试实战:Postman 断言的核心技巧与实战应用
367 11
|
4月前
|
Java 测试技术 容器
Jmeter工具使用:HTTP接口性能测试实战
希望这篇文章能够帮助你初步理解如何使用JMeter进行HTTP接口性能测试,有兴趣的话,你可以研究更多关于JMeter的内容。记住,只有理解并掌握了这些工具,你才能充分利用它们发挥其应有的价值。+
828 23
|
9月前
|
数据可视化 前端开发 测试技术
接口测试新选择:Postman替代方案全解析
在软件开发中,接口测试工具至关重要。Postman长期占据主导地位,但随着国产工具的崛起,越来越多开发者转向更适合中国市场的替代方案——Apifox。它不仅支持中英文切换、完全免费不限人数,还具备强大的可视化操作、自动生成文档和API调试功能,极大简化了开发流程。
|
6月前
|
SQL 安全 测试技术
2025接口测试全攻略:高并发、安全防护与六大工具实战指南
本文探讨高并发稳定性验证、安全防护实战及六大工具(Postman、RunnerGo、Apipost、JMeter、SoapUI、Fiddler)选型指南,助力构建未来接口测试体系。接口测试旨在验证数据传输、参数合法性、错误处理能力及性能安全性,其重要性体现在早期发现问题、保障系统稳定和支撑持续集成。常用方法包括功能、性能、安全性及兼容性测试,典型场景涵盖前后端分离开发、第三方服务集成与数据一致性检查。选择合适的工具需综合考虑需求与团队协作等因素。
851 24
|
6月前
|
SQL 测试技术
除了postman还有什么接口测试工具
最好还是使用国内的接口测试软件,其实国内替换postman的软件有很多,这里我推荐使用yunedit-post这款接口测试工具来代替postman,因为它除了接口测试功能外,在动态参数的支持、后置处理执行sql语句等支持方面做得比较好。而且还有接口分享功能,可以生成接口文档给团队在线浏览。
265 2
|
8月前
|
JSON 前端开发 测试技术
大前端之前端开发接口测试工具postman的使用方法-简单get接口请求测试的使用方法-简单教学一看就会-以实际例子来说明-优雅草卓伊凡
大前端之前端开发接口测试工具postman的使用方法-简单get接口请求测试的使用方法-简单教学一看就会-以实际例子来说明-优雅草卓伊凡
459 10
大前端之前端开发接口测试工具postman的使用方法-简单get接口请求测试的使用方法-简单教学一看就会-以实际例子来说明-优雅草卓伊凡
|
8月前
|
JSON 前端开发 API
以项目登录接口为例-大前端之开发postman请求接口带token的请求测试-前端开发必学之一-如果要学会联调接口而不是纯写静态前端页面-这个是必学-本文以优雅草蜻蜓Q系统API为实践来演示我们如何带token请求接口-优雅草卓伊凡
以项目登录接口为例-大前端之开发postman请求接口带token的请求测试-前端开发必学之一-如果要学会联调接口而不是纯写静态前端页面-这个是必学-本文以优雅草蜻蜓Q系统API为实践来演示我们如何带token请求接口-优雅草卓伊凡
401 5
以项目登录接口为例-大前端之开发postman请求接口带token的请求测试-前端开发必学之一-如果要学会联调接口而不是纯写静态前端页面-这个是必学-本文以优雅草蜻蜓Q系统API为实践来演示我们如何带token请求接口-优雅草卓伊凡