乐趣区

关于人工智能:通用图像分割任务-使用-Mask2Former-和-OneFormer

本文介绍两个当先的图像宰割神经网络模型: Mask2Former 和 OneFormer。相干模型曾经在 🤗 Transformers 提供。🤗 Transformers 是一个开源库,提供了很多便捷的先进模型。在本文中,你也会学到各种图像宰割工作的不同之处。

图像宰割

图像宰割工作旨在甄别辨别出一张图片的不同局部,比方人物、汽车等等。从技术角度讲,图像宰割工作须要依据不同的语义信息辨别并汇集起对应雷同语义的像素点。读者能够参考 Hugging Face 的 工作页面 来简要理解。

大体上,图像宰割能够分为三个子工作: 实例宰割 (instance segmentation)、语义宰割 (semantic segmentation)、全景宰割 (panoptic segmentation)。这三个子工作都有着大量的算法与模型。

  • 实例宰割 工作旨在辨别不同的“实例”,例如图像中不同的人物个体。实例宰割从某种角度看和物体检测很像,不同的是在这里咱们须要的是一个对应类别的二元的宰割掩膜,而不是一个检测框。实例也能够称为“物体 (objects)”或“实物 (things)”。须要留神的是,不同的个体可能在图像中是互相重叠的。
  • 语义宰割 辨别的是不同的“语义类别”,比方属于人物、天空等类别的各个像素点。与实例宰割不同的是,这里咱们不须要辨别开同一类别下的不同个体,例如这里咱们只须要失去“人物”类别的像素级掩膜即可,不须要辨别开不同的人。有些类别基本不存在个体的辨别,比方天空、草地,这种类别咱们称之为“货色 (stuff)”,以此辨别开其它类别,称之为“实物 (things)”。请留神这里不存在不同语义类别间的重叠,因为一个像素点只能属于一个类别。
  • 全景宰割 在 2018 年由 Kirillov et al. 提出,目标是为了对立实例宰割和语义宰割。模型单纯地甄别出一系列的图像局部,每个局部既有对应的二元掩膜,也有对应的类别标签。这些辨别进去的局部,既能够是“货色”也能够是“实物”。与实例宰割不同的是,不同局部间不存在重叠。

下图展现了三个子工作的不同: (图片来自 这篇博客文章)

近年来,研究者们曾经推出了很多针对实例、语义、全景宰割精心设计的模型架构。实例宰割和全景宰割基本上是通过输入一系列实例的二元掩膜和对应类别标签来解决的 (和物体检测很像,只不过这里不是输入每个实例的检测框)。这一操作也经常被称为“二元掩膜分类”。语义宰割则不同,通常是让模型输入一个“宰割图”,令每一个像素点都有一个标签。所以语义宰割也常被视为一个“像素级分类”的工作。采纳这一范式的语义宰割模块包含 SegFormer 和 UPerNet。针对 SegFormer 咱们还写了一篇 具体的博客。

通用图像宰割

侥幸的是,从大概 2020 年开始,人们开始钻研能同时解决三个工作 (实例、语义和全景宰割) 的对立模型。DETR 是开山之作,它通过“二元掩膜分类”的范式去解决全景宰割问题,把“实物”和“货色”的类别用对立的办法看待。其外围点是应用一个 Transformer 的解码器 (decoder) 来并行地生成一系列的二元掩膜和类别。随后 MaskFormer 又在此基础上进行了改良,表明了“二元掩膜分类”的范式也能够用在语义宰割上。

Mask2Former 又将此办法扩大到了实例宰割上,进一步改良了神经网络的构造。因而,各自拆散的子工作框架当初曾经进化到了“通用图像宰割”的框架,能够解决任何图像宰割工作。乏味的是,这些通用模型全都采取了“掩膜分类”的范式,彻底摈弃了“像素级分类”这一办法。下图就展现了 Mask2Former 的网络结构 (图像取自 这篇论文)。

简短来说,一张图片首先被送入骨干网络 (backbone) 外面来获取一系列,在论文中,骨干网络既能够是 ResNet 也能够是 Swin Transformer。接下来,这些特色图会被一个叫做 Pixel Decoder 的模块加强成为高分辨率特色图。最终,一个 transformer 的解码器会接管一系列的 query,基于上一步失去的特色,把它们转换成一些列二元掩膜和分类预测。

须要留神的是,MasksFormer 依然须要在每个独自的工作上训练来获取当先的后果。这一点被 OneFormer 进行了改良,并通过在全景数据集上训练,达到了领先水平。OneFormer 减少了一个文本编码器 (text encoder),使得模型有了一个基于文本条件 (实例、语义或全景) 的输出。该模型曾经收录入 🤗 Transformers 之中,比 Mask2Former 更精确,但因为文本编码器的引入,所以速度略慢。下图展现了 OneFormer 的根本构造,它应用 Swin Transformer 或 DiNAT 作为骨干网络。

应用 Transformers 库中的 Mask2Former 和 OneFormer 进行推理

