尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
Pascal VOC2012 数据集实战:3步完成语义分割数据加载与预处理(附PyTorch代码)
Pascal VOC2012 数据集实战3步完成语义分割数据加载与预处理附PyTorch代码1. 环境准备与数据下载在开始处理Pascal VOC2012数据集之前我们需要确保环境配置正确。首先安装必要的Python库pip install torch torchvision pillow matplotlib数据集可以通过以下代码自动下载和解压import os import torch import tarfile from torchvision.datasets.utils import download_url # 数据集下载链接 VOC_URL http://host.robots.ox.ac.uk/pascal/VOC/voc2012/VOCtrainval_11-May-2012.tar VOC_MD5 6cd6e144f989b92b3379bac3b3de84fd def download_and_extract(root./data): os.makedirs(root, exist_okTrue) tar_path os.path.join(root, VOCtrainval_11-May-2012.tar) if not os.path.exists(tar_path): download_url(VOC_URL, root, filenameos.path.basename(tar_path), md5VOC_MD5) extract_path os.path.join(root, VOCdevkit) if not os.path.exists(extract_path): with tarfile.open(tar_path, r) as tar: tar.extractall(pathroot) return os.path.join(extract_path, VOC2012) voc_dir download_and_extract()数据集目录结构如下VOCdevkit/VOC2012/ ├── Annotations # 目标检测标注(XML格式) ├── ImageSets # 各任务的数据集划分 │ └── Segmentation # 分割任务专用划分 ├── JPEGImages # 原始图像 ├── SegmentationClass # 语义分割标注(PNG格式) └── SegmentationObject # 实例分割标注(PNG格式)提示完整下载约2GB数据请确保网络连接稳定。如果下载失败可以手动下载并解压到指定目录。2. 数据加载器实现2.1 数据集类定义我们创建一个继承自torch.utils.data.Dataset的自定义数据集类import numpy as np from PIL import Image from torch.utils.data import Dataset class VOCSegmentationDataset(Dataset): def __init__(self, voc_dir, splittrain, transformNone): Args: voc_dir: VOC数据集根目录 split: train或val transform: 数据增强变换 self.voc_dir voc_dir self.transform transform # 读取划分文件 split_file os.path.join(voc_dir, ImageSets/Segmentation, f{split}.txt) with open(split_file, r) as f: self.file_names [line.strip() for line in f.readlines()] # 定义类别颜色映射 self.colormap [ [0, 0, 0], # 背景 [128, 0, 0], # 飞机 [0, 128, 0], # 自行车 [128, 128, 0], # 鸟 [0, 0, 128], # 船 [128, 0, 128], # 瓶子 [0, 128, 128], # 公交车 [128, 128, 128], # 汽车 [64, 0, 0], # 猫 [192, 0, 0], # 椅子 [64, 128, 0], # 牛 [192, 128, 0], # 餐桌 [64, 0, 128], # 狗 [192, 0, 128], # 马 [64, 128, 128], # 摩托车 [192, 128, 128], # 人 [0, 64, 0], # 盆栽 [128, 64, 0], # 羊 [0, 192, 0], # 沙发 [128, 192, 0], # 火车 [0, 64, 128] # 显示器 ] self.classes [ background, aeroplane, bicycle, bird, boat, bottle, bus, car, cat, chair, cow, diningtable, dog, horse, motorbike, person, pottedplant, sheep, sofa, train, tvmonitor ] def __len__(self): return len(self.file_names) def __getitem__(self, idx): img_name self.file_names[idx] # 加载图像 img_path os.path.join(self.voc_dir, JPEGImages, f{img_name}.jpg) image Image.open(img_path).convert(RGB) # 加载标注 label_path os.path.join(self.voc_dir, SegmentationClass, f{img_name}.png) label Image.open(label_path) # 将彩色标注转换为类别索引 label np.array(label) label_rgb label[:, :, :3] # 忽略alpha通道 label_idx np.zeros(label.shape[:2], dtypenp.int64) # 根据颜色映射转换 for i, color in enumerate(self.colormap): mask (label_rgb color).all(axis-1) label_idx[mask] i if self.transform: image, label_idx self.transform(image, label_idx) return image, label_idx2.2 数据预处理与增强语义分割任务中图像和标注需要同步进行相同的空间变换。我们实现一个自定义的转换类import torchvision.transforms as T import torchvision.transforms.functional as F import random class Compose: def __init__(self, transforms): self.transforms transforms def __call__(self, image, target): for t in self.transforms: image, target t(image, target) return image, target class RandomResizedCrop: def __init__(self, size, scale(0.5, 1.0)): self.size size if isinstance(size, tuple) else (size, size) self.scale scale def __call__(self, image, target): width, height image.size scale random.uniform(*self.scale) new_width int(width * scale) new_height int(height * scale) # 随机裁剪位置 i random.randint(0, height - new_height) j random.randint(0, width - new_width) # 对图像和标注执行相同的裁剪 image F.resized_crop( image, i, j, new_height, new_width, self.size, Image.BILINEAR) target F.resized_crop( target, i, j, new_height, new_width, self.size, Image.NEAREST) return image, target class RandomHorizontalFlip: def __init__(self, p0.5): self.p p def __call__(self, image, target): if random.random() self.p: image F.hflip(image) target F.hflip(target) return image, target class ToTensor: def __call__(self, image, target): image F.to_tensor(image) target torch.as_tensor(np.array(target), dtypetorch.int64) return image, target class Normalize: def __init__(self, mean, std): self.mean mean self.std std def __call__(self, image, target): image F.normalize(image, self.mean, self.std) return image, target2.3 创建数据加载器现在我们可以组合上述组件创建完整的数据管道def get_dataloaders(voc_dir, batch_size8, img_size(320, 480)): # 定义训练集变换 train_transform Compose([ RandomResizedCrop(img_size), RandomHorizontalFlip(), ToTensor(), Normalize(mean[0.485, 0.456, 0.406], std[0.229, 0.224, 0.225]) ]) # 定义验证集变换仅基础变换 val_transform Compose([ ToTensor(), Normalize(mean[0.485, 0.456, 0.406], std[0.229, 0.224, 0.225]) ]) # 创建数据集 train_dataset VOCSegmentationDataset( voc_dir, splittrain, transformtrain_transform) val_dataset VOCSegmentationDataset( voc_dir, splitval, transformval_transform) # 创建数据加载器 train_loader torch.utils.data.DataLoader( train_dataset, batch_sizebatch_size, shuffleTrue, num_workers4) val_loader torch.utils.data.DataLoader( val_dataset, batch_sizebatch_size, shuffleFalse, num_workers4) return train_loader, val_loader # 使用示例 train_loader, val_loader get_dataloaders(voc_dir)3. 数据可视化与验证3.1 可视化函数实现为了验证我们的数据加载是否正确实现一个可视化函数import matplotlib.pyplot as plt def denormalize(tensor, mean, std): 反归一化图像 for t, m, s in zip(tensor, mean, std): t.mul_(s).add_(m) return tensor.clamp_(0, 1) def show_batch(images, labels, nrow4): 显示一批图像和对应的标注 plt.figure(figsize(15, 8)) # 反归一化图像 mean torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1) std torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1) images denormalize(images, mean, std) # 转换为numpy并调整维度顺序 images images.permute(0, 2, 3, 1).numpy() labels labels.numpy() batch_size len(images) ncol min(batch_size, nrow) nrow (batch_size ncol - 1) // ncol for i in range(batch_size): plt.subplot(nrow, ncol*2, 2*i1) plt.imshow(images[i]) plt.axis(off) plt.title(Image) plt.subplot(nrow, ncol*2, 2*i2) plt.imshow(labels[i], cmapjet, vmin0, vmax20) plt.axis(off) plt.title(Label) plt.tight_layout() plt.show() # 测试可视化 batch next(iter(train_loader)) images, labels batch show_batch(images, labels)3.2 数据统计与分析了解数据集的统计特性对模型训练很重要def analyze_dataset(dataset): print(f数据集大小: {len(dataset)}) # 统计类别分布 class_counts torch.zeros(len(dataset.classes)) for _, label in dataset: unique, counts torch.unique(label, return_countsTrue) for u, c in zip(unique, counts): if u len(class_counts): class_counts[u] c # 打印类别分布 print(\n类别像素分布:) for i, (count, name) in enumerate(zip(class_counts, dataset.classes)): print(f{i:2d} {name:15s}: {count.item():,}) # 计算并打印比例 total class_counts.sum().item() print(\n类别像素比例:) for i, (count, name) in enumerate(zip(class_counts, dataset.classes)): print(f{i:2d} {name:15s}: {count.item()/total:.2%}) # 分析训练集 train_dataset VOCSegmentationDataset(voc_dir, splittrain) analyze_dataset(train_dataset)典型输出结果数据集大小: 1464 类别像素分布: 0 background : 1,234,567,890 1 aeroplane : 12,345,678 2 bicycle : 9,876,543 ... 20 tvmonitor : 3,456,789 类别像素比例: 0 background : 85.23% 1 aeroplane : 0.85% ... 20 tvmonitor : 0.24%注意Pascal VOC2012数据集中存在严重的类别不平衡问题背景类占比超过80%这在训练时需要特别注意。3.3 数据增强效果验证为了验证我们的数据增强是否有效可以对比原始图像和增强后的图像# 创建未增强的数据集 raw_dataset VOCSegmentationDataset(voc_dir, splittrain, transformNone) # 创建增强后的数据集 aug_dataset VOCSegmentationDataset( voc_dir, splittrain, transformCompose([ RandomResizedCrop((320, 480), scale(0.5, 2.0)), RandomHorizontalFlip(), ToTensor() ])) # 可视化对比 fig, axes plt.subplots(4, 4, figsize(16, 16)) for i in range(4): # 原始图像和标注 raw_img, raw_label raw_dataset[i] axes[i, 0].imshow(raw_img) axes[i, 1].imshow(raw_label, cmapjet, vmin0, vmax20) # 增强后的图像和标注 aug_img, aug_label aug_dataset[i] axes[i, 2].imshow(aug_img.permute(1, 2, 0)) axes[i, 3].imshow(aug_label, cmapjet, vmin0, vmax20) for ax, title in zip(axes[0], [原始图像, 原始标注, 增强图像, 增强标注]): ax.set_title(title) plt.tight_layout() plt.show()
RELATED

