【深度学习笔记】9_9 语义分割和数据集

注:本文为《动手学深度学习》开源内容,部分标注了个人理解,仅为个人学习记录,无抄袭搬运意图

9.9 语义分割和数据集

在前几节讨论的目标检测问题中,我们一直使用方形边界框来标注和预测图像中的目标。本节将探讨语义分割(semantic segmentation)问题,它关注如何将图像分割成属于不同语义类别的区域。值得一提的是,这些语义区域的标注和预测都是像素级的。图9.10展示了语义分割中图像有关狗、猫和背景的标签。可以看到,与目标检测相比,语义分割标注的像素级的边框显然更加精细。

在这里插入图片描述

图9.10 语义分割中图像有关狗、猫和背景的标签

9.9.1 图像分割和实例分割

计算机视觉领域还有2个与语义分割相似的重要问题,即图像分割(image segmentation)和实例分割(instance segmentation)。我们在这里将它们与语义分割简单区分一下。

  • 图像分割将图像分割成若干组成区域。这类问题的方法通常利用图像中像素之间的相关性。它在训练时不需要有关图像像素的标签信息,在预测时也无法保证分割出的区域具有我们希望得到的语义。以图9.10的图像为输入,图像分割可能将狗分割成两个区域:一个覆盖以黑色为主的嘴巴和眼睛,而另一个覆盖以黄色为主的其余部分身体。
  • 实例分割又叫同时检测并分割(simultaneous detection and segmentation)。它研究如何识别图像中各个目标实例的像素级区域。与语义分割有所不同,实例分割不仅需要区分语义,还要区分不同的目标实例。如果图像中有两只狗,实例分割需要区分像素属于这两只狗中的哪一只。

9.9.2 Pascal VOC2012语义分割数据集

语义分割的一个重要数据集叫作Pascal VOC2012 [1]。为了更好地了解这个数据集,我们先导入实验所需的包或模块。

%matplotlib inline
import time
import torch
import torch.nn.functional as F
import torchvision
import numpy as np
from PIL import Image
from tqdm import tqdmimport sys
sys.path.append("..") 
import d2lzh_pytorch as d2l

我们先下载这个数据集的压缩包(下载地址)。压缩包大小是2 GB左右,下载需要一定时间。下载后解压得到VOCdevkit/VOC2012文件夹,然后将其放置在data文件夹下。

!ls ../../data/VOCdevkit/VOC2012
Annotations        JPEGImages         SegmentationObject
ImageSets          SegmentationClass

进入../../data/VOCdevkit/VOC2012路径后,我们可以获取数据集的不同组成部分。其中ImageSets/Segmentation路径包含了指定训练和测试样本的文本文件,而JPEGImagesSegmentationClass路径下分别包含了样本的输入图像和标签。这里的标签也是图像格式,其尺寸和它所标注的输入图像的尺寸相同。标签中颜色相同的像素属于同一个语义类别。下面定义read_voc_images函数将输入图像和标签读进内存。

# 本函数已保存在d2lzh_pytorch中方便以后使用
def read_voc_images(root="../../data/VOCdevkit/VOC2012", is_train=True, max_num=None):txt_fname = '%s/ImageSets/Segmentation/%s' % (root, 'train.txt' if is_train else 'val.txt')with open(txt_fname, 'r') as f:images = f.read().split()if max_num is not None:images = images[:min(max_num, len(images))]features, labels = [None] * len(images), [None] * len(images)for i, fname in tqdm(enumerate(images)):features[i] = Image.open('%s/JPEGImages/%s.jpg' % (root, fname)).convert("RGB")labels[i] = Image.open('%s/SegmentationClass/%s.png' % (root, fname)).convert("RGB")return features, labels # PIL imagevoc_dir = "../../data/VOCdevkit/VOC2012"
train_features, train_labels = read_voc_images(voc_dir, max_num=100)

我们画出前5张输入图像和它们的标签。在标签图像中,白色和黑色分别代表边框和背景,而其他不同的颜色则对应不同的类别。

n = 5
imgs = train_features[0:n] + train_labels[0:n]
d2l.show_images(imgs, 2, n);

在这里插入图片描述

接下来,我们列出标签中每个RGB颜色的值及其标注的类别。

# 本函数已保存在d2lzh_pytorch中方便以后使用
VOC_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]]
# 本函数已保存在d2lzh_pytorch中方便以后使用
VOC_CLASSES = ['background', 'aeroplane', 'bicycle', 'bird', 'boat','bottle', 'bus', 'car', 'cat', 'chair', 'cow','diningtable', 'dog', 'horse', 'motorbike', 'person','potted plant', 'sheep', 'sofa', 'train', 'tv/monitor']

