YOLOv1 数据集加载

相关文章

项目地址:YOLOv1 VOC 2007

笔者训练的权重地址:阿里云盘分享

10 秒文章速览

本文针对讲解 PASCAL VOC 2007 数据集的结构、信息进行了粗略说明,并演示了数据集加载

PASCAL VOC 项目传送门:The PASCAL Visual Object Classes Homepage

这里,笔者也给出自己整理的 PASCAL VOC 2007 数据集的下载地址:Kaggle-PASCAL VOC 2007

本文讲的数据集针对 PASCAL VOC 2007

数据集介绍

数据集是从现实场景中采集的图片,一共包含20个类别

  • 人:人🧔
  • 动物:鸟🦜、猫🐈、牛🐄、狗🐕、马🐎、羊🐏
  • 车辆:飞机✈️、自行车🚲、船🚢、公共汽车🚌、汽车🚗、摩托车🏍️、火车🚂
  • 室内:瓶子🍾、椅子🪑、餐桌、盆栽🪴、沙发🛋️、电视/显示器📺

数据集可以用于主要可以用于检测、分割这2项任务

目标检测
1.png
2.png

目标分割
3.png

数据集文件结构

PASCAL VOC 2007 的训练、验证集文件结构如下

  • VOC 2007
    • Annotations:放置每张图片的标注,储存为XML格式
    • ImageSets
      • Layout:train.txt 训练集、val.txt 验证集、trainval.txt 训练验证汇总集
      • Main:对各个类别的训练集、验证集分开放置
      • Segmentation:放置用于分割任务的数据集
    • JPEGImages:放置所有图片
    • SegmentationClass:按类别进行图像分割,同一类别的物体会被标注为相同颜色
    • SegmentationObject:按对象进行图像分割,即使是同一类别也会被标注为不同颜色

XML 文件

xml文件的内容如下,标注了一张图片中目标的边框、类别等信息

<annotation>
    <folder>VOC2007</folder>
    <filename>000005.jpg</filename>
    <source>
        <database>The VOC2007 Database</database>
        <annotation>PASCAL VOC2007</annotation>
        <image>flickr</image>
        <flickrid>325991873</flickrid>
    </source>
    <owner>
        <flickrid>archintent louisville</flickrid>
        <name>?</name>
    </owner>
    <size>
        <width>500</width>
        <height>375</height>
        <depth>3</depth>
    </size>
    <segmented>0</segmented>
    <object>
        <name>chair</name>
        <pose>Rear</pose>
        <truncated>0</truncated>
        <difficult>0</difficult>
        <bndbox>
            <xmin>263</xmin>
            <ymin>211</ymin>
            <xmax>324</xmax>
            <ymax>339</ymax>
        </bndbox>
    </object>
</annotation>

<filename> 标注了图片名称,在 <size> 中标注了图片的宽(<width>)、高(<height>)、通道数(<depth>)。在 <object> 中标注了目标的名称(<name>)、边框(<bndbox>)等信息

读取 XML

在了解了数据集、XML文件之后,就可以正式进入代码💻阶段咯~

下面的代码中,定义了 PASCAL VOC 2007 数据集的类别与 load_dataload_data 函数能够返回图片的路径与生成图片相对应的标签

import os
import tensorflow as tf
from xml.etree import ElementTree as ET

# 文件路径
path_JPEGImages = 'VOCdevkit/VOC2007/JPEGImages'
path_Annotations = 'VOCdevkit/VOC2007/Annotations'
path_ImageSets_Layout_trainval = 'VOCdevkit/VOC2007/ImageSets/Layout/trainval.txt'

# 类别
classes = {'aeroplane': {'code': 0, 'name': 'aeroplane', 'color': (255, 0, 0)},
           'bicycle': {'code': 1, 'name': 'bicycle', 'color': (0, 255, 0)},
           'bird': {'code': 2, 'name': 'bird', 'color': (0, 0, 255)},
           'boat': {'code': 3, 'name': 'boat', 'color': (255, 0, 255)},
           'bottle': {'code': 4, 'name': 'bottle', 'color': (0, 255, 255)},
           'bus': {'code': 5, 'name': 'bus', 'color': (255, 165, 0)},
           'car': {'code': 6, 'name': 'car', 'color': (0, 255, 165)},
           'cat': {'code': 7, 'name': 'cat', 'color': (255, 0, 165)},
           'chair': {'code': 8, 'name': 'chair', 'color': (0, 255, 0)},
           'cow': {'code': 9, 'name': 'cow', 'color': (255, 210, 0)},
           'diningtable': {'code': 10, 'name': 'diningtable', 'color': (0, 0, 210)},
           'dog': {'code': 11, 'name': 'dog', 'color': (255, 0, 80)},
           'horse': {'code': 12, 'name': 'horse', 'color': (0, 80, 255)},
           'motorbike': {'code': 13, 'name': 'motorbike', 'color': (255, 80, 0)},
           'person': {'code': 14, 'name': 'person', 'color': (0, 255, 80)},
           'pottedplant': {'code': 15, 'name': 'pottedplant', 'color': (255, 165, 80)},
           'sheep': {'code': 16, 'name': 'sheep', 'color': (80, 0, 255)},
           'sofa': {'code': 17, 'name': 'sofa', 'color': (80, 255, 80)},
           'train': {'code': 18, 'name': 'train', 'color': (0, 165, 255)},
           'tvmonitor': {'code': 19, 'name': 'tvmonitor', 'color': (255, 220, 0)}}
