繁体   English   中英

根据颜色值将多维Numpy数组转换为二维数组

[英]Convert multi-dimensional Numpy array to 2-dimensional array based on color values

我有一个图像,它被读取为形状为(512,512,3)的uint8数组。 现在,我想将此数组转换为形状为(512,512,1)的uint8数组,其中第三轴上的每个像素值都从颜色值[255,0,0]转换为单个类标签值[3] ,基于以下颜色/类编码:

1 : [0, 0, 0], 
 2 : [0, 0, 255], 
 3 : [255, 0, 0], 
 4 : [150, 30, 150], 
 5 : [255, 65, 255], 
 6 : [150, 80, 0], 
 7 : [170, 120, 65], 
 8 : [125, 125, 125], 
 9 : [255, 255, 0], 
 10 : [0, 255, 255], 
 11 : [255, 150, 0], 
 12 : [255, 225, 120], 
 13 : [255, 125, 125], 
 14 : [200, 100, 100], 
 15 : [0, 255, 0], 
 16 : [0, 150, 80], 
 17 : [215, 175, 125], 
 18 : [220, 180, 210], 
 19 : [125, 125, 255]

最有效的方法是什么? 我想遍历所有类并使用numpy.where ,但这显然很耗时。

您可以使用巨型查询表。 令cls为dtype=np.uint8 [[0,0,0], [0,0,255], ...]

LUT = np.zeros(size=(256,256,256), dtype='u1')
LUT[cls[:,0],cls[:,1],cls[:,2]] = np.arange(cls.shape[1])+1
img_as_cls = LUT[img[...,0],img[...,1], img[...,2]]

该解决方案是每个像素O(1)。 这也是非常有效的缓存,因为实际上使用了LUT中的一小部分条目。 处理我的机器上的1000x1000图像大约需要10毫秒。

通过将3色通道转换为24位整数可以稍微改善该解决方案。 这是代码

def scalarize(x):
    # compute x[...,2]*65536+x[...,1]*256+x[...,0] in efficient way
    y = x[...,2].astype('u4')
    y <<= 8
    y +=x[...,1]
    y <<= 8
    y += x[...,0]
    return y
LUT = np.zeros(2**24, dtype='u1')
LUT[scalarize(cls)] = 1 + np.arange(cls.shape[0])
simg = scalarize(img)
img_to_cls = LUT[simg]

优化后,大约需要5毫秒来处理1000x1000的图像。

这是一个基于views -

# https://stackoverflow.com/a/45313353/ @Divakar
def view1D(a, b): # a, b are arrays
    # This function gets 1D view into 2D input arrays
    a = np.ascontiguousarray(a)
    b = np.ascontiguousarray(b)
    void_dt = np.dtype((np.void, a.dtype.itemsize * a.shape[-1]))
    return a.view(void_dt).ravel(),  b.view(void_dt).ravel()

def img2label(a, maps):
    # Get one-dimension reduced view into input image and map arrays.
    # We need to reshape image to 2D, then feed it to view1D to get 1D
    # outputs and then reshape 1D image to 2D 
    A,B = view1D(a.reshape(-1,a.shape[-1]),maps)
    A = A.reshape(a.shape[:2])

    # Trace back positions of A in B using searchsorted. This gives us
    # original order, which is the final output.
    sidx = B.argsort()
    return sidx[np.searchsorted(B,A,sorter=sidx)]

给定标签从1开始,您可能希望将1添加到输出中。

样品运行-

In [100]: # Mapping array
     ...: maps = np.array([[0, 0, 0],[0, 0, 255],\
     ...:                  [255, 0, 0],[150, 30, 150]],dtype=np.uint8)
     ...: 
     ...: # Setup random image array
     ...: idx = np.array([[0,2,1,3],[1,3,2,0]])
     ...: img = maps[idx]

In [101]: img2label(img, maps) # should retrieve back idx
Out[101]: 
array([[0, 2, 1, 3],
       [1, 3, 2, 0]])

一种方法:分别使用True值创建布尔数组,其中输入的像素值与调色板值之一匹配,然后使用算术对其进行组合。 从而:

palette = [
    [0, 0, 0], 
    [0, 0, 255], 
    [255, 0, 0],
    # etc.
]

def palettized(data, palette):
    # Initialize result array
    shape = list(data.shape)
    shape[-1] = 1
    result = np.zeros(shape)
    # Loop and add each palette index component.
    for value, colour in enumerate(palette, 1):
        result += (data == colour).all(axis=2) * value
    return result

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM