Pytorch 目标检测和数据集

Pytorch 目标检测和数据集

0. 环境介绍

环境使用 Kaggle 里免费建立的 Notebook

教程使用李沐老师的 动手学深度学习 网站和 视频讲解

小技巧:当遇到函数看不懂的时候可以按 Shift+Tab 查看函数详解。

1. 目标检测

1.1 概述

在图像分类任务中,我们假设图像中只有一个主要物体对象,我们只关注如何识别其类别。然而,很多时候图像里有多个我们感兴趣的目标,我们不仅想知道它们的类别,还想得到它们在图像中的具体位置。 在计算机视觉里,我们将这类任务称为目标检测(object detection)或目标识别(object recognition)。

1.2 边缘框

一个边缘框可以通过 4 个数字定义:

  • (左上 x,左上 y,右下 x,右下 y)或者(左上 x,左上 y,宽,高)或者(中心 x,中心 y,宽,高)等

在这里插入图片描述
数据集标注的时候就是在画框框。

2. 数据集

每行表示一个物体

  • 图片文件名,物体类别,边缘框
    COCO(cocodataset.org
  • 80 物体,330K 图片,1.5M 物体

在这里插入图片描述

3. 代码

3.1 导入图片

!pip install -U d2l
%matplotlib inline
import torch
import os
import requests
from d2l import torch as d2l

从李沐老师的 GitHub 下载图片到本地:

if not os.path.exists('../data'):
    os.mkdir('../data')
url = 'https://raw.githubusercontent.com/d2l-ai/d2l-zh/master/img/catdog.jpg'
r = requests.get(url) 
with open('../data/catdog.jpg', 'wb') as f:
    f.write(r.content)
d2l.set_figsize()
img = d2l.plt.imread('../data/catdog.jpg')
d2l.plt.imshow(img)

在这里插入图片描述

3.2 边界框

我们定义在这两种表示法之间进行转换的函数:box_corner_to_center 从两角表示法转换为中心宽度表示法,而 box_center_to_corner 反之亦然。 输入参数 boxes 可以是长度为 4 4 4 的张量,也可以是形状为( n n n 4 4 4)的二维张量,其中 n n n 是边界框的数量:

def box_corner_to_center(boxes):
    """从(左上,右下)转换到(中间,宽度,高度)"""
    x1, y1, x2, y2 = boxes[:, 0], boxes[:, 1], boxes[:, 2], boxes[:, 3]
    cx = (x1 + x2) / 2
    cy = (y1 + y2) / 2
    w = x2 - x1
    h = y2 - y1
    boxes = torch.stack((cx, cy, w, h), axis=-1)
    return boxes

def box_center_to_corner(boxes):
    """从(中间,宽度,高度)转换到(左上,右下)"""
    cx, cy, w, h = boxes[:, 0], boxes[:, 1], boxes[:, 2], boxes[:, 3]
    x1 = cx - 0.5 * w
    y1 = cy - 0.5 * h
    x2 = cx + 0.5 * w
    y2 = cy + 0.5 * h
    boxes = torch.stack((x1, y1, x2, y2), axis=-1)
    return boxes

根据坐标信息定义图像中狗和猫的边界框,并通过转换两次来验证边界框转换函数的正确性:

# bbox是边界框的英文缩写
dog_bbox, cat_bbox = [60.0, 45.0, 378.0, 516.0], [400.0, 112.0, 655.0, 493.0]

boxes = torch.tensor((dog_bbox, cat_bbox))
box_center_to_corner(box_corner_to_center(boxes)) == boxes

在这里插入图片描述

定义一个辅助函数bbox_to_rect。 它将边界框表示成matplotlib的边界框格式:

def bbox_to_rect(bbox, color):
    # 将边界框(左上x,左上y,右下x,右下y)格式转换成matplotlib格式:
    # ((左上x,左上y),宽,高)
    return d2l.plt.Rectangle(
        xy=(bbox[0], bbox[1]), width=bbox[2]-bbox[0], height=bbox[3]-bbox[1],
        fill=False, edgecolor=color, linewidth=2)

图像上添加边界框之后,我们可以看到两个物体的主要轮廓基本上在两个框内:

fig = d2l.plt.imshow(img)
fig.axes.add_patch(bbox_to_rect(dog_bbox, 'blue'))
fig.axes.add_patch(bbox_to_rect(cat_bbox, 'red'))

在这里插入图片描述

3.3 数据集

3.3.1 下载数据集
import pandas as pd
import torchvision

d2l.DATA_HUB['banana-detection'] = (
    d2l.DATA_URL + 'banana-detection.zip',
    '5de26c8fce5ccdea9f91267273464dc968d20d72')
3.3.2 读取数据集

该数据集包括一个 CSV 文件,内含目标类别标签和位于左上角和右下角的真实边界框坐标:

def read_data_bananas(is_train=True):
    """读取香蕉检测数据集中的图像和标签"""
    data_dir = d2l.download_extract('banana-detection')
    csv_fname = os.path.join(data_dir, 'bananas_train' if is_train
                             else 'bananas_val', 'label.csv')
    csv_data = pd.read_csv(csv_fname)
    csv_data = csv_data.set_index('img_name')
    images, targets = [], []
    for img_name, target in csv_data.iterrows():
        images.append(torchvision.io.read_image(
            os.path.join(data_dir, 'bananas_train' if is_train else
                         'bananas_val', 'images', f'{img_name}')))
        # 这里的target包含(类别,左上角x,左上角y,右下角x,右下角y),
        # 其中所有图像都具有相同的香蕉类(索引为0)
        targets.append(list(target))
    return images, torch.tensor(targets).unsqueeze(1) / 256
3.3.3 自定义 Dataset 类
class BananasDataset(torch.utils.data.Dataset):
    """一个用于加载香蕉检测数据集的自定义数据集"""
    def __init__(self, is_train):
        self.features, self.labels = read_data_bananas(is_train)
        print('read ' + str(len(self.features)) + (f' training examples' if
              is_train else f' validation examples'))

    def __getitem__(self, idx):
        return (self.features[idx].float(), self.labels[idx])

    def __len__(self):
        return len(self.features)
3.3.4 自定义数据加载器

为训练集和测试集返回两个数据加载器实例。对于测试集,无须按随机顺序读取它:

def load_data_bananas(batch_size):
    """加载香蕉检测数据集"""
    train_iter = torch.utils.data.DataLoader(BananasDataset(is_train=True),
                                             batch_size, shuffle=True)
    val_iter = torch.utils.data.DataLoader(BananasDataset(is_train=False),
                                           batch_size)
    return train_iter, val_iter
3.3.5 读取小批量
batch_size, edge_size = 32, 256
train_iter, _ = load_data_bananas(batch_size)
batch = next(iter(train_iter))
batch[0].shape, batch[1].shape

在这里插入图片描述
图像的小批量的形状为(批量大小,通道数,高度,宽度),与之前图像分类任务中的相同。
标签的小批量的形状为(批量大小, m m m 5 5 5),其中 m m m 是数据集的任何图像中边界框可能出现的最大数量(本数据集中只有 1 个,所以设置为 1),其中 5 5 5 表示每个框的标号(种类)以及 4 4 4 个坐标。

3.3.6 演示
# permute 交换维度,torch 数值顺序:BCHW,NP 里是:BHWC
imgs = (batch[0][0:10].permute(0, 2, 3, 1)) / 255
axes = d2l.show_images(imgs, 2, 5, scale=2)
for ax, label in zip(axes, batch[1][0:10]):
    d2l.show_bboxes(ax, [label[0][1:5] * edge_size], colors=['w'])

在这里插入图片描述
对边框操作的时候要小心,注意是按照相对位置还是像素设置。

4. Q&A

Q:有哪些标注软件/平台推荐?
A:弹幕上说的:Labeling,Makesense,Vott 等。也可以自己标注,使用半监督学习,迁移学习等。

  • 1
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

哇咔咔负负得正

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

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

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

打赏作者

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

抵扣说明:

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

余额充值