tags:

views:

553

answers:

1

I find the astype() method of numpy arrays not very efficient. I have an array containing 3 million of Uint8 point. Multiplying it by a 3x3 matrix takes 2 second, but converting the result from uint16 to uint8 takes another second.

More precisely :

    print time.clock()
    imgarray = np.dot(imgarray,  M)/255
    print time.clock()
    imgarray = imgarray.clip(0, 255)
    print time.clock()
    imgarray = imgarray.astype('B')
    print time.clock()

dot product and scaling takes 2 sec
clipping takes 200 msec type conversion takes 1 sec

Given the time taken by the other operations, I would expect astype to be faster. Is there a faster way to do type conversion, or am I wrong when guesstimating that type conversion should not be that hard ?

Edit : the goal is to save the final 8 bit array to a file

+3  A: 

When you use imgarray = imgarray.astype('B'), you get a copy of the array, cast to the specified type. This requires extra memory allocation, even though you immediately flip imgarray to point to the newly allocated array.

If you use imgarray.view('uint8'), then you get a view of the array. This uses the same data except that it is interpreted as uint8 instead of imgarray.dtype. (np.dot returns a uint32 array, so after the np.dot, imgarray is of type uint32.)

The problem with using view, however, is that a 32-bit integer becomes viewed as 4 8-bit integers, and we only care about the value in the last 8-bits. So we need to skip to every 4th 8-bit integer. We can do that with slicing:

imgarray.view('uint8')[:,::4]

IPython's %timeit command shows there is a significant speed up doing things this way:

In [37]: %timeit imgarray2 = imgarray.astype('B')
10000 loops, best of 3: 107 us per loop

In [39]: %timeit imgarray3 = imgarray.view('B')[:,::4]
100000 loops, best of 3: 3.64 us per loop
unutbu
Can I save this view to a file
shodanex
@shodanex: Yes, you could use np.save(). See http://docs.scipy.org/doc/numpy-1.3.x/reference/generated/numpy.save.html
unutbu
@shodanex: For other format options, see also http://docs.scipy.org/doc/numpy-1.3.x/reference/routines.io.html
unutbu
it is then implicitly architecture-dependent, since which slice to use depends on endianness.
kaizer.se
@kaizer.se: Yes, that's true. Do you know a nice way to make the code non-architecture-dependent?
unutbu