I have the following Cython function
我有以下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)
This is the signature of scan_frame
这是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)
This is how I'm trying to pass an array into detect
这就是我试图将数组传递给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)
This is the error I get...
这是我得到的错误......
Traceback (most recent call last): File "test.py", line 6, in detect(4, 5, a) File "tag36h11_detector.pyx", line 67, in tag36h11_detector.detect cdef detection_payload* detection = scan_frame(width, height, frame) TypeError: expected bytes, numpy.ndarray found
回溯(最近一次调用最后一次):文件“test.py”,第6行,检测(4,5,a)文件“tag36h11_detector.pyx”,第67行,在tag36h11_detector.detect cdef detection_payload * detection = scan_frame(width,高度,框架)TypeError:预期字节,找到numpy.ndarray
2 个解决方案
#1
1
While the internal data of your NumPy array is of type uint8_t
, the array itself is not a pointer, so it does not match the type uint8_t*
. You will need to make a pointer to the NumPy array along the lines of &frame[0]
(the [0]
indicates the 0th element of the array and the &
creates a pointer to it) depending on the internal data structure of the array. Also make sure that the array is C-contiguous by using numpy.asarray or the like.
虽然NumPy数组的内部数据类型为uint8_t,但数组本身不是指针,因此它与uint8_t *类型不匹配。您需要根据数组的内部数据结构,沿&frame [0]([0]指示数组的第0个元素,并创建指向它的指针)的行创建一个指向NumPy数组的指针。还要确保使用numpy.asarray之类的数组是C连续的。
Example
cdef detection_payload* detection = scan_frame(width, height, &frame[0])
#2
0
It is possible to use the method proposed by Capow, but I would advocate to replace the numpy arrays by memoryviews in the cython code, that has the following advantages:
可以使用Capow提出的方法,但我主张用cython代码中的memoryviews替换numpy数组,它具有以下优点:
- The function can be used without numpy and with other classes, which support memory views
- you can ensure, that the memory is continuous
- your cython module does not depend on numpy at all
该函数可以在没有numpy的情况下使用,也可以与支持内存视图的其他类一起使用
你可以确保,记忆是连续的
你的cython模块根本不依赖于numpy
That means:
def detect(width, height, unsigned int[::1] frame not None):
cdef detection_payload* detection = scan_frame(width, height, &frame[0])
...
We still use &frame[0]
to get the pointer.
我们仍然使用&frame [0]来获取指针。
#1
1
While the internal data of your NumPy array is of type uint8_t
, the array itself is not a pointer, so it does not match the type uint8_t*
. You will need to make a pointer to the NumPy array along the lines of &frame[0]
(the [0]
indicates the 0th element of the array and the &
creates a pointer to it) depending on the internal data structure of the array. Also make sure that the array is C-contiguous by using numpy.asarray or the like.
虽然NumPy数组的内部数据类型为uint8_t,但数组本身不是指针,因此它与uint8_t *类型不匹配。您需要根据数组的内部数据结构,沿&frame [0]([0]指示数组的第0个元素,并创建指向它的指针)的行创建一个指向NumPy数组的指针。还要确保使用numpy.asarray之类的数组是C连续的。
Example
cdef detection_payload* detection = scan_frame(width, height, &frame[0])
#2
0
It is possible to use the method proposed by Capow, but I would advocate to replace the numpy arrays by memoryviews in the cython code, that has the following advantages:
可以使用Capow提出的方法,但我主张用cython代码中的memoryviews替换numpy数组,它具有以下优点:
- The function can be used without numpy and with other classes, which support memory views
- you can ensure, that the memory is continuous
- your cython module does not depend on numpy at all
该函数可以在没有numpy的情况下使用,也可以与支持内存视图的其他类一起使用
你可以确保,记忆是连续的
你的cython模块根本不依赖于numpy
That means:
def detect(width, height, unsigned int[::1] frame not None):
cdef detection_payload* detection = scan_frame(width, height, &frame[0])
...
We still use &frame[0]
to get the pointer.
我们仍然使用&frame [0]来获取指针。