3

I'm trying to write a fast non copy interface for my python binding of a commercial image processing library. I implemented the new-style buffer api protocol which looks ok according to memoryview():

import hirsch as H
import numpy as np

w,h = 7,5
img = H.HImage.GenImageConst('byte',w,h)
m = memoryview(img)
print 'ndim shape=',m.ndim,m.shape
# -> 2 (5L, 7L)

What I don't understand is why numpy doesn't catch this interface?

a = np.array(img)
print 'ndim size shape=',a.ndim,a.size,a.shape
# -> 0 1 ()

Am I doing something wrong, or should I just resort to using the numpy array interface, which works, though it copies the data?

Note that I'm using python 2.7

fish2000
  • 4,289
  • 2
  • 37
  • 76
Dov Grobgeld
  • 4,783
  • 1
  • 25
  • 36
  • It may be that there's something surprising going on --- but it's difficult to say what without knowing what is in your implementation of `bf_getbuffer` and `bf_releasebuffer`. The new buffer interface is supposed to work also on Python 2.x (indeed: `np.array(memoryview('asd')) == np.array([ 97, 115, 100], dtype=np.uint8)`. (Note also that the Numpy array interface does not need to copy the data.) – pv. Aug 17 '14 at 14:03

2 Answers2

3

The np.array function expects an array-like object, not a buffer:

array(object, dtype=None, copy=True, order=None, subok=False, ndmin=0)

Create an array.

object : array_like
An array, any object exposing the array interface, an object whose __array__ method returns an array, or any (nested) sequence.

If you want to create an array from a buffer you should use np.frombuffer:

frombuffer(buffer, dtype=float, count=-1, offset=0)

Interpret a buffer as a 1-dimensional array.

buffer : buffer_like
An object that exposes the buffer interface.

Currently your object, as far as numpy is concerned, is a scalar:

In [7]: a=np.array(1)

In [8]: a.ndim,a.size,a.shape
Out[8]: (0, 1, ())
Bakuriu
  • 98,325
  • 22
  • 197
  • 231
  • If the new buffer is the standard python interface, I'm surprised that np array does not support it! I figured out that the following line can be used for the conversion: `a = np.frombuffer(m.tobytes(),{'i8':'i1'}[m.format]).reshape(m.shape)`. But it also involves copying in m.tobytes(). – Dov Grobgeld Aug 17 '14 at 07:57
  • The new buffer interface is supported also in `np.array`: `np.array(memoryview(np.array([1,2,3]))).shape == (3,)`. The reason for the difference may be in the implementation of the custom object's getbuffer... – pv. Aug 17 '14 at 14:00
  • I got it to work in the end. One issue that confused me is that you need to use the `copy=False` argument to `np.array()` in order to get a reference to the same memory. – Dov Grobgeld Aug 25 '14 at 16:55
0

You may also try np.asarray. I had success with it but I don't have access to hirsch so I can't test it.

BTW, Bakuriu has it right: you are creating a scalar array (ndim 0, size 1) of type np.object.

Pierre de Buyl
  • 7,074
  • 2
  • 16
  • 22