有了上面定义的两个常量以后,我们可以很容易地查找标签中每个像素的类别索引。

colormap2label = torch.zeros(256 ** 3, dtype=torch.uint8)
for i, colormap in enumerate(VOC_COLORMAP):colormap2label[(colormap[0] * 256 + colormap[1]) * 256 + colormap[2]] = i# 本函数已保存在d2lzh_pytorch中方便以后使用
def voc_label_indices(colormap, colormap2label):"""convert colormap (PIL image) to colormap2label (uint8 tensor)."""colormap = np.array(colormap.convert("RGB")).astype('int32')idx = ((colormap[:, :, 0] * 256 + colormap[:, :, 1]) * 256+ colormap[:, :, 2])return colormap2label[idx]

例如,第一张样本图像中飞机头部区域的类别索引为1,而背景全是0。

y = voc_label_indices(train_labels[0], colormap2label)
y[105:115, 130:140], VOC_CLASSES[1]

输出:

(tensor([[0, 0, 0, 0, 0, 0, 0, 0, 0, 1],[0, 0, 0, 0, 0, 0, 0, 1, 1, 1],[0, 0, 0, 0, 0, 0, 1, 1, 1, 1],[0, 0, 0, 0, 0, 1, 1, 1, 1, 1],[0, 0, 0, 0, 0, 1, 1, 1, 1, 1],[0, 0, 0, 0, 1, 1, 1, 1, 1, 1],[0, 0, 0, 0, 0, 1, 1, 1, 1, 1],[0, 0, 0, 0, 0, 1, 1, 1, 1, 1],[0, 0, 0, 0, 0, 0, 1, 1, 1, 1],[0, 0, 0, 0, 0, 0, 0, 0, 1, 1]], dtype=torch.uint8), 'aeroplane')

9.9.2.1 预处理数据

在之前的章节中,我们通过缩放图像使其符合模型的输入形状。然而在语义分割里,这样做需要将预测的像素类别重新映射回原始尺寸的输入图像。这样的映射难以做到精确,尤其在不同语义的分割区域。为了避免这个问题,我们将图像裁剪成固定尺寸而不是缩放。具体来说,我们使用图像增广里的随机裁剪,并对输入图像和标签裁剪相同区域。

# 本函数已保存在d2lzh_pytorch中方便以后使用
def voc_rand_crop(feature, label, height, width):"""Random crop feature (PIL image) and label (PIL image)."""i, j, h, w = torchvision.transforms.RandomCrop.get_params(feature, output_size=(height, width))feature = torchvision.transforms.functional.crop(feature, i, j, h, w)label = torchvision.transforms.functional.crop(label, i, j, h, w)    return feature, labelimgs = []
for _ in range(n):imgs += voc_rand_crop(train_features[0], train_labels[0], 200, 300)
d2l.show_images(imgs[::2] + imgs[1::2], 2, n);

在这里插入图片描述

9.9.2.2 自定义语义分割数据集类

我们通过继承PyTorch提供的Dataset类自定义了一个语义分割数据集类VOCSegDataset。通过实现__getitem__函数,我们可以任意访问数据集中索引为idx的输入图像及其每个像素的类别索引。由于数据集中有些图像的尺寸可能小于随机裁剪所指定的输出尺寸,这些样本需要通过自定义的filter函数所移除。此外,我们还对输入图像的RGB三个通道的值分别做标准化。

# 本函数已保存在d2lzh_pytorch中方便以后使用
class VOCSegDataset(torch.utils.data.Dataset):def __init__(self, is_train, crop_size, voc_dir, colormap2label, max_num=None):"""crop_size: (h, w)"""self.rgb_mean = np.array([0.485, 0.456, 0.406])self.rgb_std = np.array([0.229, 0.224, 0.225])self.tsf = torchvision.transforms.Compose([torchvision.transforms.ToTensor(),torchvision.transforms.Normalize(mean=self.rgb_mean, std=self.rgb_std)])self.crop_size = crop_size # (h, w)features, labels = read_voc_images(root=voc_dir, is_train=is_train, max_num=max_num)self.features = self.filter(features) # PIL imageself.labels = self.filter(labels)     # PIL imageself.colormap2label = colormap2labelprint('read ' + str(len(self.features)) + ' valid examples')def filter(self, imgs):return [img for img in imgs if (img.size[1] >= self.crop_size[0] andimg.size[0] >= self.crop_size[1])]def __getitem__(self, idx):feature, label = voc_rand_crop(self.features[idx], self.labels[idx],*self.crop_size)return (self.tsf(feature), # float32 tensorvoc_label_indices(label, self.colormap2label)) # uint8 tensordef __len__(self):return len(self.features)

9.9.2.3 读取数据集