classes_name = list(classes.keys())

def load_data(path):
    # 读取训练集验证集汇合文件
    with open(path, 'r') as f:
        file_set = f.readlines()
        file_set = map(lambda x:  x.strip(), file_set)

    # 保存图片路径
    path_set = []
    # 保存标签
    label_set = []
    for file in file_set:
        # 创建一个“空”的标签
        label = np.zeros((7, 7, 25), dtype='float32')
        # 图片路径放入路径集
        path_set.append(os.path.join(path_JPEGImages, file + '.jpg'))
        # 获取 xml 标签文件的跟路径
        root = ET.parse(os.path.join(path_Annotations, file + '.xml')).getroot()
        width = int(root.find('size').findtext('width'))  # 获取目标的宽度
        height = int(root.find('size').findtext('height'))  # 获取图片的高度
        # 获取一个网格的宽高
        w_grid = width/7
        h_grid = height/7
        # 遍历所有 object 标签
        for object_label in root.iter('object'):
            cls = classes[object_label.findtext('name')]['code']  # 获取目标的类别
            xmin = int(object_label.find('bndbox').findtext('xmin'))  # 获取目标的 xmin
            ymin = int(object_label.find('bndbox').findtext('ymin'))  # 获取目标的 ymin
            xmax = int(object_label.find('bndbox').findtext('xmax'))  # 获取目标的 xmax
            ymax = int(object_label.find('bndbox').findtext('ymax'))  # 获取目标的 ymax

            x_center = (xmin + xmax) / 2  # 获取目标中心点 x
            y_center = (ymin + ymax) / 2  # 获取目标中心点 y
            x_idx = int(x_center / w_grid)  # 将图片分成 7x7 个区域,获取 x 方向上的索引
            y_idx = int(y_center / h_grid)  # 将图片分成 7x7 个区域,获取 y 方向上的索引

            x = (x_center - x_idx * w_grid) / w_grid  # 获取在 (x_idx,y_idx) 区域的中心点 x,并归一化
            y = (y_center - y_idx * h_grid) / h_grid  # 获取在 (x_idx,y_idx) 区域的中心点 y,并归一化
            w = (xmax - xmin) / width  # 获取图像长度,并归一化
            h = (ymax - ymin) / height  # 获取图像宽度,并归一化

            # 设置标签
            label[y_idx, x_idx, cls] = 1  # 设置类别
            label[y_idx, x_idx, 20:25] = [x, y, w, h, 1]  # 设置 (x, y, w, h, confidence)
        # 标签放入标签集
        label_set.append(label)

    return path_set, label_set

创建训练集

在上文中,我们已经能够获取图片路径和标签了。接下来,我们需要读取图片信息,并创建训练集

# 读取图片
def load_img(path, bbox):
    img = tf.io.read_file(path)
    img = tf.io.decode_jpeg(img, channels=3)
    img = tf.image.resize(img, (448, 448)) / 255
    return img, bbox

# 获取图片路径、标签
path_set, label_set = load_data(path_ImageSets_Layout_trainval)

# 创建数据集
data_set = tf.data.Dataset.from_tensor_slices((path_set, label_set))
data_set = data_set.map(load_img)  # 读取图片
data_set_num = len(data_set)
train_set_num = int(data_set_num * 0.8)

# 创建训练集
train_set = data_set.take(train_set_num)  # 取 80% 作为训练集
train_set = train_set.shuffle(1000)  # 打乱训练集
train_set = train_set.batch(16)  # batch size 设置为 16

# 读取验证集数据
valid_set = data_set.skip(train_set_num)  # 取 20% 作为验证集
valid_set = [i for i in valid_set]

至此,对于数据集方面的内容,结束。还需翻过设计损失函数与模型构建与训练这三座大山⛰️,方可修成正果😇

  • 14
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

余将董道而不豫兮

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值