如何将3d rgb标签图像(在语义分割中)转换为2d灰度图像,并且类索引从0开始?

时间:2018-10-30 07:19:50

标签: python numpy numpy-broadcasting

我有一个rgb语义分段标签,如果其中有3个类,并且每个RGB值是以下之一:

[255,255,0],[0,255,255],[255,255,255]

分别,然后我想根据dict将rgb文件中的所有值映射到新的2d标签图像中:

{{255,255,0):0,(0,255,255):1,(255,255,255):2}

之后,新的灰色标签文件中的所有值都是0,1或2之一。 是否有解决此问题的有效方法?例如numpy中的广播

4 个答案:

答案 0 :(得分:1)

您可以这样做:

# the three channels
r = np.array([255, 255, 0])
g = np.array([0, 255, 255])
b = np.array([255, 255, 255])

label_seg = np.zeros((img.shape[:2]), dtype=np.int)
label_seg[(img==r).all(axis=2)] = 0
label_seg[(img==g).all(axis=2)] = 1
label_seg[(img==b).all(axis=2)] = 2

那么,如果

img = np.array([[r,g,b],[r,r,r],[b,g,r],[b,g,r]])

然后

label_seg = array([[0, 1, 2],
                   [0, 0, 0],
                   [2, 1, 0],
                   [2, 1, 0]])

答案 1 :(得分:1)

我也在这里回答了这个问题:Convert RGB image to index image

基本上:

cmap = {(255, 255, 0): 0, (0, 255, 255): 1, (255, 255, 255): 2}

def rgb2mask(img):

    assert len(img.shape) == 3
    height, width, ch = img.shape
    assert ch == 3

    W = np.power(256, [[0],[1],[2]])

    img_id = img.dot(W).squeeze(-1) 
    values = np.unique(img_id)

    mask = np.zeros(img_id.shape)

    for c in enumerate(values):
        try:
            mask[img_id==c] = cmap[tuple(img[img_id==c][0])] 
        except:
            pass
    return mask

您可以根据需要扩展字典。

答案 2 :(得分:0)

这个怎么样?

mask_mapping = {
    (255, 255, 0):   0,
    (0, 255, 255):   1,
    (255, 255, 255): 2,
}
for k in mask_mapping:
    label[(label == k).all(axis=2)] = mask_mapping[k]

我认为它与公认的方法基于相同的思想,但是看起来更加清晰。

答案 3 :(得分:0)

我尝试过这个...

首先,我注意到在下表的RGB值中,绿色值都相同,因此没有必要对其进行检查。

第二,如果将数组中的值除以255,则会得到零和一,它们与所需的标签非常接近。因此,如果您做一些数学运算:

t = R/255 + 2B/255 -1

然后您将得到字典中的值:

  R   G   B    t
==================
255 255   0    0
 0  255 255    1
255 255 255    2

与其他几个答案进行比较的代码如下:

#!/usr/bin/env python3

import numpy as np

def me(img): 
    """Return R + 2B - 1 as label"""
    return np.uint8((img[:,:,0]/255) + 2*(img[:,:,2]/255) - 1) 

def deepak(img):
    r = np.array([255, 255, 0])
    g = np.array([0, 255, 255])
    b = np.array([255, 255, 255])

    label_seg = np.zeros((img.shape[:2]), dtype=np.uint8)
    label_seg[(img==r).all(axis=2)] = 0
    label_seg[(img==g).all(axis=2)] = 1
    label_seg[(img==b).all(axis=2)] = 2
    return label_seg

def marios(label):
    mask_mapping = {
       (255, 255, 0):   0,
       (0, 255, 255):   1,
       (255, 255, 255): 2,
    }
    for k in mask_mapping:
        label[(label == k).all(axis=2)] = mask_mapping[k]

    return label

# Generate a sample image
img = np.zeros((480,640,3), dtype=np.uint8)
img[:160,:,:]    = [255,255,0]
img[160:320,:,:] = [0,255,255]
img[320:,:,:]    = [255,255,255]

时机是这样的:

In [134]: %timeit deepak(img)
15.4 ms ± 181 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

In [135]: %timeit marios(img)
15.4 ms ± 166 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

In [172]: %timeit me(img)                                                                           
869 µs ± 8.93 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)each)

虽然注释可以成为帮助:-)

的好方法,但是否值得以18倍的加速比不那么易读的代码更值得一提。

请注意,出于对Deepak的公平考虑,可以通过删除不必要的行将其时间减少到0 10.3毫秒,在该行下方将零数组中的某些元素归零:

label_seg[(img==r).all(axis=2)] = 0