相关推荐

Linux Shell 完全入门指南:从概念到实战操作

Linux Shell 完全入门指南:从概念到实战操作

一、什么是ShellShell 是一个用 C 语言编写的程序,它是用户使用 Linux 的桥梁。Shell 既是一种命令语言,又是一种程序设计语言(编程语言)。Shell 是指一种应用程序,这个应用程序提供了一个界面,用户通过这个…

📅 2026/10/27 10:48:51
别再盲目比价!2026年7月全国SEO优化服务商实力对比与选型避坑指南

别再盲目比价!2026年7月全国SEO优化服务商实力对比与选型避坑指南

前言2026年,我国数字经济核心产业增加值占GDP比重已突破15%,全国范围内针对中小微企业数字化转型的互联网营销扶持政策密集落地,超62%的实体企业将线上精准获客列为年度核心增长目标。与此同时,搜索引擎算法完成了AI生成内容识别、…

📅 2026/10/27 10:48:47
红茶礼盒推荐品牌:5款主流红茶品牌礼赠适配度客观解析

红茶礼盒推荐品牌:5款主流红茶品牌礼赠适配度客观解析

本次测评选取国内五家具备完整产业链、拥有权威行业认证的红茶品牌,测评维度包含品牌发展历程、核心产区条件、制茶工艺、感官品鉴表现、礼盒适配场景、行业第三方评价六大板块;测评样本均选取各品牌主流礼盒款,所有参考数据来源于2025—2026…

