转载自 https://blog.csdn.net/qq_21368481/article/details/80357950
FCN中的vis.py用于测试时输出可视化分割图像,可以选择两种可视化输出,一种为直接可视化的彩色分割图(左图);一种为含有掩膜的分割图(原图与分割彩色图的加权融合,右图)。
vis.py源码如下:
-
import numpy
as np
-
-
-
def make_palette(num_classes):
-
"""
-
Maps classes to colors in the style of PASCAL VOC.
-
Close values are mapped to far colors for segmentation visualization.
-
See http://host.robots.ox.ac.uk/pascal/VOC/voc2012/index.html#devkit
-
-
-
Takes:
-
num_classes: the number of classes
-
Gives:
-
palette: the colormap as a k x 3 array of RGB colors
-
"""
-
palette = np.zeros((num_classes,
3), dtype=np.uint8)
-
for k
in xrange(
0, num_classes):
-
label = k
-
i =
0
-
while label:
-
palette[k,
0] |= (((label >>
0) &
1) << (
7 - i))
-
palette[k,
1] |= (((label >>
1) &
1) << (
7 - i))
-
palette[k,
2] |= (((label >>
2) &
1) << (
7 - i))
-
label >>=
3
-
i +=
1
-
return palette
-
-
-
def color_seg(seg, palette):
-
"""
-
Replace classes with their colors.
-
-
-
Takes:
-
seg: H x W segmentation image of class IDs
-
Gives:
-
H x W x 3 image of class colors
-
"""
-
return palette[seg.flat].reshape(seg.shape + (
3,))
-
-
-
def vis_seg(img, seg, palette, alpha=0.5):
-
"""
-
Visualize segmentation as an overlay on the image.
-
-
-
Takes:
-
img: H x W x 3 image in [0, 255]
-
seg: H x W segmentation image of class IDs
-
palette: K x 3 colormap for all classes
-
alpha: opacity of the segmentation in [0, 1]
-
Gives:
-
H x W x 3 image with overlaid segmentation
-
"""
-
vis = np.array(img, dtype=np.float32)
-
mask = seg >
0
-
vis[mask] *=
1. - alpha
-
vis[mask] += alpha * palette[seg[mask].flat]
-
vis = vis.astype(np.uint8)
-
return vis
源码解读如下:
(1)make_palette()
此函数通过输入的类别数(num_classes)生成一个调色板,每个类别对应一种颜色。
-
#生成调色板
-
def make_palette(num_classes):
-
"""
-
Maps classes to colors in the style of PASCAL VOC.
-
Close values are mapped to far colors for segmentation visualization.
-
See http://host.robots.ox.ac.uk/pascal/VOC/voc2012/index.html#devkit
-
-
-
Takes:
-
num_classes: the number of classes 输入为类别数目
-
Gives:
-
palette: the colormap as a k x 3 array of RGB colors 输出为k×3大小的RGB颜色数组
-
"""
-
palette = np.zeros((num_classes,
3), dtype=np.uint8)
-
#xrange() 函数用法与 range 完全相同,所不同的是生成的不是一个数组,而是一个生成器
-
for k
in xrange(
0, num_classes):
-
label = k
-
i =
0
-
while label:
#按一定规则移位产生调色板
-
palette[k,
0] |= (((label >>
0) &
1) << (
7 - i))
#>>为二进制右移
-
palette[k,
1] |= (((label >>
1) &
1) << (
7 - i))
-
palette[k,
2] |= (((label >>
2) &
1) << (
7 - i))
-
label >>=
3
-
i +=
1
-
return palette
若输入的num_classes=21,则输出结果如下(每行对应一种颜色,从结果中也可以看出每个类别对应的颜色是不一样的):
-
[[
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]]
(2)color_seg()
此函数所产生的分割图像即如上面的左图。
-
#产生一个可视化的类别数组
-
def color_seg(seg, palette):
-
"""
-
Replace classes with their colors.
-
-
Takes:
-
seg: H x W segmentation image of class IDs
-
seg是score层产生的类别图(即每一像素的值是0-(num_classes-1)中的一个)
-
Gives:
-
H x W x 3 image of class colors
-
生成一张三通道的彩色图(其中每一种颜色对应一种类别),实际生成是H×W×3的数组,需要经过python中但PIL库调用函数Image.fromarray将此数组转化为一张彩色图(详见infer.py最后几行)
-
"""
-
return palette[seg.flat].reshape(seg.shape + (
3,))
#按照类别进行上色
(3)vis_seg()
此函数所产生的分割图像即如上面的右图。
-
#产生一个可视化的含有分割掩膜数组(即包含原图和分割掩膜但数组,本质上就是两者的加权融合)
-
def vis_seg(img, seg, palette, alpha=0.5):
#alpha为透明度,也即加权融合因子
-
"""
-
Visualize segmentation as an overlay on the image.
-
-
Takes:
-
img: H x W x 3 image in [0, 255] 原图
-
seg: H x W segmentation image of class IDs 同color_seg中的seg
-
palette: K x 3 colormap for all classes 调色板
-
alpha: opacity of the segmentation in [0, 1] 透明度
-
Gives:
-
H x W x 3 image with overlaid segmentation 输出含有掩膜的大小为H×W×3的数组
-
"""
-
vis = np.array(img, dtype=np.float32)
#将图像转换为数组
-
mask = seg >
0
#产生去除背景(标号为0)的掩膜
-
vis[mask] *=
1. - alpha
#原图像除背景外乘上alpha
-
vis[mask] += alpha * palette[seg[mask].flat]
#加上alpha倍的上色图(也除去了背景)
-
vis = vis.astype(np.uint8)
#强制转化为unchar型(图像像素0-255的限制,所以需要强制转换)
-
return vis