Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

I'm trying to find an efficient way to convert from a tuple (where every 4 entries correspond to R, G, B, alpha of a pixel) to a NumPy array (for use in OpenCV).

More specifically, I'm using pywin32 to get the client area bitmap of a window. This is returned in the form of a tuple where the first four elements belong to the RGB-alpha channels of the first pixel, then the next four of the second pixel, and so on. The tuple itself only contains the integer data (i.e. it does not contain any dimensionality, although, I do have that information). From this tuple I want to create NumPy 3D array (width x height x channel). Currently, I'm simply creating an array of zeros, then walking through every entry in the tuple and putting it in place in the NumPy array. I'm doing this using the code below. And I'm hoping that there may be a significantly more efficient way to do this that I'm just not thinking of. Any suggestions? Thank you much!

Code:

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
share|improve this question

2 Answers 2

up vote 3 down vote accepted

Similar to Bill above, but likely even faster:

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

array takes, according to the docs: "An array, any object exposing the array interface, an object whose __array__ method returns an array, or any (nested) sequence."

asarray takes a few more things: "Input data, in any form that can be converted to an array. This includes lists, lists of tuples, tuples, tuples of tuples, tuples of lists and ndarrays." It takes tuples directly :)

share|improve this answer
    
This is indeed slightly faster (for my current use it's about 10% faster then the solution proposed by Bill). –  golmschenk Nov 20 '13 at 23:08

Why not just do something like

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

For example, let ('Ri', 'Gi', 'Bi', 'ai') be the color tuple corresponding to pixel i. If you have a large tuple of these, you can do:

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

Each slice [:,:,i] for i in [0,4) will give you each channel:

In [15]: np.array(x).reshape(2, 2, 4)[:,:,0]
Out[15]: 
array([['R1', 'R2'],
       ['R3', 'R4']], 
      dtype='|S2')
share|improve this answer
    
Beautiful. So simple and is 5x faster for my current use. –  golmschenk Nov 20 '13 at 22:57

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.