Передача представлений памяти Cython в функции OpenCV
Я использую представления памяти Cython для ссылки на некоторые изображения в градациях серого. Я успешно использовал это в некотором коде обработки изображений, который я написал. Теперь мне нужно использовать некоторые функции OpenCV. К сожалению, я вижу, что не могу передать просмотры памяти в качестве аргументов изображения функциям OpenCV. Код компилируется, но когда он выполняется, он останавливается на вызове функции OpenCV с "TypeError: не является пустым массивом"
Я могу преобразовать представление памяти обратно в массив с np.asarray(my_memoryview). Это работает, но копирует данные и работает медленно.
В документации по просмотру памяти они говорят о принуждении к numpy http://docs.cython.org/src/userguide/memoryviews.html, и мне кажется, что я должен быть в состоянии заставить представление памяти к numpy массив без копирования памяти. Однако, если я напишу:
im = np.asarray(<np.uint8_t[:, :]> my_memoryview)
это приводит к ошибке компиляции: "Может создавать только cython.array из указателя или массива"
Будем весьма благодарны за любую помощь в том, как передать представление памяти в функцию OpenCV или как принудительно преобразовать представление памяти в пустой массив без копирования данных!
1 ответ
Numpy/OpenCV не берет обзоры памяти, но требует устаревшего предшественника. Вы можете создать класс-оболочку:
from cython.view cimport memoryview
cdef extern from "Python.h":
object PyLong_FromVoidPtr(void *p)
cdef class OpenCVMemoryView:
cdef object arr
cdef object underlying_object
def __init__(OpenCVMemoryView self, np.uint8_t[:, :] my_memoryview):
self.underlying_object = my_memoryview # prevents GC of my_memoryview
cdef memoryview my_memoryview_c = my_memoryview
self.arr = dict(version=3,
typestr='<u1', #typestr=np.uint8,
data=(PyLong_FromVoidPtr(<void*>my_memoryview_c.view.buf), False),
strides=my_memoryview.strides,
shape=my_memoryview.shape)
def __array_interface__(self):
return self.arr
Объект памяти Cython имеет атрибуты, которые возвращают кортежи, подобные тем __array_interface__
требует.
Если это не так быстро, я бы сделал вывод, что ваше решение уже не копирует данные.