在 RGB 图像上绘制多类语义分割透明覆盖

Posted

技术标签:

【中文标题】在 RGB 图像上绘制多类语义分割透明覆盖【英文标题】:Plotting multi-class semantic segmentation transparent overlays over RGB image 【发布时间】:2020-10-03 08:45:24 【问题描述】:

我有语义分割掩码的结果(值在 0-1 之间,需要 otsu 阈值来确定什么是正面的),我想直接在 RGB 图像上绘制,每个预测类在 RGB 图像上具有不同的随机颜色。

我使用以下方法绘制了具有单一颜色的单一蒙版。是否有一个包或简单的策略可以为多类做到这一点?

fig, ax = plt.subplots(nrows=nrows, ncols=ncols, figsize=(5, 5))
  ax.imshow(image, cmap='gray')
  ax.axis('off')
  mask = (fused_mosaic[..., channel]*255).astype('uint8')
  ret3,th3 = cv2.threshold(mask,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
  fig, ax = image_show(full_im)
  ax.imshow(mask>ret3, alpha=0.3)

我正在寻找这样的东西,只是没有盒子和标签的简单。我尝试使用detectron2(在示例中生成此注释的包,但它们需要一些我无法弄清楚的奇怪的元数据对象)。

谢谢

【问题讨论】:

那么您是说掩码中的每个唯一浮点值都可以解释为不同的类? 不,我使用上面提到的阈值将每个通道离散为二进制,所以它是一组二进制掩码 所以channel 将是您正在寻找的掩码......所以您想在一张图像中将所有语义分割掩码一起蒙版?我不太明白你想要什么。但是,如果我是对的,那只是循环的问题 这很简单,请参阅我添加到帖子中的示例图片@rayryeng​​span> 但是你还没有回答我的问题。 fused_mosaic 包含什么? 【参考方案1】:

Scikit-image 有一个内置的label2rgb() 函数,可以根据标签通道着色:

#!/usr/bin/env python3

from skimage import io
from skimage import color
from skimage import segmentation
import matplotlib.pyplot as plt

# URL for tiger image from Berkeley Segmentation Data Set BSDS
url=('http://www.eecs.berkeley.edu/Research/Projects/CS/vision/bsds/BSDS300/html/images/plain/normal/color/108073.jpg')

# Load tiger image from URL
tiger = io.imread(url)

# Segment image with SLIC - Simple Linear Iterative Clustering
seg = segmentation.slic(tiger, n_segments=30, compactness=40.0, enforce_connectivity=True, sigma=3)

# Generate automatic colouring from classification labels
io.imshow(color.label2rgb(seg,tiger))
plt.show()

【讨论】:

当然 - 让您找到更简单的解决方案。 谢谢,我得到了一些有趣的注释。有没有办法(1)控制颜色(2)透明度和(3)最重要的是在图像旁边或我在角落的白色部分或完全单独添加颜色图例? 您可以传递颜色和透明度列表 - 请参阅此处的文档 scikit-image.org/docs/stable/api/skimage.color.html#label2rgb 我认为您需要自己添加图例。 @rayryeng 你只是嫉妒我可以下降到的懒惰的深度? @MarkSetchell 工程学的缩影就是懒惰。懒惰意味着你不想做很多工作,所以你想找出最有效的方法:P。你的懒惰教会了我一些新东西!【参考方案2】:

通过我们上面的对话,您有一个 2D NumPy 整数 ID 数组,其中该数组中的每个元素确定所述像素的类 ID,从而为您提供语义分割输出。

我建议您分三个阶段进行。

    创建一个大小为N x 4 的RGB 颜色图,其中N 是分割中的输出类总数。因此,每个类 i 都被分配了一个 RGBA 颜色像素值,您将使用它来为输出着色。

    展平输入整数 NumPy 数组,使其成为一维 NumPy 数组,我们可以使用它来索引 (1)

    最后索引到 (1) 中的 RGB 颜色映射。这将创建一个(R x C) x 4 2D NumPy 数组,其中包含将语义标签映射到颜色的输出彩色图像。当然,我们需要将其恢复为原始输入尺寸,因此重新调整此数组,使其变为 R x C x 4 供您显示。最后,因为我们现在有一个图像的 Alpha 通道,所以您可以将其显示在原始图像之上。


步骤 #1 - 生成颜色图

matplotlib 有一套不错的工具可以为您生成此颜色图。您可以从此使用cm 模块。首先,决定你想为你的目的使用什么颜色图。可以在此处找到它们的完整列表:https://matplotlib.org/3.1.1/tutorials/colors/colormaps.html。我会选择 Viridis,因为这是 matplotlib 中当前使用的默认设置。

假设你系统中的类总数为N,首先生成颜色图,然后用N元素创建一个从0到1的线性间隔数组,从头到尾均匀地创建颜色这张彩色地图的结尾。另请注意,这将生成一个N x 4 颜色映射,最后一列是 Alpha 通道。这对以后非常重要。具体来说,此方法会将标签为 0 的任何像素着色为属于颜色图的下端,因为这是语义分割输出,标签 0 应对应于背景,因此我们应将此标签的 alpha 通道设置为 0要透明。我们可以将其余颜色设置为您想要的 alpha,在您的代码中为 0.3。

from matplotlib import cm
import numpy as np
N = ... # You define this here
colours = cm.get_cmap('viridis', N)  # Change the string from 'viridis' to whatever you want from the above link
cmap = colours(np.linspace(0, 1, N))  # Obtain RGB colour map
cmap[0,-1] = 0  # Set alpha for label 0 to be 0
cmap[1:,-1] = 0.3  # Set the other alphas for the labels to be 0.3

第 2 步 - 获取语义分割输出并找到合适的颜色

这是直截了当的。假设fused_mosaic 是我们之前讨论过的二维整数数组,将这个数组展平并索引您的颜色图:

output = cmap[fused_mosaic.flatten()]

步骤 #3 - 重塑为所需的输出

这又是直截了当的:

R, C = fused_mosaic.shape[:2]
output = output.reshape((R, C, -1))

output 现在将包含语义分割图中每个对象的 RGBA 渲染图像。然后,您最终可以使用它并将其显示在图像顶部。使用您的代码,这将是:

fig, ax = image_show(full_im)  # Don't know what this does but it's from your code
ax.imshow(output)

为了将所有内容联系在一起,这就是我最终要做的:

## Step #1
from matplotlib import cm
import numpy as np
N = ... # You define this here
colours = cm.get_cmap('viridis', N)  # Change the string from 'viridis' to whatever you want from the above link
cmap = colours(np.linspace(0, 1, N))  # Obtain RGB colour map
cmap[0,-1] = 0  # Set alpha for label 0 to be 0
cmap[1:,-1] = 0.3  # Set the other alphas for the labels to be 0.3

## Step #2
output = cmap[fused_mosaic.flatten()]

## Step #3
R, C = fused_mosaic.shape[:2]
output = output.reshape((R, C, -1))

## Overlay
fig, ax = image_show(full_im)  # Don't know what this does but it's from your code
ax.imshow(output)

【讨论】:

以上是关于在 RGB 图像上绘制多类语义分割透明覆盖的主要内容,如果未能解决你的问题,请参考以下文章

keras/tensorflow中语义图像分割的多类加权损失

多类语义分割模型评估

如何实现多类语义分割?

为啥训练多类语义分割的unet模型中的分类交叉熵损失函数非常高?

多类语义分割 - 输出激活?

如何使用tensorflow实现多类语义分割