Open images v6 + Yolov5 轻松获取数据并做2D目标检测

记录一下从数据获取到做出符合需求的2d检测模型的全过程,记录一共分为四个章节.其中

fiftyone

简介

fiftyone是一款用于 构建高质量数据集和计算机视觉模型的开源工具.这款工具不仅仅可以用来 加载数据,还能用来评估模型性能,查找注释错误等等
想要了解更多关于fiftyone可以点击这里

安装

创建一个虚拟环境并安装 fiftyone

mkdir Fiftyone_Yolov5
cd Fiftyone_Yolov5
conda create -n Fiftyone_Yolov5 python=3.8
conda activate  Fiftyone_Yolov5
conda install jupyter notebook
pip install fiftyone

选择需要下载的数据集

首先导入 fiftyone 中的数据zoo。

import fiftyone as fo
import fiftyone.zoo as foz
help(foz)

需要根据你需要的实际需求设置数据的下载参数。

dataset = foz.load_zoo_dataset(
        "open-images-v6",
        split="train",
        classes=["Table","Human hand","Human head","Person"],
        max_samples=100000,
        shuffle=True,
        only_matching=True,
        label_types=["detections"],
        dataset_dir="./OpenImageV6_20220921",
        num_workers=4,
)

foz.load_zoo_dataset 参数简介

  1. 填写你需要数据集的名称(字符串类型)
  2. split 指定要加载的分段。支持的值是’ (“train”, “test”, “validation”) ‘(字符串类型)
  3. classes 选择你需要的检测的对象的类别。(字符串或list类型)
    NOTE: 类别字符串一定要与数据集的类别名称一致,如果不确定可以自行百度或者google一下数据集的类别。注意大小写。
  4. max_samples 要加载的样本的最大数量。(int类型)
  5. only_matching 是否只加载与您提供的’ classes ‘或’ attrs ‘需求匹配的标签(True),还是加载与需求匹配的样本的所有标签(False)
  6. num_workers 使用的进程数,默认使用multiprocessing.cpu_count()返回的cpu数量
  7. shuffle 是否打乱下载数据的顺序
  8. include_id 是否加载标签中包含某个样本的标签
  9. image_ids 指定需要加载的图像的id
  10. seed 随机种子
  11. attrs 指定需要加载的关系属性的字符串或字符串列表。此参数仅适用于”label_type”包含”relationships”的情况。

foz.load_zoo_dataset 参数官方文档

API参数可以参考这个文档进行自定义。

文档右边可以选择你需要的数据集进行下载。往下拉可以看到所有可以选择的参数。

Open images v6 + Yolov5 轻松获取数据并做2D目标检测
Open images v6 + Yolov5 轻松获取数据并做2D目标检测
Open images v6 + Yolov5 轻松获取数据并做2D目标检测

; 图片注释格式转换

经过第一章节,我们已经拿到了我们需要的数据集,但是由于注释格式的不同我们无法直接输入yolov5进行使用,这一章节我们通过open images v6 的数据进行演示,如何将OIDv6的数据格式转换成yolo txt的数据格式。
转换分为两步: oidv6格式到voc ; voc 到 yolo txt 。

OIDv6 >> voc

这一步骤使用了这个python工具包–(oidv6-to-voc)
安装 oidv6-to-voc

pip install oidv6-to-voc

使用 oidv6-to-voc 工具进行转换

oidv6-to-voc <annotation-file(s).csv>
             -d <class-names-file.csv>
             --imgd <directory/to/your/images>
             --outd <your/output/diretory>

其中annotation-file(s).csv 可以在数据保存路径下的labels/文件夹中找到 detections.csv

Open images v6 + Yolov5 轻松获取数据并做2D目标检测
class-names-file.csv 可以在下一小节中下载

下载需要的标注文件

点击进入这个网页https://storage.googleapis.com/openimages/web/download.html

Open images v6 + Yolov5 轻松获取数据并做2D目标检测
其中 红色框内的表示annotation-file(s).csv文件,open images 将其数据分割成了 train validation test
绿色框内的表示 class-names-file.csv 下载完直接使用即可

NOTE:
其中第1列代表的是open images 的类别id(这个不是给一般人看的),第2列代表的是类别id所对应的英文名字(你可以在其中找一下有没有你需要的类别)

