简体   繁体   English

如何使用numpy将RGB图像转换为基于颜色的单热编码3d数组?

[英]How to convert RGB image to one-hot encoded 3d array based on color using numpy?

Simply put, what I'm trying to do is similar to this question: Convert RGB image to index image , but instead of 1-channel index image, I want to get n-channel image where img[h, w] is a one-hot encoded vector. 简单地说,我正在尝试做的是类似于这个问题: 将RGB图像转换为索引图像 ,但不是单通道索引图像,我想得到n通道图像,其中img[h, w]是一个 - 编码矢量。 For example, if the input image is [[[0, 0, 0], [255, 255, 255]] , and index 0 is assigned to black and 1 is assigned to white, then the desired output is [[[1, 0], [0, 1]]] . 例如,如果输入图像为[[[0, 0, 0], [255, 255, 255]] ,并且索引0指定为黑色,1指定为白色,则所需输出为[[[1, 0], [0, 1]]]

Like the previous person asked the question, I have implemented this naively, but the code runs quite slowly, and I believe a proper solution using numpy would be significantly faster. 就像之前提到的问题一样,我已经天真地实现了这个,但是代码运行得非常慢,我相信使用numpy的正确解决方案会明显加快。

Also, as suggested in the previous post, I can preprocess each image into grayscale and one-hot encode the image, but I want a more general solution. 另外,正如上一篇文章中所建议的那样,我可以将每个图像预处理为灰度级并对图像进行单热编码,但我想要一个更通用的解决方案。

Example

Say I want to assign white to 0, red to 1, blue to 2, and yellow to 3: 假设我要将白色指定为0,红色指定为1,蓝色指定为2,黄色指定为3:

(255, 255, 255): 0
(255, 0, 0): 1
(0, 0, 255): 2
(255, 255, 0): 3

, and I have an image which consists of those four colors, where image is a 3D array containing R, G, B values for each pixel: ,我有一个由这四种颜色组成的图像,其中图像是一个3D数组,包含每个像素的R,G,B值:

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

, and this is what I want to get where each pixel is changed to one-hot encoded values of index. ,这就是我想要将每个像素更改为索引的单热编码值。 (Since changing a 2d array of index values to 3d array of one-hot encoded values is easy, getting a 2d array of index values is fine too.) (由于将2d索引值数组更改为单个编码值的3d数组很容易,因此获取2d索引值数组也很好。)

[
    [[1, 0, 0, 0], [1, 0, 0, 0], [0, 1, 0, 0], [0, 1, 0, 0]],
    [[0, 0, 1, 0], [1, 0, 0, 0], [0, 1, 0, 0], [0, 1, 0, 0]],
    [[0, 0, 1, 0], [0, 0, 1, 0], [1, 0, 0, 0], [1, 0, 0, 0]],
    [[1, 0, 0, 0], [1, 0, 0, 0], [0, 0, 0, 1], [0, 0, 0, 1]]
]

In this example I used colors where RGB components are either 255 or 0, but I don't want to solutions rely on that fact. 在这个例子中,我使用了RGB组件为255或0的颜色,但我不希望解决方案依赖于这一事实。

We could generate the decimal equivalents of each pixel color. 我们可以生成每个像素颜色的十进制等值。 With each channel having 0 or 255 as the value, there would be total 8 possibilities, but it seems we are only interested in four of those colors. 每个通道的值为0255 ,总共有8可能性,但似乎我们只对其中的四种颜色感兴趣。

Then, we would have two ways to solve it : 然后,我们将有两种方法来解决它:

  • One would involve making unique indices from those decimal equivalents starting from 0 till the final color, all in sequence and finally initializing an output array and assigning into it. 其中一个将涉及从0开始到最终颜色的十进制等值的唯一索引,全部按顺序进行,最后初始化输出数组并分配到其中。

  • Other way would be to use broadcasted comparisons of those decimal equivalents against the colors. 另一种方法是使用那些十进制等值对比颜色的broadcasted比较。

These two methods are listed next - 接下来列出了这两种方法 -

def indexing_based(a):
    b = (a == 255).dot([4,2,1])  # Decimal equivalents
    colors = np.array([7,4,1,6]) # Define colors decimal equivalents here
    idx = np.empty(colors.max()+1,dtype=int)
    idx[colors] = np.arange(len(colors))
    m,n,r = a.shape
    out = np.zeros((m,n,len(colors)), dtype=int)
    out[np.arange(m)[:,None], np.arange(n), idx[b]] = 1
    return out

