【问题标题】:Passing 1D numpy array to Cython function将一维 numpy 数组传递给 Cython 函数
【发布时间】:2017-10-01 21:00:21
【问题描述】:

我有以下 Cython 函数

def detect(width, height, np.ndarray[np.uint8_t, ndim=1] frame):
    cdef detection_payload* detection = scan_frame(width, height, frame)
    return DetectionPayload()._setup(detection)

这是scan_frame的签名

cdef extern from "tag36h11_detector/tag36h11_detector.h":
    cdef struct detection_payload:
        int size
        apriltag_detection_t* detections
    ctypedef detection_payload detection_payload_t
    detection_payload* scan_frame(int width, int height, uint8_t* data)

这就是我尝试将数组传递给detect的方式

// test.py
from tag36h11_detector import detect
import numpy as np

a = np.array([1,2,3], dtype=np.uint8)

detect(4, 5, a)

这是我得到的错误...

Traceback(最近一次调用最后一次): 文件“test.py”,第 6 行,在 检测(4, 5, a) 文件“tag36h11_detector.pyx”,第 67 行,在 tag36h11_detector.detect 中 cdef detection_payload* detection = scan_frame(width, height, frame) 类型错误:预期字节,找到 numpy.ndarray

【问题讨论】:

标签: python numpy cython


【解决方案1】:

虽然 NumPy 数组的内部数据是 uint8_t 类型,但数组本身不是指针,因此它与 uint8_t* 类型不匹配。根据数组的内部数据结构,您需要沿 &frame[0] 的行创建指向 NumPy 数组的指针([0] 表示数组的第 0 个元素,& 创建指向它的指针) .还要通过使用numpy.asarray 等来确保数组是 C 连续的。

例子

cdef detection_payload* detection = scan_frame(width, height, &frame[0])

【讨论】:

    【解决方案2】:

    可以使用Capow提出的方法,但是我主张在cython代码中用memoryviews代替numpy数组,有以下优点:

    1. 该函数可以在没有 numpy 的情况下使用,也可以与其他支持内存视图的类一起使用
    2. 你可以保证,内存是连续的
    3. 你的 cython 模块根本不依赖于 numpy

    这意味着:

    def detect(width, height, unsigned int[::1] frame not None):
        cdef detection_payload* detection = scan_frame(width, height, &frame[0])
        ...
    

    我们仍然使用&frame[0] 来获取指针。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多