基于YOLOv4的目标检测模型训练与测试

一、引言

随着深度学习技术的不断发展,目标检测作为计算机视觉领域的重要任务之一,已经取得了显著的进步。YOLO(You Only Look Once)系列算法作为实时目标检测的代表性方法,凭借其出色的性能和速度,在学术界和工业界都受到了广泛关注。本文将介绍如何使用YOLOv4算法,结合自己标注的数据集进行训练,并最终使用测试图片对训练好的模型进行结果检测与展示。

YOLOv4是一种目标检测算法,全称为You Only Look Once v4。它是YOLO系列算法的新版本,于2020年发布。YOLOv4通过使用深度卷积神经网络来实现实时目标检测。与其他目标检测算法相比,YOLOv4的主要优势在于速度快且准确率高。YOLOv4采用了许多创新的技术,包括CSPDarknet53架构、PANet、SAM、YOLOv4head等。这些技术的结合使得YOLOv4在目标检测任务上取得了很好的效果。YOLOv4在训练数据集上进行训练后,可以通过输入一张图片,输出图片中所有检测到的目标的类别、位置和置信度。这种实时的目标检测能够应用于许多领域,如智能监控、自动驾驶、机器人等。

在本文中,我将分享如何使用YOLOv4代码和自己标注的数据集进行训练,以及展示训练好的模型在测试图片上进行目标检测的结果。YOLOv4是一种高效的目标检测算法,具有快速和准确的特点,能够在实时场景中实现目标检测任务。

二、数据集准备

数据集是机器学习模型训练的基础,特别是对于目标检测任务来说,一个高质量、标注准确的数据集对模型性能的提升至关重要。在开始训练之前,首先需要收集并标注一个适用于目标检测任务的数据集。标注工具可以选择开源的LabelImg、LabelMe等,这个数据集对于模型的训练和性能评估至关重要。我们可以使用一些标注工具手动绘制边界框并指定类别标签,确保每个目标类别都有准确的边界框标注,完成数据的标注工作。

数据集收集与标注

数据集的收集是目标检测任务的第一步。根据任务需求,我们需要从各种来源收集相关的图片,这些图片应该包含目标检测任务中所关心的目标对象。在收集图片时,应确保图片的多样性,包括不同场景、不同角度、不同光照条件下的图片,以提高模型的泛化能力。

数据集的质量直接影响到模型训练的效果,因此在标注过程中需要尽量准确地标注出每个目标的位置和类别。我们是通过在网上收集了100张人像图片。把自己下载的jpg图片文件放在VOCdevkit文件夹下的VOC2007文件夹下的JPEGImages文件夹中(如图所示:)

收集到图片后,接下来需要对这些图片进行标注。标注的目的是为每个目标对象提供精确的位置信息和类别标签。在这个过程中,我们选择了开源的标注工具LabelImg来进行标注工作。LabelImg是一个图形界面的标注工具,可以方便地绘制边界框并指定类别标签。

使用LabelImg进行标注时,我们首先打开一张图片,然后手动绘制出每个目标对象的边界框。在绘制过程中,可以调整边界框的大小和位置,以确保其准确地包围住目标对象。绘制完边界框后,需要为每个边界框指定一个类别标签。类别标签应该根据任务需求进行定义,我们定义了“eye”、“nose”、“ear”等类别。(如图所示:)

完成一张图片的标注后,LabelImg会将标注信息保存为一个XML文件。这个XML文件包含了图片的路径、尺寸信息以及每个目标对象的边界框坐标和类别标签。通过重复这个过程,我们可以为整个数据集的所有图片完成标注工作。把训练自己的数据集时xml标签文件放入VOCdevkit文件夹下的VOC2007文件夹下的Annotations文件夹中。(如图所示:)

数据集格式转换

完成数据集的标注后,下一步是将标注信息转换为YOLOv4算法所需的格式。YOLOv4算法通常使用Darknet框架进行训练和测试,而Darknet框架对数据集格式有特定的要求。

