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')