def broadcasting_based(a):
    b = (a == 255).dot([4,2,1])  # Decimal equivalents
    colors = np.array([7,4,1,6]) # Define colors decimal equivalents here
    return (b[...,None] == colors).astype(int)

Sample run - 样品运行 -

>>> a = np.array([
...     [[255, 255, 255], [255, 255, 255], [255,   0,   0], [255,   0,   0]],
...     [[  0,   0, 255], [255, 255, 255], [255,   0,   0], [255,   0,   0]],
...     [[  0,   0, 255], [  0,   0, 255], [255, 255, 255], [255, 255, 255]],
...     [[255, 255, 255], [255, 255, 255], [255, 255,   0], [255, 255,   0]],
...     [[255, 255, 255], [255,   0,   0], [255, 255,   0], [255,  0 ,   0]]])
>>> indexing_based(a)
array([[[1, 0, 0, 0],
        [1, 0, 0, 0],
        [0, 1, 0, 0],
        [0, 1, 0, 0]],

       [[0, 0, 1, 0],
        [1, 0, 0, 0],
        [0, 1, 0, 0],
        [0, 1, 0, 0]],

       [[0, 0, 1, 0],
        [0, 0, 1, 0],
        [1, 0, 0, 0],
        [1, 0, 0, 0]],

       [[1, 0, 0, 0],
        [1, 0, 0, 0],
        [0, 0, 0, 1],
        [0, 0, 0, 1]],

       [[1, 0, 0, 0],
        [0, 1, 0, 0],
        [0, 0, 0, 1],
        [0, 1, 0, 0]]])
>>> np.allclose(broadcasting_based(a), indexing_based(a))
True

My solution looks like this and should work for arbitrary colors: 我的解决方案看起来像这样,应该适用于任意颜色:

color_dict = {0: (0,   255, 255),
              1: (255, 255,   0),
              ....}


def rgb_to_onehot(rgb_arr, color_dict):
    num_classes = len(color_dict)
    shape = rgb_arr.shape[:2]+(num_classes,)
    arr = np.zeros( shape, dtype=np.int8 )
    for i, cls in enumerate(color_dict):
        arr[:,:,i] = np.all(rgb_arr.reshape( (-1,3) ) == color_dict[i], axis=1).reshape(shape[:2])
    return arr


def onehot_to_rgb(onehot, color_dict):
    single_layer = np.argmax(onehot, axis=-1)
    output = np.zeros( onehot.shape[:2]+(3,) )
    for k in color_dict.keys():
        output[single_layer==k] = color_dict[k]
    return np.uint8(output)

I haven't tested it for speed yet, but at least, it works :) 我还没有测试它的速度,但至少,它工作:)

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

相关问题 Numpy 数组:如何将二维数组的值转换为 3D 单热数组 - Numpy array : how to convert values of a 2D array into a 3D one-hot array 整数到位数组,然后返回整数(基于RGB图像中的位值的((多)一次热编码)) - Integer to array of bits and back to integer ((multi)-one-hot encoding based on bit values in RGB image) 将二维 numpy 数组转换为热编码 3D numpy 数组,在同一平面上具有相同的值 - Convert a 2D numpy array into a hot-encoded 3D numpy array, with same values in the same plane 如何使用矢量化快速解码 one-hot 编码的 NumPy 矩阵? - How do I decode a one-hot encoded NumPy matrix in a fast manner using vectorization? 如何将分隔值转换为单热编码列? - How to convert separated values into one-hot encoded columns? 如何在不更改图像的情况下将 3d RGB NumPy 数组转换为浮动? - How to convert a 3d RGB NumPy array to float without changing the image? 如何将jpg图像加载到3d rgb numpy数组 - How to load a jpg image to a 3d rgb numpy array 如何使用 Numpy 对字符串数组进行一次热编码? - How do I one-hot encode an array of strings with Numpy? 基于复杂的逻辑表达式创建新的numpy一键编码矩阵? - Create new numpy one-hot encoded matrix based on complex logical expression? One-Hot Encode numpy array > 2 dims - One-Hot Encode numpy array with >2 dims
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM