2013-11-20 5 views
6

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

В частности, я использую 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 

ответ

5

Похожие Биллу выше, но, вероятно, еще быстрее:

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

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

asarray принимает еще несколько вещей: «Входные данные в любой форме, которые могут быть преобразованы в массив. Сюда входят списки, списки кортежей, кортежи, кортежи кортежей, кортежи списков и ndarrays». Он берет кортежи напрямую :)

+0

Это действительно немного быстрее (для моего текущего использования это примерно на 10% быстрее, чем решение, предложенное Биллом). – golmschenk

5

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

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

Например, пусть ('Ri', 'Gi', 'Bi', 'ai') быть цвет кортеж, соответствующий пикселю 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') 
Смежные вопросы