接下来的几篇中,我将作为一个小白记录自己在图像语义分割领域实战的步骤和问题。
VOC数据集下载
VOC2012中一共有10000+图,但并不都用于分割任务,有的用以物体标识或者动作识别等。所谓其增强版就是指联合了SBD数据集(Semantic Boundaries Dataset and Benchmark),一般放在benchmark Release文件夹里。
Pascal VOC官网:http://host.robots.ox.ac.uk/pascal/VOC/
SBD官网:http://home.bharathh.info/pubs/codes/SBD/download.html
这里再提供一下网盘下载地址,SBD
PASCAL VOC下载后的目录如下:
+ VOCdevkit
+ VOC2012
+ Annotations
+ ImageSets
+ JPEGImages
+ SegmentationClass
+ SegmentationObject
SBD下载后的目录如下:
+ benchmark_RELEASE
+ cls
+ img
+ inst
+ tools
train.txt
val.txt
数据集介绍
PASCAL VOC 2012
VOC 2012数据集分为20类,算上背景一共21类,分别如下:
Person: person
Animal: bird, cat, cow, dog, horse, sheep
Vehicle: aeroplane, bicycle, boat, bus, car, motorbike, train
Indoor: bottle, chair, dining table, potted plant, sofa, tv/monitor
更详细的介绍可以查看该数据集的官网:http://host.robots.ox.ac.uk/pascal/VOC/voc2012/index.html,接下来主要介绍下载的目录中每个文件夹都是做什么的,我们主要用到下面加粗的文件目录。
Annotations: 这个文件夹内主要存放了数据的标签,里面包含了每张图片的bounding box信息,主要用于目标检测,这里不做过多介绍。
- ImageSets: ImageSets中的Segmentation目录下存放了用于分割的train, val, trainval数据集的索引。
- JPEGImages: 这里存放的就是JPG格式的原图,包含17125张彩色图片,但只有一部分(2913张)是用于分割的。
- SegmentationClass: 语义分割任务中用到的label图片,PNG格式,共2913张,与原图的每一张图片相对应。
- SegmentationObject: 实例分割任务用到的label图片,在语义分割中用不到,这里不详解介绍。
SBD
增强版的VOC跟原版没什么区别,只是增加了数据。下面还是一一介绍下载的文件夹中每个文件的作用。
- img: 增强版的原图,共11355张图片
- cls: 用于语义分割的label,共11355个.mat文件,每个.mat文件对应一张原图
- inst: 用于实例分割的label,也是11355个.mat文件
- tools: 3个用于数据转换的脚本,在后面数据转换时用到
- train.txt: 训练集索引
- val.txt: 验证集索引
数据集使用
大多数paper中使用的数据集是以上两个数据集的融合,因此,在这部分将要介绍如何融合以上两个数据集来训练。
数据转换
由于pascal voc 2012增强版的数据集的label是.mat格式的文件,需要将其转换为.png格式的图片。转化后的图片是8-bit的灰度图。
1)在benchmark_RELEASE目录下创建一个名为cls_png的目录用于存放转化后的png图片
2)在benchmark_RELEASE目录下执行mat2png.py脚本
python tools/mat2png.py cls cls_png
原始pascal voc 2012数据集中label为三通道RGB图像,为了统一,我们也将其转化为8-bit的灰度png图像。
1)在VOCdevkit/VOC2012目录下创建一个名为SegmentationClass_1D的文件夹用于存放转化后的图片
2)将benchmark_RELEASE/tools目录下的convert_labels.py和utils.py脚本拷贝到VOCdevkit/VOC2012目录下,并执行convert_labels.py脚本
python convert_labels.py SegmentationClass ImageSets/Segmentation/trainval.txt SegmentationClass_1D
数据融合
现在,我们将原始的PASCAL VOC 2012数据集和增强版的数据集合并到一起。目前已有数据文件如下
VOCdevkit/VOC2012为原始PASCAL VOC 2012数据集
- images数据集的文件名为:JPEGImages,共17125张图片(其中2913张用于分割)
- labels数据集文件名为:SegmentationClass_1D,共2913张图片
benchmark_RELEASE为增强数据集
- images数据集的文件名为:img,共11355张图片
- labels数据集文件名为:cls_png,共11355张图片
1)在VOC2012目录下创建一个move_imgs.py的文件,用于转移图片,进行融合,并且会替代重复图片
2)在VOC2012目录下运行move_imgs.py的脚本
python move_imgs.py JPEGImages ImageSets/Segmentation/trainval.txt ../../benchmark_RELEASE/img
既可以将VOC2012中用于分割的原图片转移到SBD中进行融合
python move_imgs.py SegmentationClass_1D ImageSets/Segmentation/trainval.txt ../../benchmark_RELEASE/cls_png
即可以将VOC2012中用于分割的标签图转移到SBD中进行融合
move_imgs.py的代码如下:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2020/7/9 下午2:49
# @Author : Chen Lin
# @Email : chlin@mail.ustc.edu.cn
# @File : move_imgs.py
import os
import sys
import shutil
def main():
# img_path = 'JPEGImages'
# list_file = 'ImageSets/Segmentation/trainval.txt'
# moved_path = '../../benchmark_RELEASE/img'
img_path,list_file,moved_path = process_arguments(sys.argv)
move_file(img_path,list_file,moved_path)
def move_file(img_path, list_file, moved_path):
img_list = open(list_file).readlines()
moved_list = os.listdir(moved_path)
for i, _ in enumerate(img_list):
img_list[i] = img_list[i].split('\n')[0]
print(img_list, '\n', len(img_list), img_list[0])
if 'JPEG' in img_path:
for file in img_list:
file_path = os.path.join(img_path, file + '.jpg') # 路径拼接成绝对路径
if os.path.isfile(file_path): # 如果是文件,就打印这个文件路径
if file + '.jpg' in moved_list:
print('{}已经存在'.format(file+'.jpg'))
os.remove(os.path.join(moved_path, file + '.jpg'))
shutil.copy(file_path, moved_path)
print("移动文件成功!")
elif 'Class' in img_path:
for file in img_list:
file_path = os.path.join(img_path, file + '.png') # 路径拼接成绝对路径
if os.path.isfile(file_path): # 如果是文件,就打印这个文件路径
if file + '.png' in moved_list:
print('{}已经存在'.format(file+'.png'))
os.remove(os.path.join(moved_path, file + '.png'))
shutil.copy(file_path, moved_path)
print("移动文件成功!")
def process_arguments(argv):
if len(argv) != 4:
help()
path = argv[1]
list_file = argv[2]
new_path = argv[3]
return path, list_file, new_path
def help():
print('Usage: python convert_labels.py PATH LIST_FILE NEW_PATH\n'
'PATH points to directory with segmentation image labels.\n'
'LIST_FILE denotes text file containing names of images in PATH.\n'
'Names do not include extension of images.\n'
'NEW_PATH points to directory where converted labels will be stored.'
, file=sys.stderr)
exit()
if __name__ == '__main__':
main()
重新创建文件夹
在Data文件夹中,即与VOCdevkit和benchmark_RELEASE同级的位置创建一个新文件夹ClassSegAug,将benchmark_RELEASE中融合完成的img和cls_png文件夹复制过来,并且分别重命名为imgs,labels文件夹
可以看到两个两个文件夹中此时应该分别拥有12301个文件
生成索引文件
接下来应该生成索引文件txt,方便训练时的数据读入,可以先把原先两个数据集中的train.txt和val.txt融合成新的txt文件。整个数据集可分为train, val, trainval, test。需要有索引文件来指定某个样本属于哪个集,因此最后还需要得到每个数据集的索引文件,可以写个简单的脚本生成。也可以在这里直接下载。https://pan.baidu.com/s/1e_dKDtwl3Gx7-qUsuot7yg 提取码:jn4x
最后附上参考博客: