Numpy图像数组:如何高效地从RGB转换为十六进制

3

我一直在使用嵌套的for循环将RGB图像转换为十六进制值的图像数组,但对于大型图像来说速度太慢了。有没有人知道快速的方法或库,可以帮助我在RGB和HEX之间快速切换?

编辑: @ragingSloth

这是我想到的,但对于我所需的东西来说速度太慢了:

def rgb_to_hex(array):
    (x, y, z) = array.shape
    for v in range(0, x):
        for u in range(0, y):
            array[v, u] = int('%02x%02x%02x' % (array[v, u, 0], array[v, u, 1], array[v, u, 2]))

2
你是怎么做的呢?OpenCV可能有适合你的东西。 - ragingSloth
我必须承认,我不是世界上最擅长Python的人,所以我必须问一下:什么是十六进制图像? - beaker
@beaker,我指的是RGB颜色的十六进制值。例如,RGB(123, 456, 789)在十六进制中为7BFFFF。如果您不了解十六进制颜色,这可能会有所帮助:http://www.javascripter.net/faq/rgbtohex.htm。 - user2909415
1
所以你想要获取3个RGB值并将它们打包成一个整数? - beaker
2
@beaker 是的,那是真正的目标。如果您可以将其作为六位小数完成,我也可以使用它,但是想法是从3个RGB到一个单一的整数。 - user2909415
显示剩余3条评论
3个回答

5
使用Beaker的想法,您还可以消除双重for循环:
def tohex(array):
    array = np.asarray(array, dtype='uint32')
    return ((array[:, :, 0]<<16) + (array[:, :, 1]<<8) + array[:, :, 2])

非常酷!我喜欢向量化的位。我想我需要更深入地了解Python!:D - beaker

4

字符串操作可能会比较慢。一种直接的数学方法是:

array[v, u] = ((array[v, u, 0]<<16) + (array[v, u, 1]<<8) + array[v, u, 2])

这将RGB表示中的3个字节合并为一个整数:

>>> A = [123, 255, 255]
>>> B = (A[0]<<16) + (A[1]<<8) + A[2]
>>> B
8126463
>>> hex(B)
'0x7bffff'

1

不确定是否更快,但你可以这样做:

hexarr = np.vectorize('{:02x}'.format)

然后在RGB数组上运行它:

In [67]: a = (np.random.rand(2,5,3)*255).astype('u1')

In [68]: a
Out[68]:
array([[[149, 145, 203],
        [210, 234, 219],
        [223,  50,  26],
        [166,  34,  65],
        [213,  78, 115]],

       [[191,  54, 168],
        [ 85, 235,  36],
        [180, 140,  96],
        [127,  21,  24],
        [166, 210, 128]]], dtype=uint8)

In [69]: hexarr(a)
Out[69]:
array([[['95', '91', 'cb'],
        ['d2', 'ea', 'db'],
        ['df', '32', '1a'],
        ['a6', '22', '41'],
        ['d5', '4e', '73']],

       [['bf', '36', 'a8'],
        ['55', 'eb', '24'],
        ['b4', '8c', '60'],
        ['7f', '15', '18'],
        ['a6', 'd2', '80']]],
      dtype='|S2')

您可以使用view来折叠第三个维度:
In [71]: hexarr(a).view('S6')
Out[71]:
array([[['9591cb'],
        ['d2eadb'],
        ['df321a'],
        ['a62241'],
        ['d54e73']],

       [['bf36a8'],
        ['55eb24'],
        ['b48c60'],
        ['7f1518'],
        ['a6d280']]],
      dtype='|S6')

不幸的是,这似乎并没有快多少(只是快了两倍左右):

In [89]: timeit rgb_to_hex(a)
1 loops, best of 3: 6.83 s per loop

In [90]: timeit hexarr(a).view('S6')
1 loops, best of 3: 2.54 s per loop

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接