[语义分割]基于VGG网络搭建FCN-8s并在VOC2012数据集上训练

2023-11-11

1.数据集选取

1.1数据集简介

本次训练选取PASCAL-VOC2012数据集,更详细的信息请访问

官网:http://host.robots.ox.ac.uk/pascal/VOC/voc2012/index.html

Kaggle:https://www.kaggle.com/huanghanchina/pascal-voc-2012

VOC2012用于语义分割的数据集分为20类对象+1类背景,原始的数据集包含了除分割外的分类+检测+共一万多张图片,但本次任务我们只需要语义分割的那一部分数据。

1.2 数据预处理

本次任务的标签位于VOC2012\SegmentationClass路径下,和图像识别任务不同的是,图像识别中一张图像就对应一个Label,而语义分割任务需要对一张图像实现像素级别的分类,因此分割任务是一个像素对应一个Lable,并且一张图像上还不止一个label,这样一来我们对于标签的标注方式就不能简单的像图像识别一样,可以仅通过文件的命名以体现不同图像所属的类别,而需要对图像中的每一个类别进行手动的标注,类别内的每一个像素均属于该类别。

好在VOC2012数据集为我们提供了标注好的标签,我们需要做的只是对标签进行一些细节上的处理。

1.2.1踩坑记录1

我们可以先试着读取一张标签,看看标签的存储方式:
在这里插入图片描述

'''for test'''
from PIL import Image
import matplotlib.pyplot as plt
img = Image.open('VOC2012/SegmentationClass/2007_000032.png')
print(np.array(img).shape)
plt.imshow(img)
plt.show()

[Out]: (281, 500)

可以看到输出尺寸是一个二维矩阵,说明标签的存储方式为”单通道“,但是通过imshow我们又可以发现,图片其实具有四个通道(右下角),好像又是RGBA的形式:
在这里插入图片描述

这着实让我一时半会摸不着头脑,于是我就按照RGBA->RGB的形式对图像进行处理:

#将图像转换为RGB形式(4通道->3通道)
img = Image.open('VOC2012/SegmentationClass/2007_000032.png').convert('RGB')

并自定义了将RGB图像转为灰度标签的函数(最后根本用不着):

#标注数据中每种颜色对应的类别:
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],
]


	#将颜色转换为类别:
def image2label(image, colormap):
	image = np.array(image, dtype = 'int64') # image.shape = (320, 480, 3)
	cm2lbl = np.zeros(3000) 
	for label, color in enumerate(colormap):
		# 创建哈希表存储原图颜色序列
		cm2lbl[(color[0]+color[1]*8+color[2]*2)] = label
		#print(color[0]*256+color[1]*256+color[2])
		#print(cm2lbl)
	#print(np.sum(cm2lbl != np.zeros(3000)))
	# rgb三通道合并(简单粗暴的三通道相加)
	ix = (image[:,:,0]+image[:,:,1]*8+image[:,:,2]*2) # ix.shape = (320, 480)
	#从哈希表中,将颜色序列转换为对应的标签
	image2 = cm2lbl[ix]
	return image2 # image2.shape = (320, 480)

但是最后又想了想感觉哪里不对,二维的尺寸就应该是标签的形式,于是乎就想着输出标签的一行看看:

img = Image.open('VOC2012/SegmentationClass/2007_000032.png') 
print(np.array(img)[100])

发现矩阵里的元素的确是标签形式(背景0,边缘255, 其余1~20)。。。

最后通过查阅资料才发现,VOC2012语义分割的标签存储模式是P-Mode,而不是我们熟知的RGB(可以print看看):

print(img)

[Out] : <PIL.PngImagePlugin.PngImageFile image mode=P size=500x281 at 0x217DB9D7AC8>

而plt在imshow这类格式的图像又会自动处理成RGBA格式。因此imshow的时候就有三个通道。

谜题终于揭晓,关于P Mode格式不是重点,我们只需要把它看成单通道标签处理就行,因此上述的image2label函数根本用不着(先留着说不定哪天又会用到)。

1.2.2 读取图片路径

由于VOC2012数据集并不都用于语义分割,因此一万多张图片里有一些数据是我们需要舍弃的。在数据集里的\ImageSets\Segmentation里的txt文档描述了哪些数据可以用作语义分割:

在这里插入图片描述

在这里我们定义一个函数用于筛选出这些数据作为我们的训练集与验证集:

