0

I have the following Cython function

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

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

// 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

2

2 Answers 2

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.

Example

cdef detection_payload* detection = scan_frame(width, height, &frame[0])
Sign up to request clarification or add additional context in comments.

Comments

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:

  1. The function can be used without numpy and with other classes, which support memory views
  2. you can ensure, that the memory is continuous
  3. your cython module does not depend on numpy at all

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.