因为分割的标签是一个彩色图像,而不是理想中的每一个像素就是他的类别,所以我们需要处理一下
如果你用pillow读,就会发现他的模式是P,代表着他用调色板把灰度图映射成彩色图了,所以首先要获取调色板
简单来说就是读取任意标签,然后获取他的调色板
#!/usr/bin/env python
# _*_ coding:utf-8 _*_
import numpy as np
from PIL import Image
if __name__ == '__main__':
# 任意标签
label_path ='/data/datasets/VOCtrainval_11-May-2012/VOCdevkit/VOC2012/SegmentationClass/2007_000032.png'
palette = np.array(Image.open(label_path).getpalette()).reshape((-1, 3))
print(palette[:21])
在这个链接里可以找到http://host.robots.ox.ac.uk/pascal/VOC/voc2012/VOCdevkit_18-May-2011.tar
VOCdevkit_18-May-2011/VOCdevkit/VOCcode/VOClabelcolormap.m
% VOCLABELCOLORMAP Creates a label color map such that adjacent indices have different
% colors. Useful for reading and writing index images which contain large indices,
% by encoding them as RGB images.
%
% CMAP = VOCLABELCOLORMAP(N) creates a label color map with N entries.
function cmap = labelcolormap(N)
if nargin==0
N=256
end
cmap = zeros(N,3);
for i=1:N
id = i-1; r=0;g=0;b=0;
for j=0:7
r = bitor(r, bitshift(bitget(id,1),7 - j));
g = bitor(g, bitshift(bitget(id,2),7 - j));
b = bitor(b, bitshift(bitget(id,3),7 - j));
id = bitshift(id,-3);
end
cmap(i,1)=r; cmap(i,2)=g; cmap(i,3)=b;
end
cmap = cmap / 255;
这里除了原本的20类+背景,还有一个边界
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], [224, 224, 192]]
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', 'void']
http://host.robots.ox.ac.uk/pascal/VOC/voc2012/segexamples/index.html
https://zhuanlan.zhihu.com/p/102303256
因为python不能把数组映射成数字,所以要把(r,g,b)编码成一个数字,可以考虑
r < < 16 ∣ g < < 8 ∣ b = r ∗ 256 ∗ 256 + g ∗ 256 + b r<<16|g<<8|b=r*256*256+g*256+b r<<16∣g<<8∣b=r∗256∗256+g∗256+b
然后再映射
做一个数组,包含所有的颜色的映射,然后把图片输进去就可以了
这里注意图片一定要转成int(不然貌似会超出uint8)
我这里把边界映射成了0(就是注释掉的21那里)
#!/usr/bin/env python
# _*_ coding:utf-8 _*_
import numpy as np
from cv2 import cv2
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], [224, 224, 192]]
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', 'void']
if __name__ == '__main__':
label_path ='/data/datasets/VOCtrainval_11-May-2012/VOCdevkit/VOC2012/SegmentationClass/2007_000032.png'
label_color_map = np.zeros(1 << 24, dtype=np.uint8)
for i, (r, g, b) in enumerate(VOC_COLORMAP[:21]):
# label_color_map[r << 16 | g << 8 | b] = i
label_color_map[b << 16 | g << 8 | r] = i
r, g, b = VOC_COLORMAP[-1]
# label_color_map[r << 16 | g << 8 | b] = 21
# label_color_map[r << 16 | g << 8 | b] = 0
# label_color_map[b << 16 | g << 8 | r] = 21
label_color_map[b << 16 | g << 8 | r] = 0
img = cv2.imread(label_path).astype(np.int64)
result = label_color_map[img[..., 0] << 16 | img[..., 1] << 8 | img[..., 2]].astype(np.uint8)
print(np.unique(result))
其实和第一种差不多,只是用了向量化(其实我也不知道会不会更快)
#!/usr/bin/env python
# _*_ coding:utf-8 _*_
import numpy as np
from cv2 import cv2
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], [224, 224, 192]]
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', 'void']
if __name__ == '__main__':
label_path ='/data/datasets/VOCtrainval_11-May-2012/VOCdevkit/VOC2012/SegmentationClass/2007_000032.png'
label_color_map = {}
for i, (r, g, b) in enumerate(VOC_COLORMAP[:21]):
# label_color_map[r << 16 | g << 8 | b] = i
label_color_map[b << 16 | g << 8 | r] = i
r, g, b = VOC_COLORMAP[-1]
# label_color_map[r << 16 | g << 8 | b] = 21
# label_color_map[r << 16 | g << 8 | b] = 0
# label_color_map[b << 16 | g << 8 | r] = 21
label_color_map[b << 16 | g << 8 | r] = 0
bgr2label = np.vectorize(label_color_map.get)
img = cv2.imread(label_path).astype(np.int64)
result = bgr2label(img[..., 0] << 16 | img[..., 1] << 8 | img[..., 2]).astype(np.uint8)
print(np.unique(result))
因为最后让你交的图片还是要调色板,但是我们模型输出的一般是0-21的,所以需要调整一下
def get_palette():
return [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, 128, 64, 128, 0, 192, 128, 128, 192, 128, 64, 64, 0, 192, 64, 0, 64,
192, 0, 192, 192, 0, 64, 64, 128, 192, 64, 128, 64, 192, 128, 192, 192, 128, 0, 0, 64, 128, 0, 64, 0, 128,
64, 128, 128, 64, 0, 0, 192, 128, 0, 192, 0, 128, 192, 128, 128, 192, 64, 0, 64, 192, 0, 64, 64, 128, 64,
192, 128, 64, 64, 0, 192, 192, 0, 192, 64, 128, 192, 192, 128, 192, 0, 64, 64, 128, 64, 64, 0, 192, 64, 128,
192, 64, 0, 64, 192, 128, 64, 192, 0, 192, 192, 128, 192, 192, 64, 64, 64, 192, 64, 64, 64, 192, 64, 192,
192, 64, 64, 64, 192, 192, 64, 192, 64, 192, 192, 192, 192, 192, 32, 0, 0, 160, 0, 0, 32, 128, 0, 160, 128,
0, 32, 0, 128, 160, 0, 128, 32, 128, 128, 160, 128, 128, 96, 0, 0, 224, 0, 0, 96, 128, 0, 224, 128, 0, 96,
0, 128, 224, 0, 128, 96, 128, 128, 224, 128, 128, 32, 64, 0, 160, 64, 0, 32, 192, 0, 160, 192, 0, 32, 64,
128, 160, 64, 128, 32, 192, 128, 160, 192, 128, 96, 64, 0, 224, 64, 0, 96, 192, 0, 224, 192, 0, 96, 64, 128,
224, 64, 128, 96, 192, 128, 224, 192, 128, 32, 0, 64, 160, 0, 64, 32, 128, 64, 160, 128, 64, 32, 0, 192,
160, 0, 192, 32, 128, 192, 160, 128, 192, 96, 0, 64, 224, 0, 64, 96, 128, 64, 224, 128, 64, 96, 0, 192, 224,
0, 192, 96, 128, 192, 224, 128, 192, 32, 64, 64, 160, 64, 64, 32, 192, 64, 160, 192, 64, 32, 64, 192, 160,
64, 192, 32, 192, 192, 160, 192, 192, 96, 64, 64, 224, 64, 64, 96, 192, 64, 224, 192, 64, 96, 64, 192, 224,
64, 192, 96, 192, 192, 224, 192, 192, 0, 32, 0, 128, 32, 0, 0, 160, 0, 128, 160, 0, 0, 32, 128, 128, 32,
128, 0, 160, 128, 128, 160, 128, 64, 32, 0, 192, 32, 0, 64, 160, 0, 192, 160, 0, 64, 32, 128, 192, 32, 128,
64, 160, 128, 192, 160, 128, 0, 96, 0, 128, 96, 0, 0, 224, 0, 128, 224, 0, 0, 96, 128, 128, 96, 128, 0, 224,
128, 128, 224, 128, 64, 96, 0, 192, 96, 0, 64, 224, 0, 192, 224, 0, 64, 96, 128, 192, 96, 128, 64, 224, 128,
192, 224, 128, 0, 32, 64, 128, 32, 64, 0, 160, 64, 128, 160, 64, 0, 32, 192, 128, 32, 192, 0, 160, 192, 128,
160, 192, 64, 32, 64, 192, 32, 64, 64, 160, 64, 192, 160, 64, 64, 32, 192, 192, 32, 192, 64, 160, 192, 192,
160, 192, 0, 96, 64, 128, 96, 64, 0, 224, 64, 128, 224, 64, 0, 96, 192, 128, 96, 192, 0, 224, 192, 128, 224,
192, 64, 96, 64, 192, 96, 64, 64, 224, 64, 192, 224, 64, 64, 96, 192, 192, 96, 192, 64, 224, 192, 192, 224,
192, 32, 32, 0, 160, 32, 0, 32, 160, 0, 160, 160, 0, 32, 32, 128, 160, 32, 128, 32, 160, 128, 160, 160, 128,
96, 32, 0, 224, 32, 0, 96, 160, 0, 224, 160, 0, 96, 32, 128, 224, 32, 128, 96, 160, 128, 224, 160, 128, 32,
96, 0, 160, 96, 0, 32, 224, 0, 160, 224, 0, 32, 96, 128, 160, 96, 128, 32, 224, 128, 160, 224, 128, 96, 96,
0, 224, 96, 0, 96, 224, 0, 224, 224, 0, 96, 96, 128, 224, 96, 128, 96, 224, 128, 224, 224, 128, 32, 32, 64,
160, 32, 64, 32, 160, 64, 160, 160, 64, 32, 32, 192, 160, 32, 192, 32, 160, 192, 160, 160, 192, 96, 32, 64,
224, 32, 64, 96, 160, 64, 224, 160, 64, 96, 32, 192, 224, 32, 192, 96, 160, 192, 224, 160, 192, 32, 96, 64,
160, 96, 64, 32, 224, 64, 160, 224, 64, 32, 96, 192, 160, 96, 192, 32, 224, 192, 160, 224, 192, 96, 96, 64,
224, 96, 64, 96, 224, 64, 224, 224, 64, 96, 96, 192, 224, 96, 192, 96, 224, 192, 224, 224, 192]
im = Image.fromarray(output, mode='P') # output为灰度图(0-21)
im.putpalette(get_palette())
im.save(os.path.join(target_path, filename + '.png')