# 读取图片路径         路径     
def read_image_path(root):
	# 读取文档
	image = np.loadtxt(root, dtype = str)
	n = len(image) # 数据集尺寸
	data, label = [None]*n, [None]*n
	for i, fname in enumerate(image):
		data[i] = 'VOC2012/JPEGImages/%s.jpg' %(fname)        # 数据集
		label[i] = 'VOC2012/SegmentationClass/%s.png'%(fname) # 标签
	return data, label
1.2.3 自定义图像增强与预处理模块

再次强调一遍,由于语义分割是像素级别的分类,因此标签和原图必须完美的匹配,这时候如果使用transforms模块自带的数据增强方法,因为是随机方法,因此处理后就会导致图像和标签在像素上不匹配的情况,因此我们自定义图像增强方法:

# 增强                                    # 由于是全卷积网络,图像的大小固不固定无所谓
def rand_crop(data, label, high, width): # high, width为裁剪后图像的固定宽高(320x480)
	im_width, im_high = data.size
	#生成随机点位置
	left = np.random.randint(0, im_width - width)
	top = np.random.randint(0, im_high - high)
	right = left+width
	bottom = top+high
	#图像随机裁剪(图像和标签一一对应)
	data = data.crop((left,top, right, bottom))
	label = label.crop((left,top, right, bottom))

	#图像随机翻转(图像和标签一一对应)
	angle = np.random.randint(-15,15)
	data = data.rotate(angle) # 逆时针旋转
	label = label.rotate(angle) # 逆时针旋转
	return data, label


# 预处理
def img_transforms(data, label, high, width):
	data, label = rand_crop(data, label, high, width)
	data_tfs = transforms.Compose([
		transforms.ToTensor(),
        #标准化,据说这6个参数是在ImageNet上百万张数据里提炼出来的,效果最好
		transforms.Normalize(mean = [0.485, 0.456, 0.406],std = [0.229, 0.224, 0.225]), 
		])
	data = data_tfs(data)
    
	label = torch.from_numpy(np.array(label))
	return data, label

1.3自定义数据集类

如何在PyTorch中自定义数据集类在我的上一篇博客已经做了详细的介绍,方法大同小异:传送地址

在这里我直接贴上代码,值得注意的是,为了防止rand_crop函数越界报错,本次我们添加了一个过滤方法用来过滤掉图像尺寸小于指定size的图像:

#自定义数据集:
class MyDataset(Data.Dataset):
	def __init__(self, data_root, high, width):
		self.data_root = data_root
		self.high = high
		self.width = width
		self.imtransform = img_transforms
		data_list, label_list = read_image_path(root = data_root)
		self.data_list = self.filter(data_list)
		self.label_list = self.filter(label_list)


	def __getitem__(self, idx):
		img = self.data_list[idx]
		label = self.label_list[idx]
		img = Image.open(img)
		label = Image.open(label)#.convert('RGB')
		img, label = self.imtransform(img, label, self.high, self.width)
		return img, label

	def __len__(self):
		return len(self.data_list)


	# 过滤掉图像尺寸小于high,width 的图像
	def filter(self, images):
		return [im for im in images if (Image.open(im).size[1] > self.high and Image.open(im).size[0] > self.width)]
1.3.1数据标签可视化

最后我们可以试着输出一个batch_size的图片看看效果如何。

BATCHSIZE = 8

voc_train = MyDataset("VOC2012/ImageSets/Segmentation/train.txt",high, width)
train_loader = Data.DataLoader(voc_train, batch_size = BATCHSIZE, shuffle = True)

for step, (b_x, b_y) in enumerate(train_loader):
    if(step > 0):
        break
    #可视化一个batch的图像,检查数据预处理是否正确:
    b_x_numpy = b_x.data.numpy()
    b_x_numpy = b_x_numpy.transpose(0,2,3,1)
    b_y_numpy = b_y.data.numpy()
    plt.figure(figsize = (16,3))

    for ii in range(BATCHSIZE):
        plt.subplot(2,BATCHSIZE,ii+1)
        plt.imshow(inv_normalize_image(b_x_numpy[ii]))#(320, 480, 3)
        plt.axis('off')
        plt.subplot(2,BATCHSIZE,ii+9)
        plt.imshow(label2image(b_y_numpy[ii]))
        plt.axis('off')
    plt.subplots_adjust(wspace = 0.1, hspace = 0.1)
    plt.show()

在这里插入图片描述

可视化首先要将类别转化为RGB信息:

#将标签转化为图像
def label2image(prelabel):
    h,w = prelabel.shape
    prelabel = prelabel.reshape(h*w, -1)
    image = np.zeros((h*w
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

[语义分割]基于VGG网络搭建FCN-8s并在VOC2012数据集上训练 的相关文章

  • FlutterUI(二)Canvas 与 Paint

    Flutter自定义控件分为三大类 组合控件 通过组合其他widget成为一个新的widget 自绘控件 通过使用canvas与paint来完全绘制 继承widget 使用RenderObject来绘制 但最终还是使用canvas来绘制 本
  • 看透react源码之感受react的进化

    写在前面 网上有许多关于react源码解读的文章 其中有很多都只是单纯贴源码 罗列变量名 其实大家都知道这个英文怎么读 直译也大概知道意思 但是这个英文在react中起到什么作用 并没有说的很通俗明白 对于刚刚接触源码或者想要了解react
  • VMware16调整了路径后界面全部变成了英文

    VMware调整了安装的路径后 界面全部变成了英文 查询了messages下的设置没发现问题 依然有zh CN 检查了本机的 区域设置 改回 中国 再启动VM 但是还是英文的 在 控制面板 卸载程序 运行VM后 进行更改 完成后恢复成中文
  • 【基于随机化的非确定性算法】模拟退火学习笔记

    暑假zky学长讲了模拟退火 现在正式来更一发学习笔记 这次不口胡直接正文 gt w lt 线 割 分 是 我 模拟退火 Simulated Annealing 简称SA 是一种通用概率算法 用来在一个大的搜寻空间内找寻命题的最优解 这是小学
  • 给 Android 开发者的 RxJava 详解

    http gank io post 560e15be2dca930e00da1083
  • 软考中级数据库系统工程师备考详细资料

    1 考试介绍 计算机技术与软件专业技术资格 水平 考试 以下简称计算机软件资格考试 是原中国计算机软件专业技术资格和水平考试 简称软件考试 的完善与发展 计算机软件资格考试是由国家人力资源和社会保障部 工业和信息化部领导下的国家级考试 其目
  • 搜索功能测试点汇总

    前提 1 明确搜索入口 2 明确搜索条件 3 明确搜索逻辑 一 界面测试 搜索框UI显示正常 布局合理 搜索框默认的搜索icon 末尾处的X按钮等等 搜索页面布局合理 无错别字 搜索出的结果展示 布局合理 已查看过的结果 是否要做特殊 如置
  • cloudstack guestnetwork vpc ingress/ergess介绍

    cloudstack的advance网络中可以创建的network如下 guestnetwork IsolatedNetwork vpc vpnCustomer gateway 这个应该不算一个网络 只是连接点 1 guestnetwork
  • mac下eclipse配置tomcat

    1 到 apache官方主页 http tomcat apache org 下载 Mac 版本的完整 tar gz文件包 解压拷贝到 Library 目录下 并命名为Tomcat 其他目录也可以 我这就以 Library做讲解 2 打开终端
  • 基于Java API 方式使用Java kafka在IDEA创建依赖

    在idea创建工程Maven 在pom xml添加如下依赖
  • Java编写的图书管理系统,窗体版本-003

    今天为大家分享一个java语言编写的图书管理程序 003 目前系统功能已经很全面 后续会进一步完善 整个系统界面漂亮 有完整得源码 希望大家可以喜欢 喜欢的帮忙点赞和关注 一起编程 一起进步 开发环境 开发语言为Java 开发环境Eclip
  • 数据库第十章——数据库恢复技术

    第十章 数据库恢复技术 文章目录 第十章 数据库恢复技术 一 事务的基本概念 一 基本概念 二 特性 二 数据库恢复概述 三 故障的种类 四 恢复的实现技术 如何建立冗余数据 一 数据转储 二 登记日志文件 五 恢复策略 如何利用冗余数据进
  • ruoyi cloud 用官方自带的工具更换包名出现的问题与解决办法

    使用ruoyi cloud官方的包生成后 有2点的修改很重要 1是所有带META INF spinrg文件夹的org springframework boot autoconfigure AutoConfiguration imports文
  • oracle10g异常日志查看

    oracle10g异常日志查看 警告日志 oracle product 10 2 0 db 1 admin orcl bdump alert orcl log 监听日志 oracle product 10 2 0 db 1 NETWORK
  • SpringMVC:从入门到精通,7篇系列篇带你全面掌握--三.使用SpringMVC完成增删改查

    Welcome Huihui s Code World 接下来看看由辉辉所写的关于SpringMVC的相关操作吧 目录 Welcome Huihui s Code World 效果演示 一 导入项目的相关依赖 二 添加框架的配置文件 gen
  • 高效的公式提取神器Mathpix snipping Tool+ Mathtype

    推荐一个有用高效的公式提取神器Mathpix snipping Tool Mathtype Mathpix snip是一款功能强大 很有用的公式识别及复制软件 能够将已有的PDF或CAJ等文中的公式 纸上打印的公式 甚至在纸上手写的公式统统
  • 共享计算机后防火墙能开启,Windows XP中防火墙后如何实现共享

    通过开启Windows XP系统中内置的 Internet 连接防火墙 可以让我们安心的上网冲浪 但是在开启了 Internet 连接防火墙 之后 我们就会发现不能正常的使用 网络共享 功能了 Internet 连接防火墙 在阻挡恶意程序的
  • C语言将int类型存入char型

    最近在做算法题的时候遇到了一个问题 就是怎么将int类型的值变成当成字符串 字符数组 类型 例如 有个 int 1024 如何将整形的1024转为字符串类型 String 的1024或者字符数组 char 类型的1024呢 其实可以用ito
  • Vscode快速入门、 插件安装、插件位置、修改vscode默认引用插件的路径、在命令行总配置code、快捷键

    Vscode快速入门 这里写目录标题 安装 插件安装 Ctrl Shift X 插件商店 插件位置 默认位置 修改默认路径 修改vscode默认引用插件的路径 在命令行总配置code 基本操作 安装 Visual Studio Code 官
  • RxJava2+Retrofit2+RxLifecycle3+OkHttp3网络请求封装(动态演示)

    入职公司后 公司要求组件化开发 经过讨论后我将网络请求框架单独进行了封装 不过当时框架里将常用的 util 和 ui 均放入到了共同的 Common 包下 导致里面部分代码耦合 后来为了降低耦合性又将 Common 拆分为了lib comm

随机推荐

  • Python 解决百钱买百鸡问题

    我国古代数学家张丘建在 算经 一书中曾提出过著名的 百钱买百鸡 问题 该问题叙述如下 鸡翁一 值钱五 鸡母一 值钱三 鸡雏三 值钱一 百钱买百鸡 则翁 母 雏各几何 翻译过来 意思是公鸡一个五块钱 母鸡一个三块钱 小鸡三个一块钱 现在要用一
  • Django开发员工管理系统(Part I)

    文章目录 1 准备工作 1 1 创建django项目 1 2 创建app 1 3 配置settings py文件 完成app注册 2 设计数据库表结构 3 在MySQL中生成表 3 1 创建数据库 3 2 修改配置文件 连接MySQL数据库
  • Nature:为啥室温超导支棱不起来

    克雷西 发自 凹非寺量子位 公众号 QbitAI 引发全球热议的LK 99风波告一段落后 Nature的一篇资讯头条再次提及了 室温超导 尽管对超导的热情一直不减 但随着一次又一次被证伪 人们很难不对 室温超导 慎之又慎 Nature的这篇
  • GitHub开源:狗屁不通文章生成器

    万字申请 废话报告 魔幻形式主义大作怎么写 GitHub开源狗屁不通文章生成器了解一下 只要输入一句话 系统就会给你一篇万字长文 查看源代码编写风格清新脱俗 并且毫无算法 简单暴力 直接在关键语句前后加上废话 名人名言 GitHub Git
  • 关系数据库中连接池的机制是什么?

    前提 为数据库连接建立一个缓冲池 1 从连接池获取或创建可用连接 2 使用完毕之后 把连接返回给连接池 3 在系统关闭前 断开所有连接并释放连接占用的系统资源 4 能够处理无效连接 限制连接池中的连接总数不低于或者不超过某个限定值 其中有几
  • 模式识别之分类器

    常见分类器介绍 1 SVM分类器 监督学习分类器 答 训练样本必须先标识不同类别 然后进行训练 SVM算法就是找一个超平面 对于已经被标记的训练样本 SVM训练得到一个超平面 使得两个类别训练集中距离超平面最近的样本之间的垂直距离要最大 也
  • Java--Map和HashMap基础

    一 Map常用方法 1 Map集合在 java util Map 包下 Map集合以键值对 key和value 的方式存储数据 key和value都是引用数据类型 都是存储对象的内存地址 2 Map接口中常用方法 V put K key V
  • W3C?什么是W3C相关标准?

    什么是W3C标准 什是W3C标准 不是一个标准 而是万维网联盟制定的一系列标准 网页主要由三部分组成 结构 Structure 表现 Presentation 和行为 Behavior 对应的标准也分三方面 结构化标准语言主要包括XHTML
  • 数据采集+数据可视化练习(2022-1-6)

    任务书3 赛题说明 竞赛内容分布 竞赛时长 任务一 Spark 组件部署管理 Standalone 模式 15 任务二 数据采集 20 任务三 数据清洗与分析 30 任务四 数据可视化 20 任务五 综合分析 10 团队分工明确合理 操作规
  • Python-Django毕业设计信息安全风险评估系统设计与实现(程序+Lw)

    项目运行 环境配置 Jdk1 8 Tomcat7 0 Mysql HBuilderX Webstorm也行 Eclispe IntelliJ IDEA Eclispe MyEclispe Sts都支持 项目技术 SSM mybatis Ma
  • CentOs yum源配置

    yum 的理念是使用一个中心仓库 repository 管理一部分甚至一个distribution 的应用程序相互关系 根据计算出来的软件依赖关系进行相关的升级 安装 删除等等操作 减少了Linux 用户一直头痛的dependencies
  • 通过opencv与神经网络对滑动验证码的一次深入学习

    好久没写博客了 人到中年 有点儿犯懒 从信息安全行业 又去了IT合规领域 与信息安全结合还是两手抓 两手都不硬 由于工作原因 需要获取一个token来请求接口 奈何没有现成的接口 需要在web端登录才可以获取 既然如此 想要实现这个功能肯定
  • 【LeetCode解题报告】《算法基础009_算术基本定理》- Java

    目录 一 507 完美数 1 题目 2 分析 3 代码 二 263 丑数 1 题目 2 分析 3 代码 一 507 完美数 1 题目 507 完美数 对于一个 正整数 如果它和除了它自身以外的所有 正因子 之和相等 我们称它为 完美数 给定
  • PHP通过URL远程下载图片到本地

    一 业务场景 我们需要远程将微信提供接口生成的临时二维码图片下载下来之后使用本地服务器去访问图片并存储在服务器数据库作为记录 此方法同样可以帮助你爬取网上一些公开数据 如cdnjs css 所需参数 公网能够访问到的图片 文件 地址 二 代
  • Source Insight给Linux内核创建工程

    所有文档请关注公众号 一口Linux 后台回复 ubuntu linux驱动视频同步更新到 https live bilibili com 22719960 一 Source Insight安装 1 预先准备好 Source Insight
  • ubuntu 文件删除后磁盘没有释放

    磁盘满了 删除文件后df发现没有变化 base root xddz df h Filesystem Size Used Avail Use Mounted on udev 32G 0 32G 0 dev tmpfs 6 3G 2 8M 6
  • 在JDBC连接池中启动Oracle RAC的TAF

    Oracle RAC 的一个负责故障切换处理的主要组件是透明应用程序故障切换 TAF 选件 下面列举通过JDBC实现的透明应用程序故障切换的代码 more Tele zhou Class forName oracle jdbc driver
  • RabbitMq结合springBoot实现延时任务

    简介 rabbitMQ延时任务的实现思想 rabbitmq实现延时任务本质就是使用 过期时间 和 死信队列 实现的 首先定义一个死信队列和死信队列的消费者 这个死信队列用来接收延时队列过期的消息 死信队列消费者用来接收到过期消息后就进行消费
  • FFmpeg中调用av_read_frame函数导致的内存泄漏问题

    使用FFmpeg的av read frame函数后 每读完一个packet 必须调用av packet unref函数进行内存释放 否则会导致内存释泄漏 在vs 博主所用的ffmpeg版本是3 4 2 vs版本是vs2015 中编译运行如下
  • [语义分割]基于VGG网络搭建FCN-8s并在VOC2012数据集上训练

    文章目录 1 数据集选取 1 1数据集简介 1 2 数据预处理 1 2 1踩坑记录1 1 2 2 读取图片路径 1 2 3 自定义图像增强与预处理模块 1 3自定义数据集类 1 3 1数据标签可视化 2 搭建FCN 8s网络 2 1基础FC