我们通过自定义的VOCSegDataset类来分别创建训练集和测试集的实例。假设我们指定随机裁剪的输出图像的形状为 320 × 480 320\times 480 320×480。下面我们可以查看训练集和测试集所保留的样本个数。

crop_size = (320, 480)
max_num = 100
voc_train = VOCSegDataset(True, crop_size, voc_dir, colormap2label, max_num)
voc_test = VOCSegDataset(False, crop_size, voc_dir, colormap2label, max_num)

输出:

read 75 valid examples
read 77 valid examples

设批量大小为64,分别定义训练集和测试集的迭代器。

batch_size = 64
num_workers = 0 if sys.platform.startswith('win32') else 4
train_iter = torch.utils.data.DataLoader(voc_train, batch_size, shuffle=True,drop_last=True, num_workers=num_workers)
test_iter = torch.utils.data.DataLoader(voc_test, batch_size, drop_last=True,num_workers=num_workers)

打印第一个小批量的类型和形状。不同于图像分类和目标识别,这里的标签是一个三维数组。

for X, Y in train_iter:print(X.dtype, X.shape)print(y.dtype, Y.shape)break

输出:

torch.float32 torch.Size([64, 3, 320, 480])
torch.uint8 torch.Size([64, 320, 480])

小结

  • 语义分割关注如何将图像分割成属于不同语义类别的区域。
  • 语义分割的一个重要数据集叫作Pascal VOC2012。
  • 由于语义分割的输入图像和标签在像素上一一对应,所以将图像随机裁剪成固定尺寸而不是缩放。

练习

  • 回忆9.1节(图像增广)中的内容。哪些在图像分类中使用的图像增广方法难以用于语义分割?

参考文献

[1] Pascal VOC2012数据集。http://host.robots.ox.ac.uk/pascal/VOC/voc2012/


注:除代码外本节与原书基本相同,原书传送门

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/747253.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

深度学习基础知识之Atrous卷积(空洞卷积)

太久不看代码确实生疏了,盯着一堆不同的dilation,不知道有什么作用,论文中说是Atrous卷积,原来就是空洞卷积的意思。 Dilated/Atrous Convolution 空洞卷积(膨胀卷积/扩张卷积) 空洞卷积是一种不增加参数量…

Web 服务器-Tomcat

文章目录 Web服务器一、Tomcat简介二、基本使用三、在IDEA中创建Maven Web项目四、在IDEA中使用Tomcat Web服务器 一、Tomcat简介 二、基本使用 三、在IDEA中创建Maven Web项目 四、在IDEA中使用Tomcat

外包干了9天,技术退步明显。。。。。

先说一下自己的情况,本科生,2018年我通过校招踏入了南京一家软件公司,开始了我的职业生涯。那时的我,满怀热血和憧憬,期待着在这个行业中闯出一片天地。然而,随着时间的推移,我发现自己逐渐陷入…

【C#】.net core 6.0 使用第三方日志插件Log4net,日志输出到控制台或者文本文档

欢迎来到《小5讲堂》 大家好,我是全栈小5。 这是《C#》系列文章,每篇文章将以博主理解的角度展开讲解, 特别是针对知识点的概念进行叙说,大部分文章将会对这些概念进行实际例子验证,以此达到加深对知识点的理解和掌握。…

关于原型的一些总结

猛然发现太久没去复习了,于是复习了一些知识,顺便冒个泡。本次主要总结的知识点关于原型,再文章后半部分有原型相关的题,感兴趣的可直接观看。 一、原型 1.什么是原型 简单理解,原型就是一个对象,通过原…

Linux基础 想学好Linux请看这篇文章 Linux操作指令大全

当涉及学习 Linux 时,了解其基本原理和核心概念是至关重要的。Linux 是一种开源操作系统,广泛应用于服务器、嵌入式系统以及个人计算机中。它的灵活性、稳定性和安全性使得它成为许多 IT 专业人士和开发人员的首选。 第一步:了解基本概念和特…

CC连接过程

1、CC线连接过程 DFP和UFP会实时监控CC1和CC2引脚的电压,来评估DFP和UFP是否都已经在位。同时DFP可以根据电压确定自己所能提供的电流的大小 2、连接过程 Source端使用一个MOS管去控制Vbus,初始状态下,FET为关闭状态,Vbus不通。S…

苍穹外卖问题记录(持续更新)

Day01_3.2.4前后端联调 1. 前端无法登录 (1)确保nginx服务器已经启动 (2)查看自己数据库的用户名和密码是否和老师的一样,不一样的话需要在application-dev.yml文件中把老师的用户名密码修改成自己的 老师的用户名…

单⽬相机成像过程_看这一篇就够了

单⽬相机成像过程:看这一篇就够了 附赠宝贵的全套自动驾驶学习资料: 资料链接 附赠宝贵的全套自动驾驶学习资料: 资料链接

开发反应式API

开发反应式API 开发反应式API1 使用SpringWebFlux1.1 Spring WebFlux 简介1.2 编写反应式控制器 2 定义函数式请求处理器3 测试反应式控制器3.1 测试 GET 请求3.2 测试 POST 请求3.3 使用实时服务器进行测试 4 反应式消费RESTAPI4.1 获取资源4.2 发送资源4.3 删除资源4.4 处理错…

107. 如何使用Docker以及Docker Compose部署Go Web应用

文章目录 一、为什么需要Docker?二、Docker部署示例1. 准备代码2. 创建Docker镜像3. 编写Dockerfile4. Dockerfile解析5. 构建镜像6. 通过镜像创建容器运行 三、分阶段构建示例四、附带其他文件的部署示例五、关联其他容器六、Docker Compose模式七、总结 本文将介绍…

49、东北大学、阿尔伯塔大学:MVS-GCN多视角脑区、具有先验脑结构学习的图模型[GCN六元理论识别所有EEG!]

本文由东北大学医学图像智能计算教育部重点实验室&#xff0c;加拿大阿尔伯塔大学于2022年1.19日发表于<Computers in Biology and Medicine> JCR\IF: Q1\7.7 Abstract&#xff1a; 目的:近年来&#xff0c;脑功能网络(FBN)已被用于神经系统疾病的分类&#xff0c;如自…

力扣题目训练(21)

2024年2月14日力扣题目训练 2024年2月14日力扣题目训练605. 种花问题617. 合并二叉树628. 三个数的最大乘积289. 生命游戏299. 猜数字游戏149. 直线上最多的点数 2024年2月14日力扣题目训练 2024年2月14日第二十一天编程训练&#xff0c;今天主要是进行一些题训练&#xff0c;…

【智能算法】人工水母搜索算法(JS)原理及实现

目录 1.背景2.算法原理2.1算法思想2.2算法过程 3.代码实现4.参考文献 1.背景 2020年&#xff0c;Chou 等人受到水母运动行为启发&#xff0c;提出了人工水母搜索算法(Artificial Jellyfish Search Optimizer, JS)。 2.算法原理 2.1算法思想 JS模拟了水母的搜索行为&#xf…

关于OPC-UA客户端调用服务端方法CallMethod节点的问题

在OpcUaClient中可以通过CallMethodByNodeId调用方法节点 //// 摘要:// call a server method//// 参数:// tagParent:// 方法的父节点tag//// tag:// 方法的节点tag//// args:// 传递的参数//// 返回结果:// 输出的结果值public object[] CallMetho…

栈与队列|232.用栈实现队列

力扣题目链接 class MyQueue { public:stack<int> stIn;stack<int> stOut;/** Initialize your data structure here. */MyQueue() {}/** Push element x to the back of queue. */void push(int x) {stIn.push(x);}/** Removes the element from in front of que…

数据结构--线性表

1.线性表的定义&#xff1a; 存在唯一的一个被称为“第一个”的数据元素&#xff1b; 存在唯一的一个被称为“最后一个”的数据元素&#xff1b; 除第一个之外&#xff0c;集合中的每一个数据元素都只有一个前驱&#xff1b; 除最后一个之外&#xff0c;集合中的每一个数据…

大话设计模式——7.抽象工厂模式(Abstract Factory Pattern)

1.介绍 抽象工厂模式是工厂模式的进一步优化&#xff0c;提供一个创建一系列相关或相互依赖对象的接口&#xff0c;而无需指定它们具体的类。属于创建型模式。 UML图&#xff1a; 2.示例 车辆制造工厂&#xff0c;不仅可以制造轿车也可以用来生产自行车。 1&#xff09;Abs…

vivado 逻辑优化约束、功率优化、Vivado Tools电源优化

逻辑优化约束 逻辑保护 Vivado设计套件在逻辑优化过程中尊重DONT_TOUCH属性。确实如此不优化具有这些特性的离开网或单元。为了加快网络选择过程&#xff0c;网络具有DONT_TOUCH的属性被预过滤并且不被考虑用于物理优化。对于有关详细信息&#xff0c;请参阅《Vivado Design …

10、MongoDB -- MongoDB 的 MongoTemplate 的功能和用法介绍

目录 MongoTemplate 的功能和用法演示前提&#xff1a;登录单机模式的 mongodb 服务器命令登录【test】数据库的 mongodb 客户端命令登录【admin】数据库的 mongodb 客户端命令 为 MongoDB 提供的两个 Starterspring-boot-starter-data-mongodb&#xff08;为以同步方式操作 Mo…