找回密码
 立即注册
首页 业界区 业界 【语义分割专栏】先导篇:常用数据集(VOC、Camvid、City ...

【语义分割专栏】先导篇:常用数据集(VOC、Camvid、Cityscape、ADE20k、COCO)

洪势 前天 10:14
目录

  • 前言
  • mask模式
  • PASCAL-VOC2012

    • 下载
    • 数据集简介
    • 数据加载(dataloader)

  • CamVid

    • 下载
    • 数据集简介
    • 数据加载(dataloader)

  • Cityscape

    • 下载
    • 数据集简介
    • 数据集处理
    • 数据加载(dataloader)

  • ADE20K

    • 下载
    • 数据集简介
    • 数据加载(dataloader)

  • COCO2017

    • 下载
    • 数据集简介
    • 数据集处理
    • 数据加载(dataloader)

  • 结语
  • 参考内容

前言

本篇向大家介绍下语义分割任务中的常用的数据集。本文将会向大家介绍常用的一些数据集以及数据集的处理加载方式。本篇文章收录于语义分割专栏,如果对语义分割领域感兴趣的,可以去看看本专栏,会对经典的模型以及代码进行详细的讲解哦!其中会包含可复现的代码!
mask模式

在讲数据集前,首先向大家介绍一下我们语义标注文件的格式。
在语义分割中,标注文件一般都是P模式(调色板模式)或者是L模式(灰度模式)。如下图所示,左边就是L模式的图片展示,右边就是P模式的图片展示。
1.png

其实两种模式的内容是相同的,都是单通道的,但是其所表示的含义不同。P模式中的数字代表的是类别到调色板的映射,什么意思呢?就是8位最多有256个(0-255),其中每一个都映射了调色版中的一个颜色,当然最多也就只能映射256个颜色了,每个颜色代表了一个类别。P模式的标注图能够更直观的让我们看到图像的标注。而L模式中的数字代表的就是灰度值,同样的每个灰度值代表了一个类别。
我们可以通过如下方式来查看图像的模式:
  1. print(Image.open('image.png').mode)
复制代码
两者的读写也是不同的,对于L模式,我们用PIL或者cv2都是可以进行读取的,读灰度图模式即可,写的话直接保存即可:
  1. # 读方式一:
  2. label = cv2.imread(label_path, 0)
  3. # 读方式二:
  4. label = np.asarray(Image.open(label_path), dtype=np.int32)
  5. # 写方式一:
  6. cv2.imwrite('gray_image.png', gray_image)
  7. # 写方式二:
  8. gray_image.save('gray_image.png')
复制代码
对于P模式,我们只能用PIL库来进行处理(cv2库不支持P模式):
  1. #读
  2. label = np.asarray(Image.open(label_path), dtype=np.int32)
  3. #写
  4. def save_colored_mask(mask, save_path):
  5.     lbl_pil = Image.fromarray(mask.astype(np.uint8), mode="P")
  6.     colormap = imgviz.label_colormap()
  7.     lbl_pil.putpalette(colormap.flatten())
  8.     lbl_pil.save(save_path)
复制代码
不过我们也可能遇到RGB模式的标注文件了(很少很少,基本上不会,其实就是为了更直观的查看而已),就是我们日常中经常使用的图像,这个就需要在数据加载的时候将RGB的格式转成P模式或者L模式进行加载,要不然会出错。后续有个数据集就是这么处理的。对于三种模式的总结如下,应该还是比较一目了然的。(其实不管L模式还是P模式,我们可以用PIL.Image.open()统一读取的)
模式通道数每个像素的含义适用于常用读取方式备注P (Palette)1通道(索引)类别ID ➔ 查调色板得到颜色语义分割标注(类别索引型)PIL.Image.open()像素值是类别索引,调色板映射成RGBL (Luminance)1通道(灰度值)0~255 灰度值灰度图、深度图、标签图PIL.Image.open().convert('L') or cv2.imread(..., 0)直接表示亮度或类别ID,无调色板RGB3通道真实颜色(R,G,B各0~255)彩色图片、可视化图像cv2.imread() / PIL.Image.open().convert('RGB')每个像素是直接的颜色值PASCAL-VOC2012

下载

数据集名称:PASCAL-VOC2012
数据集下载地址:The PASCAL Visual Object Classes Challenge 2012 (VOC2012)
2.png

在这里下载哈,2GB的那个。
数据集简介

VOC2012 数据集是Pascal Visual Object Classes (VOC) 持续的竞赛和挑战的一部分,广泛用于图像分类、目标检测、语义分割等任务。VOC2012 数据集的语义分割任务包含20个类别,主要用于评估物体级别的分割精度。
数据特点

  • 图像数量:训练集有1,464张图像,验证集有1,449张图像,测试集有1,456张图像。
  • 类别:包括20个物体类别,如人、动物、交通工具、家具等,且每个图像都标注有相应的像素级标签。
  • 格式:每张图像都附有一个对应的标注图(标签图),其每个像素值对应物体类别的ID。
数据加载(dataloader)

VOC2012的标注就是P模式的
  1. import torch
  2. import numpy as np
  3. from PIL import Image
  4. from torch.utils.data import Dataset, DataLoader
  5. import os
  6. import random
  7. import torchvision.transforms as T
  8. VOC_CLASSES = [
  9.     'background','aeroplane','bicycle','bird','boat','bottle','bus',
  10.     'car','cat','chair','cow','diningtable','dog','horse',
  11.     'motorbike','person','potted plant','sheep','sofa','train','tv/monitor'
  12. ]
  13. VOC_COLORMAP = [
  14.     [0, 0, 0], [128, 0, 0], [0, 128, 0], [128, 128, 0],
  15.     [0, 0, 128], [128, 0, 128], [0, 128, 128], [128, 128, 128],
  16.     [64, 0, 0], [192, 0, 0], [64, 128, 0], [192, 128, 0],
  17.     [64, 0, 128], [192, 0, 128], [64, 128, 128], [192, 128, 128],
  18.     [0, 64, 0], [128, 64, 0], [0, 192, 0], [128, 192, 0], [0, 64, 128]
  19. ]
  20. class VOCSegmentation(Dataset):
  21.     def __init__(self, root, split='train', img_size=320, augment=True):
  22.         super(VOCSegmentation, self).__init__()
  23.         self.root = root
  24.         self.split = split
  25.         self.img_size = img_size
  26.         self.augment = augment
  27.         img_dir = os.path.join(root, 'JPEGImages')
  28.         mask_dir = os.path.join(root, 'SegmentationClass')
  29.         split_file = os.path.join(root, 'ImageSets', 'Segmentation', f'{split}.txt')
  30.         if not os.path.exists(split_file):
  31.             raise FileNotFoundError(split_file)
  32.         with open(split_file, 'r') as f:
  33.             file_names = [x.strip() for x in f.readlines()]
  34.         self.images = [os.path.join(img_dir, x + '.jpg') for x in file_names]
  35.         self.masks = [os.path.join(mask_dir, x + '.png') for x in file_names]
  36.         assert len(self.images) == len(self.masks)
  37.         print(f"{split} set loaded: {len(self.images)} samples")
  38.         self.normalize = T.Normalize(mean=[0.485, 0.456, 0.406],
  39.                                      std=[0.229, 0.224, 0.225])
  40.     def __getitem__(self, index):
  41.         img = Image.open(self.images[index]).convert('RGB')
  42.         mask = Image.open(self.masks[index])  # mask为P模式(0~20的类别)
  43.         # Resize
  44.         img = img.resize((self.img_size, self.img_size), Image.BILINEAR)
  45.         mask = mask.resize((self.img_size, self.img_size), Image.NEAREST)
  46.         # 转Tensor
  47.         img = T.functional.to_tensor(img)
  48.         mask = torch.from_numpy(np.array(mask)).long()  # 0~20
  49.         # 数据增强
  50.         if self.augment:
  51.             if random.random() > 0.5:
  52.                 img = T.functional.hflip(img)
  53.                 mask = T.functional.hflip(mask)
  54.             if random.random() > 0.5:
  55.                 img = T.ColorJitter(brightness=0.2, contrast=0.2, saturation=0.2, hue=0.2)(img)
  56.         img = self.normalize(img)
  57.         return img, mask
  58.     def __len__(self):
  59.         return len(self.images)
  60. def get_dataloader(data_path, batch_size=4, img_size=320, num_workers=4):
  61.     train_dataset = VOCSegmentation(root=data_path, split='train', img_size=img_size, augment=True)
  62.     val_dataset = VOCSegmentation(root=data_path, split='val', img_size=img_size, augment=False)
  63.     train_loader = DataLoader(train_dataset, shuffle=True, batch_size=batch_size, pin_memory=True, num_workers=num_workers)
  64.     val_loader = DataLoader(val_dataset, shuffle=False, batch_size=batch_size, pin_memory=True, num_workers=num_workers)
  65.     return train_loader, val_loader
复制代码
3.png

CamVid

下载

数据集名称:CamVid
数据集下载地址:Object Recognition in Video Dataset
4.png

在这里进行下载,CamVid数据集有两种,一种是官方的就是上述的下载地址的,总共有32种类别,划分的会更加的细致。但是一般官网的太难打开了,所以我们可以通过Kaggle中的CamVid (Cambridge-Driving Labeled Video Database)进行下载。
还有一种就是11类别的(不包括背景),会将一些语义相近的内容进行合并,就划分的没有这么细致,任务难度也会比较低一些。(如果你在网上找不到的话,可以在评论区发言或是私聊我要取)
数据集简介

CamVid 数据集主要用于自动驾驶场景中的语义分割,包含驾驶场景中的道路、交通标志、车辆等类别的标注图像。该数据集旨在推动自动驾驶系统在道路场景中的表现。
数据特点

  • 图像数量:包括701帧视频序列图像,分为训练集、验证集和测试集。
  • 类别:包含32个类别(也有包含11个类别的),包括道路、建筑物、车辆、行人等。
  • 挑战:由于数据集主要来自城市交通场景,因此面临着动态变化的天气、光照、交通密度等挑战
数据加载(dataloader)

CamVid我从kaggle中下载的就是RGB的mask图像,所以我们需要先将其转换为单通道mask图像(L模式)
  1. def mask_to_class(mask):
  2.     mask_class = np.zeros((mask.shape[0], mask.shape[1]), dtype=np.uint8)
  3.     for idx, color in enumerate(Cam_COLORMAP):
  4.         color = np.array(color)
  5.         # 每个像素和当前颜色匹配
  6.         matches = np.all(mask == color, axis=-1)
  7.         mask_class[matches] = idx
  8.     return mask_class
复制代码
故数据加载的代码为(以下为32类的,如果需要十一类改下Cam_CLASSES和Cam_COLORMAP即可):
  1. import osfrom PIL import Imageimport albumentations as Afrom albumentations.pytorch.transforms import ToTensorV2from torch.utils.data import Dataset, DataLoaderimport numpy as np# 32类Cam_CLASSES = ['Animal', 'Archway', 'Bicyclist', 'Bridge', 'Building', 'Car', 'CartLuggagePram', 'Child',               'Column_Pole', 'Fence', 'LaneMkgsDriv', 'LaneMkgsNonDriv', 'Misc_Text', 'MotorcycleScooter',               'OtherMoving', 'ParkingBlock', 'Pedestrian', 'Road', 'RoadShoulder', 'Sidewalk', 'SignSymbol',               'Sky', 'SUVPickupTruck', 'TrafficCone', 'TrafficLight', 'Train', 'Tree', 'Truck_Bus', 'Tunnel',               'VegetationMisc', 'Void', 'Wall']# 用于做可视化Cam_COLORMAP = [    [64, 128, 64], [192, 0, 128], [0, 128, 192], [0, 128, 64], [128, 0, 0],    [64, 0, 128], [64, 0, 192], [192, 128, 64], [192, 192, 128], [64, 64, 128],    [128, 0, 192], [192, 0, 64], [128, 128, 64], [192, 0, 192], [128, 64, 64],    [64, 192, 128], [64, 64, 0], [128, 64, 128], [128, 128, 192], [0, 0, 192],    [192, 128, 128], [128, 128, 128], [64, 128, 192], [0, 0, 64], [0, 64, 64],    [192, 64, 128], [128, 128, 0], [192, 128, 192], [64, 0, 64], [192, 192, 0],    [0, 0, 0], [64, 192, 0]]# 转换RGB mask为类别id的函数def mask_to_class(mask):
  2.     mask_class = np.zeros((mask.shape[0], mask.shape[1]), dtype=np.uint8)
  3.     for idx, color in enumerate(Cam_COLORMAP):
  4.         color = np.array(color)
  5.         # 每个像素和当前颜色匹配
  6.         matches = np.all(mask == color, axis=-1)
  7.         mask_class[matches] = idx
  8.     return mask_classclass CamVidDataset(Dataset):    def __init__(self, image_dir, label_dir):        self.image_dir = image_dir        self.label_dir = label_dir        self.transform = A.Compose([            A.Resize(448, 448),            A.HorizontalFlip(),            A.VerticalFlip(),            A.Normalize(),            ToTensorV2(),        ])        self.images = sorted(os.listdir(image_dir))        self.labels = sorted(os.listdir(label_dir))        assert len(self.images) == len(self.labels), "Images and labels count mismatch!"    def __len__(self):        return len(self.images)    def __getitem__(self, idx):        img_path = os.path.join(self.image_dir, self.images[idx])        label_path = os.path.join(self.label_dir, self.labels[idx])        image = np.array(Image.open(img_path).convert("RGB"))        label_rgb = np.array(Image.open(label_path).convert("RGB"))        # RGB转类别索引        label_class = mask_to_class(label_rgb)        # Albumentations 需要 (H, W, 3) 和 (H, W)        transformed = self.transform(image=image, mask=label_class)        return transformed['image'], transformed['mask']def get_dataloader(data_path, batch_size=4, num_workers=4):    train_dir = os.path.join(data_path, 'train')    val_dir = os.path.join(data_path, 'val')    trainlabel_dir = os.path.join(data_path, 'train_labels')    vallabel_dir = os.path.join(data_path, 'val_labels')    train_dataset = CamVidDataset(train_dir, trainlabel_dir)    val_dataset = CamVidDataset(val_dir, vallabel_dir)    train_loader = DataLoader(train_dataset, shuffle=True, batch_size=batch_size, pin_memory=True, num_workers=num_workers)    val_loader = DataLoader(val_dataset, shuffle=False, batch_size=batch_size, pin_memory=True, num_workers=num_workers)    return train_loader, val_loader
复制代码
5.png

Cityscape

下载

数据集名称:Cityscape
数据集下载地址:Download – Cityscapes Dataset
6.png

需要注册才能够登录,然后这三个都需要进行下载,因为后续我们数据处理的时候会要用到的。
其中leftImg8bit就是图片文件,gtFine就是精细标注的文件,gtCoarse就是粗略标注的文件。其实我们只需要用到的就是gtFine中的,但是我们后续数据处理的时候需要用到gtCoarse,要不然就会报错。
数据集简介

Cityscapes是一个专注于城市街道的语义分割数据集,特别适用于自动驾驶和城市环境中的语义分割任务。它提供了详细的像素级标注,涵盖了各种城市景观,如街道、建筑、交通信号灯等。
数据特点

  • 图像数量:包含5,000张高分辨率图像,其中包括2,975张训练图像,500张验证图像,1,525张测试图像。
  • 类别:包含30个类别,其中19个是常见的语义分割类别,如道路、人行道、建筑物、车辆等。
  • 挑战:数据集注重高分辨率图像(2048x1024),适用于复杂城市街道场景的分割任务。
数据集处理

下载好这三个文件之后,我们需要通过代码来生成标注,可以直接下载对应的库,也可以去github上下载对应的工具。
  1. pip install cityscapesscripts
复制代码
下载好之后进入preparation文件夹内找到createTrainIdLabelImgs.py文件
7.png

加上这么一句,你的CityScape地址,然后直接运行该文件即可。注意你的地址文件夹下面应该包含gtFine和gtCoarse两个文件夹。
  1. os.environ['CITYSCAPES_DATASET'] = r"your Cityscape"
复制代码
8.png

运行之后就可以直接生成标注文件了,注意这里生成的是19个类的标注文件,其实原gtFine文件夹中有标注文件的,只不过是33类别的。我们一般用到的都是19类别的。以labelids结尾的就是33类别的,labelTrainids结尾的就是我们刚刚生成的19类别的标准文件了。
9.png

然后我们将数据文件和标注整理下
  1. import os
  2. import random
  3. import shutil
  4. # 处理图片
  5. dataset_path = r"D:\博客记录\语义分割\data\Cityscape"
  6. # 原始的train, valid文件夹路径
  7. train_dataset_path = os.path.join(dataset_path, 'leftImg8bit/train')
  8. val_dataset_path = os.path.join(dataset_path, 'leftImg8bit/val')
  9. test_dataset_path = os.path.join(dataset_path, 'leftImg8bit/test')
  10. # 创建train,valid的文件夹
  11. train_images_path = os.path.join(dataset_path, 'train_images')
  12. val_images_path = os.path.join(dataset_path, 'val_images')
  13. test_images_path = os.path.join(dataset_path, 'test_images')
  14. # 处理标注
  15. # 原始的train_label, valid_label文件夹路径
  16. train_label_path = os.path.join(dataset_path, 'gtFine/train')
  17. val_label_path = os.path.join(dataset_path, 'gtFine/val')
  18. test_label_path = os.path.join(dataset_path, 'gtFine/test')
  19. # 创建train,valid的文件夹
  20. train_images_label_path = os.path.join(dataset_path, 'train_labels(19)')
  21. val_images_label_path = os.path.join(dataset_path, 'val_labels(19)')
  22. test_images_label_path = os.path.join(dataset_path, 'test_labels(19)')
  23. if os.path.exists(train_images_path) == False:
  24.     os.mkdir(train_images_path)
  25. if os.path.exists(val_images_path) == False:
  26.     os.mkdir(val_images_path)
  27. if os.path.exists(test_images_path) == False:
  28.     os.mkdir(test_images_path)
  29. if os.path.exists(train_images_label_path) == False:
  30.     os.mkdir(train_images_label_path)
  31. if os.path.exists(val_images_label_path) == False:
  32.     os.mkdir(val_images_label_path)
  33. if os.path.exists(test_images_label_path) == False:
  34.     os.mkdir(test_images_label_path)
  35. # -----------------移动文件夹-------------------------------------------------
  36. for file_name in os.listdir(train_dataset_path):
  37.     file_path = os.path.join(train_dataset_path, file_name)
  38.     for image in os.listdir(file_path):
  39.         shutil.copy(os.path.join(file_path, image), os.path.join(train_images_path, image))
  40. for file_name in os.listdir(val_dataset_path):
  41.     file_path = os.path.join(val_dataset_path, file_name)
  42.     for image in os.listdir(file_path):
  43.         shutil.copy(os.path.join(file_path, image), os.path.join(val_images_path, image))
  44. for file_name in os.listdir(test_dataset_path):
  45.     file_path = os.path.join(test_dataset_path, file_name)
  46.     for image in os.listdir(file_path):
  47.         shutil.copy(os.path.join(file_path, image), os.path.join(test_images_path, image))
  48.         
  49. for file_name in os.listdir(train_label_path):
  50.     file_path = os.path.join(train_label_path, file_name)
  51.     for image in os.listdir(file_path):
  52.         # 查找对应的后缀名,然后保存到文件中
  53.         if image.split('.png')[0][-13:] == "labelTrainIds":
  54.             # print(image)
  55.             shutil.copy(os.path.join(file_path, image), os.path.join(train_images_label_path, image))
  56. for file_name in os.listdir(val_label_path):
  57.     file_path = os.path.join(val_label_path, file_name)
  58.     for image in os.listdir(file_path):
  59.         if image.split('.png')[0][-13:] == "labelTrainIds":
  60.             shutil.copy(os.path.join(file_path, image), os.path.join(val_images_label_path, image))
  61. for file_name in os.listdir(test_label_path):
  62.     file_path = os.path.join(test_label_path, file_name)
  63.     for image in os.listdir(file_path):
  64.         if image.split('.png')[0][-13:] == "labelTrainIds":
  65.             shutil.copy(os.path.join(file_path, image), os.path.join(test_images_label_path, image))
复制代码
结果如下图所示(当然tese_labels(19)文件夹内的数据都是无效的):
10.png

数据加载(dataloader)

Cityscapes的标注图像是L模式的
  1. import os
  2. from PIL import Image
  3. import albumentations as A
  4. from albumentations.pytorch.transforms import ToTensorV2
  5. from torch.utils.data import Dataset, DataLoader
  6. import numpy as np
  7. CITYSCAPES_CLASSES = [
  8.     "road", "sidewalk", "building", "wall", "fence", "pole", "traffic light", "traffic sign", "vegetation",
  9.     "terrain", "sky", "person", "rider", "car", "truck", "bus", "train", "motorcycle", "bicycle","background",
  10. ]
  11. CITYSCAPES_COLORMAP = [
  12.     [128, 64, 128],    # road
  13.     [244, 35, 232],    # sidewalk
  14.     [70, 70, 70],      # building
  15.     [102, 102, 156],   # wall
  16.     [190, 153, 153],   # fence
  17.     [153, 153, 153],   # pole
  18.     [250, 170, 30],    # traffic light
  19.     [220, 220, 0],     # traffic sign
  20.     [107, 142, 35],    # vegetation
  21.     [152, 251, 152],   # terrain
  22.     [70, 130, 180],    # sky
  23.     [220, 20, 60],     # person
  24.     [255, 0, 0],       # rider
  25.     [0, 0, 142],       # car
  26.     [0, 0, 70],        # truck
  27.     [0, 60, 100],      # bus
  28.     [0, 80, 100],      # train
  29.     [0, 0, 230],       # motorcycle
  30.     [119, 11, 32], # bicycle
  31.     [0, 0, 0],# background
  32. ]
  33. class CityScapes(Dataset):
  34.     def __init__(self, image_dir, label_dir):
  35.         self.image_dir = image_dir
  36.         self.label_dir = label_dir
  37.         self.transform = A.Compose([
  38.             A.Resize(448, 448),
  39.             A.HorizontalFlip(),
  40.             A.VerticalFlip(),
  41.             A.Normalize(),
  42.             ToTensorV2(),
  43.         ])
  44.         self.images = sorted(os.listdir(image_dir))
  45.         self.labels = sorted(os.listdir(label_dir))
  46.         assert len(self.images) == len(self.labels), "Images and labels count mismatch!"
  47.     def __len__(self):
  48.         return len(self.images)
  49.     def __getitem__(self, idx):
  50.         img_path = os.path.join(self.image_dir, self.images[idx])
  51.         label_path = os.path.join(self.label_dir, self.labels[idx])
  52.         image = np.array(Image.open(img_path).convert("RGB"))
  53.         label = np.array(Image.open(label_path))
  54.         # Albumentations 需要 (H, W, 3) 和 (H, W)
  55.         transformed = self.transform(image=image, mask=label)
  56.         return transformed['image'], transformed['mask']
  57. def get_dataloader(data_path, batch_size=4, num_workers=4):
  58.     train_dir = os.path.join(data_path,'train_images')
  59.     val_dir = os.path.join(data_path,'val_images')
  60.     trainlabel_dir = os.path.join(data_path, 'train_labels(19)')
  61.     vallabel_dir = os.path.join(data_path, 'val_labels(19)')
  62.     train_dataset = CityScapes(train_dir, trainlabel_dir)
  63.     val_dataset = CityScapes(val_dir, vallabel_dir)
  64.     train_loader = DataLoader(train_dataset, shuffle=True, batch_size=batch_size, pin_memory=True, num_workers=num_workers)
  65.     val_loader = DataLoader(val_dataset, shuffle=False, batch_size=batch_size, pin_memory=True, num_workers=num_workers)
  66.     return train_loader, val_loader
复制代码
11.png

ADE20K

下载

数据集名称:ADE20K
数据集下载地址:ADE20K dataset
12.png

在这里进行下载。但是也需要注册什么的比较麻烦。
数据集简介

ADE20k是一个大规模的语义分割数据集,涵盖了各种日常场景,提供了广泛的类标注,用于评估图像分割算法的性能。
数据特点

  • 图像数量:数据集包含20K多张图像,其中包括训练集、验证集和测试集。
  • 类别:有150个语义类别,涵盖了物体、场景以及物体的一些具体部分(例如家具、道路、天空等)。
  • 挑战:ADE20k是一个多类别、多样化的数据集,标注了大量不同的对象类别,适用于大规模的语义分割研究。
数据加载(dataloader)

ADE20k的标注也是L模式的
  1. import os
  2. from PIL import Image
  3. import albumentations as A
  4. from albumentations.pytorch.transforms import ToTensorV2
  5. from torch.utils.data import Dataset, DataLoader
  6. import numpy as np
  7. ADE_CLASSES = [
  8.     "background", "wall", "building", "sky", "floor", "tree", "ceiling", "road", "bed", "windowpane",
  9.     "grass", "cabinet", "sidewalk", "person", "earth", "door", "table", "mountain", "plant", "curtain",
  10.     "chair", "car", "water", "painting", "sofa", "shelf", "house", "sea", "mirror", "rug",
  11.     "field", "armchair", "seat", "fence", "desk", "rock", "wardrobe", "lamp", "bathtub", "railing",
  12.     "cushion", "base", "box", "column", "signboard", "chest of drawers", "counter", "sand", "sink", "skyscraper",
  13.     "fireplace", "refrigerator", "grandstand", "path", "stairs", "runway", "case", "pool table", "pillow", "screen door",
  14.     "stairway", "river", "bridge", "bookcase", "blind", "coffee table", "toilet", "flower", "book", "hill",
  15.     "bench", "countertop", "stove", "palm", "kitchen island", "computer", "swivel chair", "boat", "bar", "arcade machine",
  16.     "hovel", "bus", "towel", "light", "truck", "tower", "chandelier", "awning", "streetlight", "booth",
  17.     "television receiver", "airplane", "dirt track", "apparel", "pole", "land", "bannister", "escalator", "ottoman", "bottle",
  18.     "buffet", "poster", "stage", "van", "ship", "fountain", "conveyer belt", "canopy", "washer", "plaything",
  19.     "swimming pool", "stool", "barrel", "basket", "waterfall", "tent", "bag", "minibike", "cradle", "oven",
  20.     "ball", "food", "step", "tank", "trade name", "microwave", "pot", "animal", "bicycle", "lake",
  21.     "dishwasher", "screen", "blanket", "sculpture", "hood", "sconce", "vase", "traffic light", "tray", "ashcan",
  22.     "fan", "pier", "crt screen", "plate", "monitor", "bulletin board", "shower", "radiator", "glass", "clock",
  23.     "flag"
  24. ]
  25. ADE_COLORMAP = [[0,0,0],
  26.     [120, 120, 120], [180, 120, 120], [6, 230, 230], [80, 50, 50], [4, 200, 3],
  27.     [120, 120, 80], [140, 140, 140], [204, 5, 255], [230, 230, 230], [4, 250, 7],
  28.     [224, 5, 255], [235, 255, 7], [150, 5, 61], [120, 120, 70], [8, 255, 51],
  29.     [255, 6, 82], [143, 255, 140], [204, 255, 4], [255, 51, 7], [204, 70, 3],
  30.     [0, 102, 200], [61, 230, 250], [255, 6, 51], [11, 102, 255], [255, 7, 71],
  31.     [255, 9, 224], [9, 7, 230], [220, 220, 220], [255, 9, 92], [112, 9, 255],
  32.     [8, 255, 214], [7, 255, 224], [255, 184, 6], [10, 255, 71], [255, 41, 10],
  33.     [7, 255, 255], [224, 255, 8], [102, 8, 255], [255, 61, 6], [255, 194, 7],
  34.     [255, 122, 8], [0, 255, 20], [255, 8, 41], [255, 5, 153], [6, 51, 255],
  35.     [235, 12, 255], [160, 150, 20], [0, 163, 255], [140, 140, 140], [250, 10, 15],
  36.     [20, 255, 0], [31, 255, 0], [255, 31, 0], [255, 224, 0], [153, 255, 0],
  37.     [0, 0, 255], [255, 71, 0], [0, 235, 255], [0, 173, 255], [31, 0, 255],
  38.     [11, 200, 200], [255, 82, 0], [0, 255, 245], [0, 61, 255], [0, 255, 112],
  39.     [0, 255, 133], [255, 0, 0], [255, 163, 0], [255, 102, 0], [194, 255, 0],
  40.     [0, 143, 255], [51, 255, 0], [0, 82, 255], [0, 255, 41], [0, 255, 173],
  41.     [10, 0, 255], [173, 255, 0], [0, 255, 153], [255, 92, 0], [255, 0, 255],
  42.     [255, 0, 245], [255, 0, 102], [255, 173, 0], [255, 0, 20], [255, 184, 184],
  43.     [0, 31, 255], [0, 255, 61], [0, 71, 255], [255, 0, 204], [0, 255, 194],
  44.     [0, 255, 82], [0, 10, 255], [0, 112, 255], [51, 0, 255], [0, 194, 255],
  45.     [0, 122, 255], [0, 255, 163], [255, 153, 0], [0, 255, 10], [255, 112, 0],
  46.     [143, 255, 0], [82, 0, 255], [163, 255, 0], [255, 235, 0], [8, 184, 170],
  47.     [133, 0, 255], [0, 255, 92], [184, 0, 255], [255, 0, 31], [0, 184, 255],
  48.     [0, 214, 255], [255, 0, 112], [92, 255, 0], [0, 224, 255], [112, 224, 255],
  49.     [70, 184, 160], [163, 0, 255], [153, 0, 255], [71, 255, 0], [255, 0, 163],
  50.     [255, 204, 0], [255, 0, 143], [0, 255, 235], [133, 255, 0], [255, 0, 235],
  51.     [245, 0, 255], [255, 0, 122], [255, 245, 0], [10, 190, 212], [214, 255, 0],
  52.     [0, 204, 255], [20, 0, 255], [255, 255, 0], [0, 153, 255], [0, 41, 255],
  53.     [0, 255, 204], [41, 0, 255], [41, 255, 0], [173, 0, 255], [0, 245, 255],
  54.     [71, 0, 255], [122, 0, 255], [0, 255, 184], [0, 92, 255], [184, 255, 0],
  55.     [0, 133, 255], [255, 214, 0], [25, 194, 194], [102, 255, 0], [92, 0, 255]
  56. ]
  57. class ADE20kDataset(Dataset):
  58.     def __init__(self, image_dir, label_dir):
  59.         self.image_dir = image_dir
  60.         self.label_dir = label_dir
  61.         self.transform = A.Compose([
  62.             A.Resize(448, 448),
  63.             A.HorizontalFlip(),
  64.             A.VerticalFlip(),
  65.             A.Normalize(),
  66.             ToTensorV2(),
  67.         ])
  68.         self.images = sorted(os.listdir(image_dir))
  69.         self.labels = sorted(os.listdir(label_dir))
  70.         assert len(self.images) == len(self.labels), "Images and labels count mismatch!"
  71.     def __len__(self):
  72.         return len(self.images)
  73.     def __getitem__(self, idx):
  74.         img_path = os.path.join(self.image_dir, self.images[idx])
  75.         label_path = os.path.join(self.label_dir, self.labels[idx])
  76.         image = np.array(Image.open(img_path).convert("RGB"))
  77.         label = np.array(Image.open(label_path))
  78.         # Albumentations 需要 (H, W, 3) 和 (H, W)
  79.         transformed = self.transform(image=image, mask=label)
  80.         return transformed['image'], transformed['mask']
  81. def get_dataloader(data_path, batch_size=4, num_workers=4):
  82.     train_dir = os.path.join(data_path,'images', 'training')
  83.     val_dir = os.path.join(data_path,'images', 'validation')
  84.     trainlabel_dir = os.path.join(data_path, 'annotations','training')
  85.     vallabel_dir = os.path.join(data_path, 'annotations','validation')
  86.     train_dataset = ADE20kDataset(train_dir, trainlabel_dir)
  87.     val_dataset = ADE20kDataset(val_dir, vallabel_dir)
  88.     train_loader = DataLoader(train_dataset, shuffle=True, batch_size=batch_size, pin_memory=True, num_workers=num_workers)
  89.     val_loader = DataLoader(val_dataset, shuffle=False, batch_size=batch_size, pin_memory=True, num_workers=num_workers)
  90.     return train_loader, val_loader
复制代码
13.png

COCO2017

下载

数据集名称:COCO2017
数据集下载地址:COCO - Common Objects in Context
14.png

下载我所框出来的三个文件,分别是训练图像,验证图像和标注文件。标注文件是json格式的,后续我们将会进行转换。
数据集简介

COCO2017 数据集是一个大规模的数据集,设计用于物体检测、分割和关键点检测等任务。COCO数据集特别注重“上下文”信息,提供了丰富的标注和不同尺度的物体实例。
数据特点

  • 图像数量:训练集包含118K张图像,验证集包含5K张图像,测试集包含20K张图像。
  • 类别:包括80个物体类别,如人、动物、交通工具、家具等。
  • 标注:除了物体检测和实例分割标注外,COCO还提供了分割掩码、关键点标注等。
  • 复杂性:COCO包含大量的遮挡、重叠物体、不同背景等,适合挑战性强的分割任务。
数据集处理

下载好三个文件之后,我们需要通过annotation中的instances_train2017和instances_val2017来转换获得我们的mask标注文件,我将其转换成了P模式的。
15.png

转换代码为:
  1. import os
  2. import numpy as np
  3. from pycocotools.coco import COCO
  4. from pycocotools import mask as maskUtils
  5. from PIL import Image
  6. from tqdm import tqdm
  7. import imgviz
  8. def coco_to_semantic_mask_pmode(coco_json_path, image_dir, save_mask_dir):
  9.     os.makedirs(save_mask_dir, exist_ok=True)
  10.     coco = COCO(coco_json_path)
  11.     img_ids = coco.getImgIds()
  12.     cat_ids = coco.getCatIds()
  13.     catid2label = {cat_id: i+1 for i, cat_id in enumerate(cat_ids)}  # +1保留0为背景
  14.     colormap = imgviz.label_colormap()  # 得到颜色映射
  15.     for img_id in tqdm(img_ids):
  16.         img_info = coco.loadImgs(img_id)[0]
  17.         ann_ids = coco.getAnnIds(imgIds=img_id)
  18.         anns = coco.loadAnns(ann_ids)
  19.         h, w = img_info['height'], img_info['width']
  20.         mask = np.zeros((h, w), dtype=np.uint8)
  21.         for ann in anns:
  22.             cat_id = ann['category_id']
  23.             label = catid2label[cat_id]
  24.             rle = coco.annToRLE(ann)
  25.             m = maskUtils.decode(rle)
  26.             mask[m == 1] = label
  27.         # 保存成P模式 (带调色板)
  28.         mask_img = Image.fromarray(mask, mode='P')
  29.         # 设置调色板(需要1维list)
  30.         palette = [v for color in colormap for v in color]
  31.         palette += [0] * (256 * 3 - len(palette))  # 填满256个颜色
  32.         mask_img.putpalette(palette)
  33.         mask_img.save(os.path.join(save_mask_dir, f"{img_info['file_name'].replace('.jpg', '.png')}"))
  34.     print(f"已保存 {len(img_ids)} 张P模式语义分割mask图到 {save_mask_dir}")
  35. # ==== 用法 ====
  36. # 训练集
  37. coco_to_semantic_mask_pmode(
  38.     coco_json_path='../../data/COCO2017/annotations1/instances_train2017.json',
  39.     image_dir='../../data/COCO2017/train2017',
  40.     save_mask_dir='../../data/COCO2017/train2017_labels'
  41. )
  42. # 验证集
  43. coco_to_semantic_mask_pmode(
  44.     coco_json_path='../../data/COCO2017/annotations1/instances_val2017.json',
  45.     image_dir='../../data/COCO2017/val2017',
  46.     save_mask_dir='../../data/COCO2017/val2017_labels'
  47. )
复制代码
数据加载(dataloader)

经过我们数据集处理后的COCO2017的标注就是P模式的
  1. import os
  2. from PIL import Image
  3. import albumentations as A
  4. from albumentations.pytorch.transforms import ToTensorV2
  5. from torch.utils.data import Dataset, DataLoader
  6. import numpy as np
  7. import imgviz
  8. COCO_CLASSES = [
  9.     "background", "person", "bicycle", "car", "motorcycle", "airplane", "bus", "train", "truck", "boat",
  10.     "traffic light", "fire hydrant", "stop sign", "parking meter", "bench", "bird", "cat", "dog", "horse", "sheep",
  11.     "cow", "elephant", "bear", "zebra", "giraffe", "backpack", "umbrella", "handbag", "tie", "suitcase",
  12.     "frisbee", "skis", "snowboard", "sports ball", "kite", "baseball bat", "baseball glove", "skateboard", "surfboard", "tennis racket",
  13.     "bottle", "wine glass", "cup", "fork", "knife", "spoon", "bowl", "banana", "apple", "sandwich",
  14.     "orange", "broccoli", "carrot", "hot dog", "pizza", "donut", "cake", "chair", "couch", "potted plant",
  15.     "bed", "dining table", "toilet", "tv", "laptop", "mouse", "remote", "keyboard", "cell phone", "microwave",
  16.     "oven", "toaster", "sink", "refrigerator", "book", "clock", "vase", "scissors", "teddy bear", "hair drier",
  17.     "toothbrush"
  18. ]
  19. COCO_COLORMAP = imgviz.label_colormap()
  20. class COCO2017Dataset(Dataset):
  21.     def __init__(self, image_dir, label_dir):
  22.         self.image_dir = image_dir
  23.         self.label_dir = label_dir
  24.         self.transform = A.Compose([
  25.             A.Resize(448, 448),
  26.             A.HorizontalFlip(),
  27.             A.VerticalFlip(),
  28.             A.Normalize(),
  29.             ToTensorV2(),
  30.         ])
  31.         self.images = sorted(os.listdir(image_dir))
  32.         self.labels = sorted(os.listdir(label_dir))
  33.         assert len(self.images) == len(self.labels), "Images and labels count mismatch!"
  34.     def __len__(self):
  35.         return len(self.images)
  36.     def __getitem__(self, idx):
  37.         img_path = os.path.join(self.image_dir, self.images[idx])
  38.         label_path = os.path.join(self.label_dir, self.labels[idx])
  39.         image = np.array(Image.open(img_path).convert("RGB"))
  40.         label = np.array(Image.open(label_path))
  41.         # Albumentations 需要 (H, W, 3) 和 (H, W)
  42.         transformed = self.transform(image=image, mask=label)
  43.         return transformed['image'], transformed['mask']
  44. def get_dataloader(data_path, batch_size=4, num_workers=4):
  45.     train_dir = os.path.join(data_path,'train2017')
  46.     val_dir = os.path.join(data_path,'val2017')
  47.     trainlabel_dir = os.path.join(data_path, 'train2017_labels')
  48.     vallabel_dir = os.path.join(data_path, 'val2017_labels')
  49.     train_dataset = COCO2017Dataset(train_dir, trainlabel_dir)
  50.     val_dataset = COCO2017Dataset(val_dir, vallabel_dir)
  51.     train_loader = DataLoader(train_dataset, shuffle=True, batch_size=batch_size, pin_memory=True, num_workers=num_workers)
  52.     val_loader = DataLoader(val_dataset, shuffle=False, batch_size=batch_size, pin_memory=True, num_workers=num_workers)
  53.     return train_loader, val_loader
复制代码
16.png

结语

上述所述的相关数据集就是语义分割任务中常用的数据集了,各个数据集都各有特点:

  • VOC2012 更适用于初学者和基本实验。
  • COCO2017ADE20k 则适用于大规模、多类别的复杂分割任务。
  • CamVidCityscapes 主要聚焦于自动驾驶和城市环境中的语义分割。
希望上列所述内容对你有所帮助,如果有错误的地方欢迎大家批评指正!
如果你觉得讲的还不错想转载,可以直接转载,不过麻烦指出本文来源出处即可,谢谢!
参考内容

语义分割标签——mask的读取与保存_mask文件-CSDN博客
语义分割数据集:Cityscapes的使用_cityscapes数据集-CSDN博客
ADE20K数据集 - 知乎
图像语意分割Cityscapes训练数据集使用方法详解_图像语意分割训练cityscapes数据集segnet-convnet神经网络详解-CSDN博客
Dataset之CamVid:CamVid数据集的简介、下载、使用方法之详细攻略_camvid数据集下载-CSDN博客

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册