【问题标题】:New style python buffer protocol and numpy arrays新型 python 缓冲区协议和 numpy 数组
【发布时间】:2014-08-17 06:41:29
【问题描述】:

我正在尝试为我的商业图像处理库的 python 绑定编写一个快速的非复制接口。我实现了根据 memoryview() 看起来不错的新型缓冲区 api 协议:

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)

我不明白的是为什么numpy没有捕捉到这个接口?

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

我是不是做错了什么,还是我应该求助于使用 numpy 数组接口,虽然它会复制数据,但它可以工作?

请注意,我使用的是 python 2.7

【问题讨论】:

  • 可能发生了一些令人惊讶的事情 --- 但如果不知道您的 bf_getbufferbf_releasebuffer 的实现是什么,就很难说出什么。新的缓冲区接口应该也适用于 Python 2.x(实际上是:np.array(memoryview('asd')) == np.array([ 97, 115, 100], dtype=np.uint8)。(另请注意,Numpy 数组接口不需要复制数据。)

标签: python python-2.7 numpy python-c-api pep3118


【解决方案1】:

np.array 函数需要一个 类数组 对象,而不是缓冲区:

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

创建一个数组。

对象:array_like
一个数组,任何暴露数组接口的对象,一个 其__array__ 方法返回一个数组或任何对象的对象 (嵌套)序列。

如果你想从缓冲区创建一个数组,你应该使用np.frombuffer:

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

将缓冲区解释为一维数组。

缓冲区:buffer_like
一个暴露缓冲区接口的对象。

目前,就 numpy 而言,您的对象是一个标量:

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

In [8]: a.ndim,a.size,a.shape
Out[8]: (0, 1, ())

【讨论】:

  • 如果新缓冲区是标准的python接口,我很惊讶np数组不支持它!我发现以下行可用于转换:a = np.frombuffer(m.tobytes(),{'i8':'i1'}[m.format]).reshape(m.shape)。但它也涉及复制 m.tobytes()。
  • np.array: np.array(memoryview(np.array([1,2,3]))).shape == (3,) 也支持新的缓冲区接口。产生差异的原因可能是自定义对象的getbuffer的实现...
  • 我终于让它工作了。让我感到困惑的一个问题是,您需要使用np.array()copy=False 参数才能获得对同一内存的引用。
【解决方案2】:

您也可以试试np.asarray。我已经成功了,但我无法访问 hirsch,所以我无法对其进行测试。

顺便说一句,Bakuriu 说得对:您正在创建一个 np.object 类型的标量数组 (ndim 0, size 1)。

【讨论】:

    猜你喜欢
    • 2010-12-15
    • 1970-01-01
    • 1970-01-01
    • 2011-09-18
    • 2010-11-28
    • 1970-01-01
    • 1970-01-01
    • 2021-12-19
    • 2011-11-15
    相关资源
    最近更新 更多