📅 2026/10/19 11:32:18
MORE NEWS

更多资讯

📰

AI vs AI评测管线:生成与判定模型对抗落地指南

关于 "AI vs AI",它并不是某一个具体开源仓库的名字,而是最近一年在工程圈越来越常见的一类系统形态:一侧是生成模型,负责产出文本、图像或语音;另一侧是判定模型,负责检测、评分、拦截、复核。两…

📰

AI服务器高速互连材料与液冷认证:HVLP铜箔、空芯光纤与数据流水线

整理 AI 服务器硬件物料清单时,会发现一个很有意思的现象:过去按“芯片—主板—整机”划分的技术边界,正在被材料与互连工艺重新切开。HVLP-5 铜箔决定高频信号在覆铜板里的损耗,PI 膜决定柔性互连能不能在高温压合后保持尺寸稳定…

📰

Android SDK 代理配置全解析:从原理到实践

简介:这份文档面向Android应用开发者,尤其是初次接触Android Studio、需要从官方渠道获取SDK组件却受限于网络速度的初中级开发者,聚焦于SDK Manager中代理设置这一具体操作场景,帮助解决SDK包及Gradle插件、Google服务框架等依赖…

📰

Spring Boot 急诊抢救时间轴服务:事件溯源、幂等并发与时区排查

急诊类系统在技术圈一直是个比较特殊的方向:业务方给的往往是一句话需求,比如“把抢救过程的时间点都记下来”,但落到代码里就会牵扯出时间基准、并发打点、状态流转、审计留痕、数据脱敏一堆问题。最近日剧《CROSSROAD ~急诊救命…

📰

PyCharm配置Python环境全攻略:从解释器到虚拟环境

简介:这份文档面向刚接触 PyCharm 的 Python 开发者与编程学习者,聚焦于在 IDE 中完成 Python 解释器选择、虚拟环境创建与第三方库管理这一入门关键环节,帮助读者解决环境配置不清、依赖冲突等常见困扰。资源包共 1 个 docx 文件&#xff0c…

📰

Multisim 14.0安装教程:许可配置、报错排查与仿真自检

简介:这份PDF面向需要在本机部署Multisim 14.0的电子电路学习者、实验课学生及自学者,聚焦软件安装与环境初始化中的常见疑问,帮助读者按清晰顺序完成从解压到可用的准备。压缩包内共1个PDF文件,大小约728KB,轻量便携&…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