Open images v6 + Yolov5 轻松获取数据并做2D目标检测

; VOC >> YOLO TXT

使用python实现格式转换

以下代码主要参考了这篇博客
首先导入我们所需要的数据包

import xml.etree.ElementTree as ET
import glob
import os
import json

导入两个函数

def xml_to_yolo_bbox(bbox, w, h):

    x_center = ((bbox[2] + bbox[0]) / 2) / w
    y_center = ((bbox[3] + bbox[1]) / 2) / h
    width = (bbox[2] - bbox[0]) / w
    height = (bbox[3] - bbox[1]) / h
    return [x_center, y_center, width, height]
def yolo_to_xml_bbox(bbox, w, h):

    w_half_len = (bbox[2] * w) / 2
    h_half_len = (bbox[3] * h) / 2
    xmin = int((bbox[0] * w) - w_half_len)
    ymin = int((bbox[1] * h) - h_half_len)
    xmax = int((bbox[0] * w) + w_half_len)
    ymax = int((bbox[1] * h) + h_half_len)
    return [xmin, ymin, xmax, ymax]

依次填入类别名称、VOC格式的注释文件所在目录,你想要输出YOLO TXT格式的注释文件所在目录、图片目录

classes = []
input_dir = "annotations/"
output_dir = "labels/"
image_dir = "images/"

if not os.path.isdir(output_dir):
    os.mkdir(output_dir)

这是注释格式转换的主要代码

files = glob.glob(os.path.join(input_dir, '*.xml'))
for fil in files:
    basename = os.path.basename(fil)
    filename = os.path.splitext(basename)[0]
    if not os.path.exists(os.path.join(image_dir, f"{filename}.jpg")):
        print(f"{filename} image does not exist!")
        continue
    files = glob.glob(os.path.join(input_dir, '*.xml'))
    result = []
    tree = ET.parse(fil)
    root = tree.getroot()
    width = int(root.find("size").find("width").text)
    height = int(root.find("size").find("height").text)
    for obj in root.findall('object'):
        label = obj.find("name").text
        if label not in classes:
            classes.append(label)
        index = classes.index(label)
        pil_bbox = [int(x.text) for x in obj.find("bndbox")]
        yolo_bbox = xml_to_yolo_bbox(pil_bbox, width, height)
        bbox_string = " ".join([str(x) for x in yolo_bbox])
        result.append(f"{index}{bbox_string}")
    if result:
        with open(os.path.join(output_dir, f"{filename}.txt"), "w", encoding="utf-8") as f:
            f.write("\n".join(result))

记录一下类别

with open('classes.txt', 'w', encoding='utf8') as f:
    f.write(json.dumps(classes))

Yolov5的训练

yolov5 训练前的准备工作

下载yolov5项目代码并安装需要的运行环境(最好在虚拟环境下运行)

git clone https://github.com/ultralytics/yolov5
cd yolov5
pip install -r requirements.txt

移动数据集到指定位置

在yolov5的目录下创建一个datasets文件夹用以装载训练和测试数据

Open images v6 + Yolov5 轻松获取数据并做2D目标检测
其中 images 装载图片训练和验证的数据分别装在train和val文件夹下
labels同理装载注释数据的txt文件
; 修改model的配置文件(yaml)

在data目录下创建一个关于自己数据的yaml文件 比如customerData.yaml

train: ./datasets/images/train
val: ./datasets/images/val

nc: 3

names: ["car","person","human face"]

修改data的配置文件(yaml)

进入models文件夹 选择你想要的yolov5模型,我们以yolov5l.yaml 为例,将文件中的nc: 80 改为你的类别数目。比如 如果你需要检测car、person、cycline三类 就写一个3。


nc: 80
depth_multiple: 1.0
width_multiple: 1.0
anchors:
  - [10,13, 16,30, 33,23]
  - [30,61, 62,45, 59,119]
  - [116,90, 156,198, 373,326]

