NumPy-эффективное преобразование из кортежа в массив?

Я пытаюсь найти эффективный способ преобразования из кортежа (где каждые 4 записи соответствуют R, G, B, alpha пикселя) в массив NumPy (для использования в OpenCV).

более конкретно, я использую pywin32 для получения растрового изображения клиентской области окна. Это возвращается в виде кортежа, где первые четыре элемента принадлежат RGB-Альфа-каналам первого пикселя, затем следующим четырем второго пикселя и так далее. Сам кортеж содержит только целочисленные данные (т. е. он не содержит никакой размерности, хотя у меня есть эта информация). Из этого кортежа я хочу создать массив NumPy 3D (ширина x Высота x канал). В настоящее время я просто создаю массив нулей, затем просматриваю каждую запись в кортеже и помещаю ее в массив NumPy. Я делаю это, используя код ниже. И я надеюсь, что может быть значительно более эффективный способ сделать это, что я просто не думали. Есть предложения? Спасибо много!

код:

bitmapBits = dataBitmap.GetBitmapBits(False) #Gets the tuple.
clientImage = numpy.zeros((height, width, 4), numpy.uint8)
iter_channel = 0
iter_x = 0
iter_y = 0
for bit in bitmapBits:
    clientImage[iter_y, iter_x, iter_channel] = bit
    iter_channel += 1
    if iter_channel == 4:
        iter_channel = 0
        iter_x += 1
    if iter_x == width:
        iter_x = 0
        iter_y += 1
    if iter_y == height:
        iter_y = 0

2 ответов


подобно Биллу выше, но, вероятно, еще быстрее:

clientImage = np.asarray(bitmapBits, dtype=np.uint8).reshape(height, width, 4)

array принимает, согласно документам: "массив, любой объект, подвергающий интерфейс массива, объект,__array__ метод возвращает массив или любую (вложенную) последовательность."

asarray принимает еще несколько вещей: "входные данные, в любой форме, которая может быть преобразована в массив. Это включает списки, списки кортежей, кортежи, кортежи кортежей, кортежи, списки и ndarrays."Он принимает кортежи непосредственно:)


почему бы просто не сделать что-то вроде

import numpy as np
clientImage = np.array(list(bitmapBits), np.uint8).reshape(height, width, 4)

например,('Ri', 'Gi', 'Bi', 'ai') быть цветовым кортежем, соответствующим pixel i. Если у вас есть большой кортеж из них, вы можете сделать:

In [9]: x = ['R1', 'G1', 'B1', 'a1', 'R2', 'G2', 'B2', 'a2', 'R3', 'G3', 'B3', 'a3', 'R4', 'G4', 'B4', 'a4']

In [10]: np.array(x).reshape(2, 2, 4)
Out[10]: 
array([[['R1', 'G1', 'B1', 'a1'],
        ['R2', 'G2', 'B2', 'a2']],

       [['R3', 'G3', 'B3', 'a3'],
        ['R4', 'G4', 'B4', 'a4']]], 
      dtype='|S2')

каждый ломтик [:,:,i] на i in [0,4) даст вам каждый канал:

In [15]: np.array(x).reshape(2, 2, 4)[:,:,0]
Out[15]: 
array([['R1', 'R2'],
       ['R3', 'R4']], 
      dtype='|S2')