具体来说,Darknet框架需要的数据集格式包括一个文本文件列表,其中每一行对应一张图片的路径;以及一个包含所有标注信息的文本文件,其中每一行对应一个目标对象的类别标签、边界框坐标等信息。

为了将数据集转换为这种格式,我们需要编写一个转换脚本。这个脚本会遍历所有标注好的XML文件,提取出每张图片的路径、尺寸信息以及每个目标对象的边界框坐标和类别标签,然后将这些信息按照Darknet框架要求的格式写入到相应的文本文件中。

在转换过程中,还需要注意一些细节问题。例如,Darknet框架对边界框坐标的格式有特定的要求,通常需要使用相对于图片宽高的比例来表示边界框的左上角和右下角坐标。此外,类别标签也需要进行编码,通常使用一个整数来表示每个类别。

完成数据集的格式转换后,我们就可以将转换后的数据集用于YOLOv4算法的训练和测试了。通过正确地准备数据集,我们可以为后续的模型训练奠定坚实的基础。

三、环境搭建与代码准备

环境搭建

在开始使用YOLOv4进行模型训练之前,我们首先需要在计算机上安装必要的软件和依赖库。这涉及到深度学习框架、GPU加速库以及一些辅助工具的安装和配置。

首先,我们需要安装一个python、深度学习框架。在这个实验中,我们将使用Darknet框架,因为它是YOLO系列算法的原生框架,能够很好地支持YOLOv4的训练和推理。Darknet是一个轻量级的深度学习框架,专注于实时目标检测任务。

除了Darknet框架外,我们还需要安装CUDA和cuDNN这两个GPU加速库。CUDA是NVIDIA推出的并行计算平台和API,它允许开发者使用NVIDIA的GPU进行高性能计算。cuDNN则是NVIDIA专为深度神经网络设计的一套GPU加速库,能够显著提高深度学习算法的计算效率。

在安装这些软件和库时,我们需要确保计算机的硬件支持GPU加速。通常,这意味着计算机需要配备NVIDIA的GPU,并且安装了相应的驱动程序。

安装过程可能因操作系统和具体需求的不同而有所差异,但一般可以通过访问相关官方网站或查阅文档来获取详细的安装指南。

代码准备

安装好必要的软件和库后,我们需要准备YOLOv4的代码。这可以通过下载官方代码或开源实现来完成。在这个实验中,我们选择的是课上老师所提供的代码进行实现的,它包含了完整的训练、验证和推理代码,以及预训练的权重文件。

下载代码后,我们需要根据自己的需求进行适当的修改。这主要涉及到配置文件的修改,包括指定数据集路径、设置训练参数等。配置文件通常是一个文本文件,其中包含了训练过程中所需的各种参数和设置。

例如,在配置文件中,我们需要指定数据集的路径,以便训练时能够正确加载图片和标注信息。同时,我们还需要设置学习率、批次大小、训练轮数等超参数,以控制训练过程的进行。

此外,我们还可以根据需要修改模型文件。这包括加载预训练的权重文件作为初始化,或者调整模型的结构以适应特定的任务需求。

完成代码准备后,我们就可以开始使用YOLOv4进行模型训练了。通过正确的环境搭建和代码准备,我们可以为后续的训练和推理工作奠定坚实的基础。部分代码展示:

import os
import random
import xml.etree.ElementTree as ET

import numpy as np

from utils.utils import get_classes

#--------------------------------------------------------------------------------------------------------------------------------#
#   annotation_mode用于指定该文件运行时计算的内容
#   annotation_mode为0代表整个标签处理过程,包括获得VOCdevkit/VOC2007/ImageSets里面的txt以及训练用的2007_train.txt、2007_val.txt
#   annotation_mode为1代表获得VOCdevkit/VOC2007/ImageSets里面的txt
#   annotation_mode为2代表获得训练用的2007_train.txt、2007_val.txt
#--------------------------------------------------------------------------------------------------------------------------------#
annotation_mode     = 2
#-------------------------------------------------------------------#
#   必须要修改,用于生成2007_train.txt、2007_val.txt的目标信息
#   与训练和预测所用的classes_path一致即可
#   如果生成的2007_train.txt里面没有目标信息
#   那么就是因为classes没有设定正确
#   仅在annotation_mode为0和2的时候有效
#-------------------------------------------------------------------#
classes_path        = 'model_data/voc_classes.txt'
#--------------------------------------------------------------------------------------------------------------------------------#
#   trainval_percent用于指定(训练集+验证集)与测试集的比例,默认情况下 (训练集+验证集):测试集 = 9:1
#   train_percent用于指定(训练集+验证集)中训练集与验证集的比例,默认情况下 训练集:验证集 = 9:1
#   仅在annotation_mode为0和1的时候有效
#--------------------------------------------------------------------------------------------------------------------------------#
trainval_percent    = 0.9
train_percent       = 0.9
#-------------------------------------------------------#
#   指向VOC数据集所在的文件夹
#   默认指向根目录下的VOC数据集
#-------------------------------------------------------#
VOCdevkit_path  = 'VOCdevkit'

VOCdevkit_sets  = [('2007', 'train'), ('2007', 'val')]
classes, _      = get_classes(classes_path)

#-------------------------------------------------------#
#   统计目标数量
#-------------------------------------------------------#
photo_nums  = np.zeros(len(VOCdevkit_sets))
nums        = np.zeros(len(classes))
def convert_annotation(year, image_id, list_file):
    in_file = open(os.path.join(VOCdevkit_path, '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))
        
        nums[classes.index(cls)] = nums[classes.index(cls)] + 1
        
if __name__ == "__main__":
    random.seed(0)
    if " " in os.path.abspath(VOCdevkit_path):
        raise ValueError("数据集存放的文件夹路径与图片名称中不可以存在空格,否则会影响正常的模型训练,请注意修改。")

    if annotation_mode == 0 or annotation_mode == 1:
        print("Generate txt in ImageSets.")
        xmlfilepath     = os.path.join(VOCdevkit_path, 'VOC2007/Annotations')
        saveBasePath    = os.path.join(VOCdevkit_path, 'VOC2007/ImageSets/Main')
        temp_xml        = os.listdir(xmlfilepath)
        total_xml       = []
        for xml in temp_xml:
            if xml.endswith(".xml"):
                total_xml.append(xml)

        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)  
        
        print("train and val size",tv)
        print("train size",tr)
        ftrainval   = open(os.path.join(saveBasePath,'trainval.txt'), 'w')  
        ftest       = open(os.path.join(saveBasePath,'test.txt'), 'w')  
        ftrain      = open(os.path.join(saveBasePath,'train.txt'), 'w')  
        fval        = open(os.path.join(saveBasePath,'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("Generate txt in ImageSets done.")

    if annotation_mode == 0 or annotation_mode == 2:
        print("Generate 2007_train.txt and 2007_val.txt for train.")
        type_index = 0
        for year, image_set in VOCdevkit_sets:
            image_ids = open(os.path.join(VOCdevkit_path, '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('%s/VOC%s/JPEGImages/%s.jpg'%(os.path.abspath(VOCdevkit_path), year, image_id))

                convert_annotation(year, image_id, list_file)
                list_file.write('\n')
            photo_nums[type_index] = len(image_ids)
            type_index += 1
            list_file.close()
        print("Generate 2007_train.txt and 2007_val.txt for train done.")
        
        def printTable(List1, List2):
            for i in range(len(List1[0])):
                print("|", end=' ')
                for j in range(len(List1)):
                    print(List1[j][i].rjust(int(List2[j])), end=' ')
                    print("|", end=' ')
                print()

        str_nums = [str(int(x)) for x in nums]
        tableData = [
            classes, str_nums
        ]
        colWidths = [0]*len(tableData)
        len1 = 0
        for i in range(len(tableData)):
            for j in range(len(tableData[i])):
                if len(tableData[i][j]) > colWidths[i]:
                    colWidths[i] = len(tableData[i][j])
        printTable(tableData, colWidths)

        if photo_nums[0] <= 500:
            print("训练集数量小于500,属于较小的数据量,请注意设置较大的训练世代(Epoch)以满足足够的梯度下降次数(Step)。")

        if np.sum(nums) == 0:
            print("在数据集中并未获得任何目标,请注意修改classes_path对应自己的数据集,并且保证标签名字正确,否则训练将会没有任何效果!")
            print("在数据集中并未获得任何目标,请注意修改classes_path对应自己的数据集,并且保证标签名字正确,否则训练将会没有任何效果!")
            print("在数据集中并未获得任何目标,请注意修改classes_path对应自己的数据集,并且保证标签名字正确,否则训练将会没有任何效果!")
            print("(重要的事情说三遍)。")

四、模型训练

配置训练参数

在开始训练之前,我们需要设置一系列训练参数,这些参数将直接影响模型的训练效果和收敛速度。通常情况下,这些参数会在一个配置文件中指定,如

主要的训练参数包括:

  • 学习率(Learning Rate):决定了模型参数在训练过程中的更新步长。过高的学习率可能导致训练不稳定,而过低的学习率则可能导致训练速度过慢。
  • 批次大小(Batch Size):每次迭代中用于计算梯度并更新模型权重的样本数量。增大批次大小可以加速训练,但也可能增加内存消耗。
  • 训练轮数(Epochs):整个数据集将被用于训练的完整次数。足够的训练轮数可以确保模型充分学习数据特征,但过多的轮数可能导致过拟合。
  • 优化器(Optimizer):用于更新模型权重的算法,如SGD、Adam等。
  • 权重衰减(Weight Decay):用于防止模型过拟合的正则化项。

在配置好这些参数后,我们就可以开始训练过程了。

开始训练

运行训练脚本,开始模型的训练过程。在训练过程中,可以观察损失函数的变化以及验证集上的性能表现,以便及时调整训练策略。

保存训练好的模型

训练完成后,保存训练好的模型权重文件,以便后续进行推理和测试。

dn.save_weights(net, 'yolov4_trained.weights')

在保存权重文件后,我们就可以使用这个模型进行目标检测任务了。后续步骤通常包括加载模型权重、处理输入图像、进行前向传播以获取检测结果,并对结果进行可视化或进一步分析。

五、模型测试与结果展示

加载训练好的模型

模型测试阶段,首先需要加载之前训练好的模型权重文件。这通常涉及到使用相应的深度学习框架提供的函数或方法,来读取权重文件并初始化模型。加载模型后,我们还需要准备用于测试的图片数据集。部分代码如下:

对测试图片进行推理

加载模型后,我们可以使用它对测试图片进行推理。推理过程通常包括预处理图像(如调整大小、归一化等)、前向传播获取检测结果,以及后处理(如非极大值抑制NMS)来消除冗余的边界框。

结果展示与评估

推理完成后,我们可以将检测结果绘制在原始图片上,生成带有边界框和类别标签的可视化结果。这可以通过使用OpenCV等库来完成,将边界框绘制在图片上,并在每个边界框旁边添加类别标签和置信度分数。



	def evaluate_model(detections, annotations):  


	    mAP = calculate_mAP(detections, annotations)  

	    accuracy = calculate_accuracy(detections, annotations)  

	    return mAP, accuracy  
  

	mAP, accuracy = evaluate_model(detections_list, annotations_list)  

	print(f'mAP: {mAP:.2f}, Accuracy: {accuracy:.2f}')

六、总结与展望

总结

本文大概讲述了基于YOLOv4算法的目标检测任务,从数据集的准备、环境的搭建、模型的训练、测试到结果的展示与评估,为读者提供了一个简要的流程。通过实践,我们深入了解了目标检测任务中的关键步骤和技术要点。

在数据集的准备阶段,我们学习了如何收集、标注和处理图像数据,以构建符合任务需求的数据集。在环境搭建阶段,我们介绍了如何安装必要的依赖库和工具,并配置了适合YOLOv4训练的运行环境。在模型训练阶段,我们详细探讨了训练参数的配置、训练过程的监控以及模型权重的保存。而在模型测试和结果展示阶段,我们学习了如何加载训练好的模型,对测试图片进行推理,并将结果可视化呈现出来。

通过这一系列步骤,我们成功地训练出了一个能够在自定义数据集上进行目标检测的模型,并通过评估指标验证了模型的性能。这为我们后续的目标检测任务提供了宝贵的经验和参考。我们可以对检测结果进行分析和优化。通过观察检测结果,可以发现模型可能存在的一些问题如漏检、误检等,然后可以针对性地调整模型的参数或者进行进一步的数据增强来提升模型的性能和鲁棒性。同时,我也不是特别懂这些算法,还希望你们能给我提意见,我会好好看、好好学的。

展望

虽然本文已经展示了基于YOLOv4的目标检测任务的基本流程,但仍有许多可以改进和优化的地方。例如,可以尝试使用更先进的数据增强技术来提高模型的泛化能力;也可以探索不同的模型优化策略来提升检测性能。此外,随着新的目标检测算法和技术的不断涌现,未来还可以考虑将这些新方法与YOLOv4进行结合,以进一步提升目标检测的准确性和效率。

首先,我们可以尝试使用更先进的数据增强技术。数据增强是一种通过对原始图像进行变换来生成更多训练样本的方法,可以有效地提高模型的泛化能力。未来,我们可以探索更多种类的数据增强方法,如旋转、缩放、裁剪、颜色变换等,以进一步扩充数据集并提升模型的性能。

其次,我们可以探索不同的模型优化策略。在模型训练过程中,优化器的选择和学习率的调整对模型的收敛速度和性能有着重要影响。未来,我们可以尝试使用不同的优化器以及学习率调度策略,便于找到更适合我们任务的训练策略。

此外,随着深度学习技术的不断发展,新的目标检测算法和框架不断涌现。未来,我们可以考虑将这些新方法与YOLOv4进行结合,以进一步提升目标检测的准确性和效率。

最后,我们还可以考虑将目标检测任务与其他计算机视觉任务进行结合,以实现更复杂的场景理解和应用。例如,我们可以将目标检测与实例分割、语义分割或行为识别等任务进行融合,以构建更全面的视觉感知系统。

总的来说,基于课上的YOLOv4代码,结合自己标注的数据集进行训练,得到训练好的模型,并使用测试图片对结果进行检测展示是一个非常有趣和实用的实践项目。通过这样的实践,可以更深入地理解目标检测算法的原理和实现细节,并且可以应用于实际的项目中,如智能监控、无人驾驶等领域。

  • 26
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
基于YOLOv8的行人目标检测训练细节如下: 1. 数据集准备:首先,需要收集包含行人目标的图像数据集。可以使用公开的行人数据集,如COCO、CityPersons等,也可以自己标注图像数据集。确保数据集中包含足够多的行人目标样本,并且标注准确。 2. 数据预处理:对数据集进行预处理是必要的。常见的预处理操作包括图像缩放、裁剪、旋转、亮度调整等。此外,还可以进行数据增强操作,如随机翻转、随机扩展、随机旋转等,以增加数据集的多样性。 3. 构建模型:使用YOLOv8作为基础模型进行行人目标检测YOLOv8是一种基于卷积神经网络的目标检测算法,具有较高的检测速度和准确率。可以使用开源的YOLOv8代码库进行模型构建。 4. 模型训练:将准备好的数据集输入到模型中进行训练训练过程中,需要定义损失函数,常用的损失函数包括交叉熵损失和均方误差损失。通过反向传播算法更新模型参数,使得模型能够逐渐学习到行人目标的特征。 5. 参数调优:在训练过程中,可以通过调整学习率、优化器、批次大小等参数来提高模型的性能。可以使用验证集进行模型的评估和调优,选择最佳的模型参数。 6. 模型评估:训练完成后,使用测试集对模型进行评估。常用的评估指标包括准确率、召回率、精确率和F1值等。根据评估结果,可以对模型进行进一步的改进和优化。 7. 模型部署:训练完成后,可以将模型部署到实际应用中进行行人目标检测。可以使用模型推理库,如TensorRT、OpenVINO等,将模型转换为可部署的格式,并进行性能优化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值