backbone:

  [[-1, 1, Conv, [64, 6, 2, 2]],
   [-1, 1, Conv, [128, 3, 2]],
   [-1, 3, C3, [128]],
   [-1, 1, Conv, [256, 3, 2]],
   [-1, 6, C3, [256]],
   [-1, 1, Conv, [512, 3, 2]],
   [-1, 9, C3, [512]],
   [-1, 1, Conv, [1024, 3, 2]],
   [-1, 3, C3, [1024]],
   [-1, 1, SPPF, [1024, 5]],
  ]

head:
  [[-1, 1, Conv, [512, 1, 1]],
   [-1, 1, nn.Upsample, [None, 2, 'nearest']],
   [[-1, 6], 1, Concat, [1]],
   [-1, 3, C3, [512, False]],

   [-1, 1, Conv, [256, 1, 1]],
   [-1, 1, nn.Upsample, [None, 2, 'nearest']],
   [[-1, 4], 1, Concat, [1]],
   [-1, 3, C3, [256, False]],

   [-1, 1, Conv, [256, 3, 2]],
   [[-1, 14], 1, Concat, [1]],
   [-1, 3, C3, [512, False]],

   [-1, 1, Conv, [512, 3, 2]],
   [[-1, 10], 1, Concat, [1]],
   [-1, 3, C3, [1024, False]],

   [[17, 20, 23], 1, Detect, [nc, anchors]],
  ]

yolov5 的训练参数

改好之后就可以开始训练了

python3 train.py --img-size 640 \
--batch-size 16 \
--epochs 300 \
--data ./data/customerData.yaml \
--cfg ./models/yolov5l.yaml \
--weights weights/yolov5l.pt \
--device 0,1

其他可选参数简介:

  1. –evolve {num} 使用yolo自带的进化算法调整模型超参数(num为训练的代数3)
  2. –multi-scale 随机调整 imgsz的大小 调整范围为 “±50%”
  3. –workers {num} 多进程设置(num 为需要设定的进程数)
  4. –cache 将数据提前加载到内存
  5. –hyp xxx.yaml 手动调整模型和数据增强的超参数
  6. –optimizer 模型优化器选择,默认 SGD,可从这三个里面进行选择[‘SGD’, ‘Adam’, ‘AdamW’]
  7. –image-weights 测试过程中,图像的那些测试地方不太好,对这些不太好的地方加权重

可参考一下链接,如果有参数名称找不到,需要自行查看一下train.py文件中的keyword ,名字可能有所改动。(列如:–cache-images 更改为了 –cache)

NOTE: 当使用 –multi-scale 参数时 需要预留足够的GPU显存,不然会导致GPU内存溢出。

yolov5 训练经验记录

数据增强超参数调整:


lr0: 0.01
lrf: 0.1
momentum: 0.937
weight_decay: 0.0005
warmup_epochs: 3.0
warmup_momentum: 0.8
warmup_bias_lr: 0.1
box: 0.05
cls: 0.3
cls_pw: 1.0
obj: 0.7
obj_pw: 1.0
iou_t: 0.20
anchor_t: 4.0

fl_gamma: 0.0
hsv_h: 0.015
hsv_s: 0.7
hsv_v: 0.4
degrees: 90.0
translate: 0.1
scale: 0.9
shear: 0.5
perspective: 0.0
flipud: 0.2
fliplr: 0.5
mosaic: 1.0
mixup: 0.3
copy_paste: 0.1

数据集中出现图片注释不完善

这个问题应该是open image 这个数据集特有的,暂时没在其他数据集上发现。
问题如下,比如我需要检测 人脸 人眉毛和人这三类。但是有些图片中明明有人脸和人的眉毛,数据集却并没有该类的标记,而是仅仅只标记了人出来,这就会导致模型在训练的时候,明明图片中有一个人的眉毛并且模型可以将其识别出来,但是由于没有这个注释导致进行loss计算的正确答案是背景类(而不是眉毛类)。因此噪音多了就会让模型无法学习到真正的眉毛。

其他

yolov5 的模型检测命令

python detect.py --source
                 --weights
                 --imgsz 1280
                 --conf-thres 0.05
                 --iou-thres 0.05
                 --data ./data/customerData.yaml
                 --save-txt

Original: https://blog.csdn.net/weixin_39986534/article/details/126990840
Author: 一口气吃五碗饭的阿霖
Title: Open images v6 + Yolov5 轻松获取数据并做2D目标检测

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/681661/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球