038、语义分割

之——介绍与数据集

杂谈

        语义分割,语义分割(Semantic Segmentation)方法-CSDN博客

        语义分割是计算机视觉领域的一项重要任务,旨在将图像中的每个像素分配到其对应的语义类别中。与物体检测或图像分类不同,语义分割不仅要识别图像中的对象,还要为每个像素标注其语义类别,实现对图像的细粒度理解。

        在语义分割中,每个像素都被赋予一个标签,表示该像素属于图像中的哪个语义类别,例如人、车、道路、树等。这使得语义分割成为深度学习在医学图像分析、自动驾驶、农业图像处理等领域中的关键技术之一。

        常见的语义分割方法包括基于卷积神经网络(CNN)的深度学习方法。这些方法通常使用编码器-解码器结构,通过学习图像的高级特征来实现像素级别的分类。语义分割在许多应用中都有广泛的用途,如交通场景理解、医学图像分析、卫星图像解释等。


正文

1.语义分割

        像素级的分割:

        一般的分割只是对类似样式像素进行聚类,而语义分割在此基础上还加入了对这个类别的理解。


2.应用

        背景虚化:

        道路分割:

         另外还有一个进化版,在语义分割上升级为对每个实例都有区分:


3.数据集

        Pascal VOC2012数据集:

d2l.DATA_HUB['voc2012'] = (d2l.DATA_URL + 'VOCtrainval_11-May-2012.tar',
                           '4e443f8a2eca6b1dac8a6c57641b67dd40621a49')

voc_dir = d2l.download_extract('voc2012', 'VOCdevkit/VOC2012')

        读取,依次把图片和对应的标号读进来:

def read_voc_images(voc_dir, is_train=True):
    """读取所有VOC图像并标注"""
    txt_fname = os.path.join(voc_dir, 'ImageSets', 'Segmentation',
                             'train.txt' if is_train else 'val.txt')
    mode = torchvision.io.image.ImageReadMode.RGB
    with open(txt_fname, 'r') as f:
        images = f.read().split()
    features, labels = [], []
    for i, fname in enumerate(images):
        features.append(torchvision.io.read_image(os.path.join(
            voc_dir, 'JPEGImages', f'{fname}.jpg')))
        labels.append(torchvision.io.read_image(os.path.join(
            voc_dir, 'SegmentationClass' ,f'{fname}.png'), mode))
    return features, labels

train_features, train_labels = read_voc_images(voc_dir, True)

        展示:

n = 5
imgs = train_features[0:n] + train_labels[0:n]
imgs = [img.permute(1,2,0) for img in imgs]
d2l.show_images(imgs, 2, n);

        列举颜色和类别名:

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]]

#@save
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']

        通过以上定义的两个常量,可以方便地查找标签中每个像素的类索引。

        通过创造个colormap,可能的颜色组合就是256^3,然后进行三通道颜色的融合计算与类别数一一映射上:

def voc_colormap2label():
    """构建从RGB到VOC类别索引的映射"""
    colormap2label = torch.zeros(256 ** 3, dtype=torch.long)
    for i, colormap in enumerate(VOC_COLORMAP):
        colormap2label[
            (colormap[0] * 256 + colormap[1]) * 256 + colormap[2]] = i
    return colormap2label


def voc_label_indices(colormap, colormap2label):
    """将VOC标签中的RGB值映射到它们的类别索引"""
    colormap = colormap.permute(1, 2, 0).numpy().astype('int32')
    idx = ((colormap[:, :, 0] * 256 + colormap[:, :, 1]) * 256
           + colormap[:, :, 2])
    return colormap2label[idx]

         这样就把分割颜色转换为了类别:

y = voc_label_indices(train_labels[1], voc_colormap2label())
y[190:200, 190:200], VOC_CLASSES[20]

        可见 VOC_CLASSES 和数字挂上了钩:

         随机裁剪图像:

def voc_rand_crop(feature, label, height, width):
    """随机裁剪特征和标签图像"""
    rect = torchvision.transforms.RandomCrop.get_params(
        feature, (height, width))
    feature = torchvision.transforms.functional.crop(feature, *rect)
    label = torchvision.transforms.functional.crop(label, *rect)
    return feature, label

imgs = []
for _ in range(n):
    imgs += voc_rand_crop(train_features[0], train_labels[0], 200, 300)

imgs = [img.permute(1, 2, 0) for img in imgs]

d2l.show_images(imgs[::2] + imgs[1::2], 2, n);

        自定义语义分割数据集:

class VOCSegDataset(torch.utils.data.Dataset):
    """一个用于加载VOC数据集的自定义数据集"""

    def __init__(self, is_train, crop_size, voc_dir):
        self.transform = torchvision.transforms.Normalize(
            mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
        self.crop_size = crop_size
        features, labels = read_voc_images(voc_dir, is_train=is_train)
        self.features = [self.normalize_image(feature)
                         for feature in self.filter(features)]
        self.labels = self.filter(labels)
        self.colormap2label = voc_colormap2label()
        print('read ' + str(len(self.features)) + ' examples')

    def normalize_image(self, img):
        return self.transform(img.float() / 255)

    def filter(self, imgs):
        return [img for img in imgs if (
            img.shape[1] >= self.crop_size[0] and
            img.shape[2] >= self.crop_size[1])]

    def __getitem__(self, idx):
        feature, label = voc_rand_crop(self.features[idx], self.labels[idx],
                                       *self.crop_size)
        return (feature, voc_label_indices(label, self.colormap2label))

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

拓展

        语义分割的算法和技术在不断发展,以下是一些常见的算法和技术:

  1. 全卷积网络(Fully Convolutional Networks,FCN):这是语义分割领域中的里程碑之一。FCN将传统的卷积神经网络中的全连接层替换为全卷积层,允许输入图像尺寸与输出分割结果尺寸不同。通过上采样和跳跃连接,FCN能够生成像素级别的语义分割。

  2. U-Net:U-Net结构由编码器(收缩路径)和解码器(扩展路径)组成,通过特征提取和逐步上采样,能够在保留空间信息的同时进行语义分割,尤其在医学图像分割中应用广泛。

  3. DeepLab:DeepLab系列模型利用空洞卷积(或称为膨胀卷积)来扩大卷积操作的感受野,有助于捕获更广阔的上下文信息。DeepLab模型还使用了空间金字塔池化(Spatial Pyramid Pooling)等技术来处理多尺度信息。

  4. Mask R-CNN:这是一种结合了目标检测和语义分割的方法。它在Faster R-CNN的基础上增加了分割分支,可以同时检测和分割图像中的对象。

  5. 图卷积网络(Graph Convolutional Network,GCN):针对具有图结构的数据,如社交网络或分子结构,GCN可用于图像语义分割。它能够处理像素之间的关联信息,有助于更好地理解图像中像素之间的联系。

  6. 实例分割(Instance Segmentation):与语义分割类似,但不仅对像素进行语义标注,还能区分不同实例。Mask R-CNN是其中一个流行的实例分割方法。

        这些算法和技术的不断发展使得语义分割在医学影像、自动驾驶、农业图像处理、地理信息系统等领域中有着广泛的应用和进展。同时,结合了深度学习和传统计算机视觉技术的组合也在不断涌现,为语义分割领域带来了新的创新。

        关于yolo的分割:

        YOLOv3 及其后续版本也包含了一定程度的语义分割功能。

        虽然 YOLO 主要是用于目标检测,但YOLOv3及后续版本提供了一种称为“预测像素级别标签”的功能。这种功能允许 YOLO 模型输出对图像进行分割的结果。虽然它并不是专门用于像素级别的语义分割,但这种预测可以提供较为粗略的分割效果。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Here-We-Are

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值