【问题标题】:Passing cython memoryviews to OpenCV functions将 cython 内存视图传递给 OpenCV 函数
【发布时间】:2012-10-10 19:32:06
【问题描述】:

我正在使用 cython memoryviews 来引用一些灰度图像。我已经在我编写的一些图像处理代码中成功地使用了它。现在,我需要使用一些 OpenCV 函数。 不幸的是,我发现我无法将内存视图作为图像参数传递给 OpenCV 函数。代码可以编译,但运行时会在 OpenCV 函数调用处停止,并显示“TypeError: is not a numpy array”

我可以使用 np.asarray(my_memoryview) 将 memoryview 转换回 numpy 数组。这可行,但它复制数据并且速度很慢。

在 memoryview 文档中,他们谈到强制转换为 numpy http://docs.cython.org/src/userguide/memoryviews.html#coercion-to-numpy 似乎我应该能够在不复制内存的情况下将 memoryview 强制为 numpy 数组。但是,如果我写:

im = np.asarray(<np.uint8_t[:, :]> my_memoryview)

导致编译错误:“Can only create cython.array from pointer or array”

任何有关如何将 memoryview 传递给 OpenCV 函数,或如何在不复制数据的情况下将 memoryview 强制转换为 numpy 数组的帮助将不胜感激!

【问题讨论】:

  • 你从哪里得到原始内存视图?
  • 我从一个numpy数组(这是一个openCV图像)中得到原始的memoryview如下: cdef np.uint8_t[:, ::1] im2 = im 然后我操作im2,基本上提取了一个子窗口(a memoryview) 然后我传递给 cv2.matchTemplate 目前我正在使用 np.asarray(subwindow) 因为我无法直接传递 memoryview。我想我可能误解了强制转换为 numpy 文档示例,在该示例中,他们将指针转换为 memoryview,然后使用 np.asarray 将其转换为 numpy 数组,这与我正在做的相同。但是,我不确定它是强制还是复制。

标签: opencv numpy cython memoryview


【解决方案1】:

Numpy/OpenCV 不使用内存视图,但需要 legacy precursor。您可以创建一个包装类:

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 memoryview object 具有返回元组的属性,如 __array_interface__ 所要求的。

如果这不是更快,我会推断您的解决方案已经不是复制数据。

【讨论】:

  • 感谢您的回答。我想试试你的建议,但是当我编译你的代码时,我得到了我无法通过的错误,错误在data=PyLong_FromVoidPtr(&lt;void*&gt;my_memoryview.view.buf) 我得到memoryview_opencv.pyx:13:51: Casting temporary Python object to non-numeric non-Python type 你知道如何解决这个问题吗?
  • 嗨,martinako,中间变量my_memoryview_c(具有不同的 Cython 类型)部分有效。我稍微编辑了我的答案,但我的电脑在我开始工作之前就崩溃了。如果你得到expected a readable buffer interface,你可能需要使用注释掉的typestr
  • 嗨,现在它构建了,但是在将 OpenCVMemoryView 传递给 cv2.matchTemplate 时出现运行时错误:TypeError: &lt;unknown&gt; is not a numpy array 我已经尝试了注释的 typestr,它没有任何区别。
  • 好吧,现在我确信 np.asarray 没有复制数据。我使用 np.asarray 将 memoryview 转换为 ndarray,然后修改了原始 memoryview,修改显示在转换后的 ndarray 中。 @r3m0t 非常感谢您的帮助,我仍然想测试这个 OpenCVMemoryView 类,也许这种内存视图的包装比使用 asarray 创建的更快?另一方面,我最初的问题是错误的,因为我虽然 np.asarray 复制了数据,这就是问题的动机。我想我需要编辑问题并解释情况并非如此。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多