Numpy Image Arrays: как эффективно переключаться с RGB на Hex

Я использовал вложенные циклы 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]))

3 ответа

Решение

Используя идею мензурки, вы также можете исключить двойной цикл for:

def tohex(array):
    array = np.asarray(array, dtype='uint32')
    return ((array[:, :, 0]<<16) + (array[:, :, 1]<<8) + array[:, :, 2])

Строковые операции, вероятно, довольно медленные. Прямой математический подход будет:

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

Это объединяет 3 байта RGB-представления в одно целое:

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

Не уверен, что это намного быстрее, но вы могли бы сделать что-то вроде этого:

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
Другие вопросы по тегам