Reputation: 1029
I have been using nested for loops to turn RGB images into an image array of Hex values, but it is too slow for large images. Does anyone know a quick way and or a library that can help me switch back and from RGB to HEX?
edit: @ragingSloth
This is what I came up with but it is too slow for what I need:
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]))
Upvotes: 3
Views: 2335
Reputation: 880677
Using beaker's idea, you can also eliminate the double for-loop:
def tohex(array):
array = np.asarray(array, dtype='uint32')
return ((array[:, :, 0]<<16) + (array[:, :, 1]<<8) + array[:, :, 2])
Upvotes: 6
Reputation: 46578
Not sure if this is much faster, but you could do something like this:
hexarr = np.vectorize('{:02x}'.format)
And then run it on an RGB array:
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')
You can collapse the third dimension with view
:
In [71]: hexarr(a).view('S6')
Out[71]:
array([[['9591cb'],
['d2eadb'],
['df321a'],
['a62241'],
['d54e73']],
[['bf36a8'],
['55eb24'],
['b48c60'],
['7f1518'],
['a6d280']]],
dtype='|S6')
Unfortunately, this doesn't seem to be a whole lot faster (just over twice as fast):
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
Upvotes: 1
Reputation: 16811
String operations are probably pretty slow. A direct mathematical approach would be:
array[v, u] = ((array[v, u, 0]<<16) + (array[v, u, 1]<<8) + array[v, u, 2])
This combines the 3 bytes of the RGB representation into a single int:
>>> A = [123, 255, 255]
>>> B = (A[0]<<16) + (A[1]<<8) + A[2]
>>> B
8126463
>>> hex(B)
'0x7bffff'
Upvotes: 5