Article / 文章中心

超详细!手把手教你使用YOLOX进行物体检测(附数据集)

发布时间:2022-08-25 点击数:709

作者:王浩,3D视觉开发者社区签约作者,毕业于北京航空航天大学,人工智能领域优质创作者,CSDN博客认证专家。

编辑:3D视觉开发者社区

摘要

YOLOX: Exceeding YOLO Series in 2021

•代码:https://github.com/Megvii-BaseDetection/YOLOX•论文:https://arxiv.org/abs/2107.08430

7f654c17ec08012d44a572019fdd2bab.png

YOLOX 是旷视开源的高性能检测器。旷视的研究者将解耦头、数据增强、无锚点以及标签分类等目标检测领域的优秀进展与 YOLO 进行了巧妙的集成组合,提出了 YOLOX,不仅实现了超越 YOLOv3、YOLOv4 和 YOLOv5 的 AP,而且取得了极具竞争力的推理速度。如下图:

9493b5ac21696c0c0be76123542114ea.png 其中YOLOX-L版本以 68.9 FPS 的速度在 COCO 上实现了 50.0% AP,比 YOLOv5-L 高出 1.8% AP!还提供了支持 ONNX、TensorRT、NCNN 和 Openvino 的部署版本,本文将详细介绍如何使用 YOLOX进行物体检测。

一、 配置环境

本机的环境:

操作系统 Win10
Pytorch版本 1.8.0
Cuda版本 11.1
   

1.1 下载源码

GitHub地址:https://github.com/Megvii-BaseDetection/YOLOX,下载完成后放到D盘根目录,然后用PyCharm打开。

1.2 安装依赖包

点击“Terminal”,如下图,

995c46683c054394a6e5dc11147680fa.png

然后执行下面的命令,安装所有的依赖包。

pip install -r requirements.txt

09d64b565ced4a2f9364e45dbc528f73.png 1.3 安装yolox

python setup.py install

e285d0ec996e18764b6354c3a315cfce.png

看到如下信息,则说明安装完成了

9e0ab7c92ad67d896eef909ac96fd153.png 1.4 安装apex

APEX是英伟达开源的,完美支持PyTorch框架,用于改变数据格式来减小模型显存占用的工具。其中最有价值的是amp(Automatic Mixed Precision),将模型的大部分操作都用Float16数据类型测试,一些特别操作仍然使用Float32。并且用户仅仅通过三行代码即可完美将自己的训练代码迁移到该模型。实验证明,使用Float16作为大部分操作的数据类型,并没有降低参数,在一些实验中,反而由于可以增大Batch size,带来精度上的提升,以及训练速度上的提升。

安装步骤:

1) 到官网下载apex,地址:mirrors / nvidia / apex · CODE CHINA (csdn.net)[1]

2) 下载完成后,解压后,在Shell里,进入到apex-master中。

19ebdc7c89c4f7653d3d6f6829e510d4.png

3) 执行安装命令

pip install -r requirements.txt
   python setup.py install

看到如下log,则表明安装成功。

fa743bc267a8e22516927c65ba2c0727.png 1.5 安装pycocotools

pip install pycocotools

注:如果出现环境问题,可以参考博客:https://blog.csdn.net/hhhhhhhhhhwwwwwwwwww/article/details/105858384

1.6 验证环境

下载预训练模型,本文选用的是YOLOX-s,下载地址:https://github.com/Megvii-BaseDetection/YOLOX/releases/download/0.1.1rc0/yolox_s.pth。

下载完成后,将预训练模型放到工程的根目录,如下图:

0e3baedd679e86d8d10bd96af9838189.png

然后验证环境,执行:

python tools/demo.py image -f exps/default/yolox_s.py -c ./yolox_s.pth --path assets/dog.jpg --conf 0.3 --nms 0.65 --tsize 640 --save_result --device gpu

 

参数说明

参数 说明
-c 权重的路径
-path 测试图片的路径
-conf 置信度阈值
-nms nms的IOU阈值
-tsize 测试图片resize的大小
-save_result 是否保存推理结果
--device 选用gpu或cpu推理


2f4a3024cb7cb6cf250f6b1fca1fb745.png

查看运行结果:

ed3c1e2a1b0e3d31bbd66533b945c49a.png

看到上图说明环境没有问题了。

二、 制作数据集

数据集我们采用VOC数据集,原始数据集是Labelme标注的数据集。下载地址:https://pan.baidu.com/s/1kj-diqEK2VNVqd2n4ROa5g (提取码rrnz)

新建labelme2voc.py文件

 

import os
from typing import List, Any
import numpy as np
import codecs
import json
from glob import glob
import cv2
import shutil
from sklearn.model_selection import train_test_split


# 1.标签路径


labelme_path = "LabelmeData/"  # 原始labelme标注数据路径
saved_path = "VOC2007/"  # 保存路径
isUseTest = True  # 是否创建test集
# 2.创建要求文件夹
if not os.path.exists(saved_path + "Annotations"):
    os.makedirs(saved_path + "Annotations")
if not os.path.exists(saved_path + "JPEGImages/"):
    os.makedirs(saved_path + "JPEGImages/")
if not os.path.exists(saved_path + "ImageSets/Main/"):
    os.makedirs(saved_path + "ImageSets/Main/")
# 3.获取待处理文件
files = glob(labelme_path + "*.json")
files = [i.replace("\\", "/").split("/")[-1].split(".json")[0] for i in files]
print(files)
# 4.读取标注信息并写入 xml
for json_file_ in files:
    json_filename = labelme_path + json_file_ + ".json"
    json_file = json.load(open(json_filename, "r", encoding="utf-8"))
    height, width, channels = cv2.imread(labelme_path + json_file_ + ".jpg").shape
with codecs.open(saved_path + "Annotations/" + json_file_ + ".xml", "w", "utf-8") as xml:
        xml.write('\n')
        xml.write('\t' + 'WH_data' + '\n')
        xml.write('\t' + json_file_ + ".jpg" + '\n')
        xml.write('\t\n')
        xml.write('\t\tWH Data\n')
        xml.write('\t\tWH\n')
        xml.write('\t\tflickr\n')
        xml.write('\t\tNULL\n')
        xml.write('\t\n')
        xml.write('\t\n')
        xml.write('\t\tNULL\n')
        xml.write('\t\tWH\n')
        xml.write('\t\n')
        xml.write('\t\n')
        xml.write('\t\t' + str(width) + '\n')
        xml.write('\t\t' + str(height) + '\n')
        xml.write('\t\t' + str(channels) + '\n')
        xml.write('\t\n')
        xml.write('\t\t0\n')
for multi in json_file["shapes"]:
            points = np.array(multi["points"])
            labelName = multi["label"]
            xmin = min(points[:, 0])
            xmax = max(points[:, 0])
            ymin = min(points[:, 1])
            ymax = max(points[:, 1])
            label = multi["label"]
if xmax <= xmin:
pass
elif ymax <= ymin:
pass
else:
                xml.write('\t\n')
                xml.write('\t\t' + labelName + '\n')
                xml.write('\t\tUnspecified\n')
                xml.write('\t\t1\n')
                xml.write('\t\t0\n')
                xml.write('\t\t\n')
                xml.write('\t\t\t' + str(int(xmin)) + '\n')
                xml.write('\t\t\t' + str(int(ymin)) + '\n')
                xml.write('\t\t\t' + str(int(xmax)) + '\n')
                xml.write('\t\t\t' + str(int(ymax)) + '\n')
                xml.write('\t\t\n')
                xml.write('\t\n') print(json_filename, xmin, ymin, xmax, ymax, label) xml.write('') # 5.复制图片到 VOC2007/JPEGImages/下 image_files = glob(labelme_path + "*.jpg") print("copy image files to VOC007/JPEGImages/") for image in image_files: shutil.copy(image, saved_path + "JPEGImages/") # 6.split files for txt txtsavepath = saved_path + "ImageSets/Main/" ftrainval = open(txtsavepath + '/trainval.txt', 'w') ftest = open(txtsavepath + '/test.txt', 'w') ftrain = open(txtsavepath + '/train.txt', 'w') fval = open(txtsavepath + '/val.txt', 'w') total_files = glob("./VOC2007/Annotations/*.xml") total_files = [i.replace("\\", "/").split("/")[-1].split(".xml")[0] for i in total_files] trainval_files = [] test_files = [] if isUseTest: trainval_files, test_files = train_test_split(total_files, test_size=0.15, random_state=55) else: trainval_files = total_files for file in trainval_files: ftrainval.write(file + "\n") # split train_files, val_files = train_test_split(trainval_files, test_size=0.15, random_state=55) # train for file in train_files: ftrain.write(file + "\n") # val for file in val_files: fval.write(file + "\n") for file in test_files: print(file) ftest.write(file + "\n") ftrainval.close() ftrain.close() fval.close() ftest.close()



运行上面的代码就可以得到VOC2007数据集。如下图所示:


VOC的目录如下,所以要新建data/VOCdevkit目录,然后将上面的结果复制进去