如何自己做网站一年赚一亿,网站怎么做seo优化,做方案的网站,网站ftp目录引言
在深度学习项目中#xff0c;数据准备是非常重要的一环。特别是在物体检测任务中#xff0c;数据的组织和预处理直接影响到模型的训练效果。YOLO V3#xff08;You Only Look Once Version 3#xff09;作为一种高效的实时物体检测框架#xff0c;其数据加载器的设计…引言
在深度学习项目中数据准备是非常重要的一环。特别是在物体检测任务中数据的组织和预处理直接影响到模型的训练效果。YOLO V3You Only Look Once Version 3作为一种高效的实时物体检测框架其数据加载器的设计对于确保模型训练的顺利进行至关重要。本文将详细介绍如何使用Python和PyTorch实现一个YOLO V3的数据加载器以支持从文件系统中读取图像及其对应的标签文件并进行必要的预处理。
数据集组织
首先我们需要了解数据集是如何组织的。通常情况下图像数据集会被分成两个主要的部分
图像文件这些文件通常保存在磁盘上并且每张图像都有一个对应的文件名。标签文件与图像文件一一对应每个标签文件记录了图像中物体的位置和类别信息。
标签文件通常是以文本格式存储的每一行代表一个物体的边界框信息格式为 类别 中心点X 中心点Y 宽度 高度。这些值通常是归一化的即相对于图像的宽度和高度而言。
数据加载器实现
为了实现YOLO V3的数据加载器我们需要创建一个继承自torch.utils.data.Dataset的类并重写其__init__、__len__和__getitem__方法。此外我们还需要定义一些辅助函数来处理图像的预处理工作如填充、调整大小等。
导入必要的库
import glob
import random
import os
import numpy as np
from PIL import Image
import torch
import torch.nn.functional as F
from torch.utils.data import Dataset
import torchvision.transforms as transforms
这段代码导入了构建数据加载器所需的库包括文件处理、图像处理、张量操作等。
辅助函数定义
pad_to_square 函数
# 定义将图像填充为正方形的函数
def pad_to_square(img, pad_value):# 获取图像的通道数、高度和宽度c, h, w img.shape# 计算高度和宽度的差值dim_diff np.abs(h - w)# 计算需要在较短边填充的数量pad1, pad2 dim_diff // 2, dim_diff - dim_diff // 2# 根据高度和宽度确定填充的方向左侧/右侧 或 上侧/下侧pad (0, 0, pad1, pad2) if h w else (pad1, pad2, 0, 0)# 对图像进行填充img F.pad(img, pad, constant, valuepad_value)return img, pad
此函数将图像填充为正方形以便后续处理。它计算图像的高度和宽度之差并据此决定在哪个方向上添加填充。
resize 函数 # 定义调整图像大小的函数
def resize(image, size):# 使用最近邻插值调整图像大小image F.interpolate(image.unsqueeze(0), sizesize, modenearest).squeeze(0)return image
此函数将图像调整为指定的大小。它首先将图像的维度扩展到 (1, C, H, W)然后使用最近邻插值进行缩放最后再压缩回原来的维度。
数据集类定义
ListDataset 类
# 定义数据集类
class ListDataset(Dataset):# 初始化方法def __init__(self, list_path, img_size416, augmentTrue, multiscaleTrue, normalized_labelsTrue):# 读取包含图像路径的列表文件with open(list_path, r) as file:self.img_files file.readlines()# 根据图像路径找到对应的标签文件路径self.label_files [path.replace(images, labels).replace(.png, .txt).replace(.jpg, .txt)for path in self.img_files]# 设置图像大小self.img_size img_size# 最大对象数量self.max_objects 100# 是否启用数据增强self.augment augment# 是否启用多尺度训练self.multiscale multiscale# 标签是否已经归一化self.normalized_labels normalized_labels# 设置图像大小的最小值和最大值self.min_size self.img_size - 3 * 32self.max_size self.img_size 3 * 32# 用于追踪批次计数self.batch_count 0
这是数据集类的初始化方法它读取包含图像路径的列表文件并根据图像路径找到对应的标签文件路径。
__getitem__ 方法 # 获取数据集中指定索引的项目def __getitem__(self, index):# 获取图像路径img_path self.img_files[index % len(self.img_files)].rstrip()# 读取图像并转换为张量img transforms.ToTensor()(Image.open(img_path).convert(RGB))# 如果图像不是三通道则扩展为三通道if len(img.shape) ! 3:img img.unsqueeze(0)img img.expand((3, img.shape[1:]))# 获取图像的高度和宽度_, h, w img.shape# 计算填充因子h_factor, w_factor (h, w) if self.normalized_labels else (1, 1)# 将图像填充为正方形img, pad pad_to_square(img, 0)# 获取填充后的图像的高度和宽度_, padded_h, padded_w img.shape# 获取标签文件路径label_path self.label_files[index % len(self.img_files)].rstrip()targets Noneif os.path.exists(label_path):# 读取标签文件boxes torch.from_numpy(np.loadtxt(label_path).reshape(-1, 5))# 计算边界框的真实坐标x1 w_factor * (boxes[:, 1] - boxes[:, 3] / 2)y1 h_factor * (boxes[:, 2] - boxes[:, 4] / 2)x2 w_factor * (boxes[:, 1] boxes[:, 3] / 2)y2 h_factor * (boxes[:, 2] boxes[:, 4] / 2)# 考虑到填充的影响调整边界框坐标x1 pad[0]y1 pad[2]x2 pad[1]y2 pad[3]# 重新归一化边界框坐标boxes[:, 1] ((x1 x2) / 2) / padded_wboxes[:, 2] ((y1 y2) / 2) / padded_hboxes[:, 3] * w_factor / padded_wboxes[:, 4] * h_factor / padded_h# 创建目标张量targets torch.zeros((len(boxes), 6))targets[:, 1:] boxes# 应用数据增强if self.augment and np.random.random() 0.5:img, targets horisontal_flip(img, targets)return img_path, img, targets
此方法用于获取数据集中单个样本。它读取图像进行必要的预处理如转换为张量、填充至正方形、调整大小并读取对应的标签文件调整边界框坐标以适应图像处理后的变化。
collate_fn 方法 # 用于处理一批数据的方法def collate_fn(self, batch):# 解压批次数据paths, imgs, targets zip(*batch)# 移除空的占位标签targets [boxes for boxes in targets if boxes is not None]# 给每个目标添加样本索引for i, boxes in enumerate(targets):boxes[:, 0] i# 合并所有目标targets torch.cat(targets, 0)# 每十个批次选择一个新的图像大小if self.multiscale and self.batch_count % 10 0:self.img_size random.choice(range(self.min_size, self.max_size 1, 32))# 调整图像大小imgs torch.stack([resize(img, self.img_size) for img in imgs])# 更新批次计数self.batch_count 1return paths, imgs, targets
此方法用于处理从数据集中获取的一批数据。它合并不同样本的标签并根据需要调整图像大小。
__len__ 方法 # 返回数据集中样本的数量def __len__(self):return len(self.img_files)
返回数据集中样本的数量。