应用 Mask2Former 和 OneFormer 办法相当间接,而且和它们的前身 MaskFormer 十分类似。咱们这里从 Hub 中应用一个在 COCO 全景数据集上训练的一个模型来实例化一个 Mask2Former 以及对应的 processor。须要留神的是,在不同数据集上训练进去的 checkpoints 曾经公开,数量不下 30 个。

from transformers import AutoImageProcessor, Mask2FormerForUniversalSegmentation

processor = AutoImageProcessor.from_pretrained("facebook/mask2former-swin-base-coco-panoptic")
model = Mask2FormerForUniversalSegmentation.from_pretrained("facebook/mask2former-swin-base-coco-panoptic")

而后咱们从 COCO 数据集中找出一张猫的图片,用它来进行推理。

from PIL import Image

url = "http://images.cocodataset.org/val2017/000000039769.jpg"
image = Image.open(requests.get(url, stream=True).raw)
image

咱们应用 processor 解决原始图片,而后送入模型进行前向推理。

inputs = processor(image, return_tensors="pt")

with torch.no_grad():
    outputs = model(**inputs)

模型输入了一系列二元掩膜以及对应类别的 logit。Mask2Former 的原始输入还能够应用 processor 进行解决,来失去最终的实例、语义或全景宰割后果:

prediction = processor.post_process_panoptic_segmentation(outputs, target_sizes=[image.size[::-1]])[0]
print(prediction.keys())
Output:
----------------------------------------------------------------------------------------------------
dict_keys(['segmentation', 'segments_info'])

在全景宰割中,最终的 prediction 蕴含两样货色: 一个是形态为 (height, width) 的 segmentation 图,外面针对每一个像素都给出了编码实例 ID 的值; 另一个是与之对应的 segments_info,蕴含了不同宰割区域的更多信息 (比方类别、类别 ID 等)。须要留神的是,为了高效,Mask2Former 输入的二元掩码的形态是 (96, 96) 的,咱们须要用 target_sizes 来扭转尺寸,使得这个掩膜和原始图片尺寸统一。

将后果可视化进去:

from collections import defaultdict
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
from matplotlib import cm

def draw_panoptic_segmentation(segmentation, segments_info):
    # get the used color map
    viridis = cm.get_cmap('viridis', torch.max(segmentation))
    fig, ax = plt.subplots()
    ax.imshow(segmentation)
    instances_counter = defaultdict(int)
    handles = []
    # for each segment, draw its legend
    for segment in segments_info:
        segment_id = segment['id']
        segment_label_id = segment['label_id']
        segment_label = model.config.id2label[segment_label_id]
        label = f"{segment_label}-{instances_counter[segment_label_id]}"
        instances_counter[segment_label_id] += 1
        color = viridis(segment_id)
        handles.append(mpatches.Patch(color=color, label=label))
        
    ax.legend(handles=handles)

draw_panoptic_segmentation(**panoptic_segmentation)

能够看到,模型辨别开了不同的猫和遥控器。相比较而言,语义宰割只会为“猫”这一品种创立一个繁多的掩膜。

如果你想试试 OneFormer,它和 Mask2Former 的 API 简直一样,只不过多了一个文本提醒的输出; 能够参考这里的 demo notebook。

应用 transformers 微调 Mask2Former 和 OneFormer

读者能够参考这里的 demo notebooks 来在自定义的实例、语义或全景宰割数据集上微调 Mask2Former 或 OneFormer 模型。MaskFormer、Mask2Former 和 OneFormer 都有着类似的 API,所以基于 MaskFormer 进行改良非常不便、须要的批改很少。

在上述 notebooks 中,都是应用 MaskFormerForInstanceSegmentation 来加载模型,而你须要换成应用 Mask2FormerForUniversalSegmentation 或 OneFormerForUniversalSegmentation。对于 Mask2Former 中的图像处理,你也须要应用 Mask2FormerImageProcessor。你也能够应用 AutoImageProcessor 来主动地加载适宜你的模型的 processor。OneFormer 则须要应用 OneFormerProcessor,因为它不仅预处理图片,还须要解决文字。

总结

总的来说就这些内容!你当初晓得实例宰割、语义宰割以及全景宰割都有什么不同了,你也晓得如何应用 🤗 Transformers 中的 Mask2Former 和 OneFormer 之类的“通用架构”了。

咱们心愿你喜爱本文并学有所学。如果你微调了 Mask2Former 或 OneFormer,也请让咱们晓得你是否对后果足够称心。

如果想深刻学习,咱们举荐以下资源:

  • 咱们针对 MaskFormer, Mask2Former and OneFormer, 推出的 demo notebooks,将会给出更多对于推理 (包含可视化) 和微调的常识。
  • 在 Hugging Face Hub 上,Mask2Former 和 OneFormer 的 live demo spaces,能够让你疾速用本人的输出数据尝试不同模型。

原文链接: https://hf.co/blog/mask2former

作者: Niels Rogge、Shivalika Singh、Alara Dirik

译者: Hoi2022

审校、排版: zhongdongy (阿东)

退出移动版