2012-10-10 54 views
4

我使用cython memoryviews來引用一些灰度圖像。我已經在我編寫的一些圖像處理代碼中成功地使用了它。現在,我需要使用一些OpenCV功能。 不幸的是,我發現我無法將這些memoryviews作爲圖像參數傳遞給OpenCV函數。代碼編譯,但當它運行它停止在OpenCV函數調用與「TypeError:不是一個numpy陣列」將Cyclic Memoryviews傳遞給OpenCV函數

我可以將memoryview轉換回numpy陣列與np.asarray(my_memoryview)。這工作,但它複製數據,速度很慢。

在memoryview文檔中,他們談論的是強制轉換爲http://docs.cython.org/src/userguide/memoryviews.html#coercion-to-numpy ,好像我應該能夠在沒有複製內存的情況下將內存視圖強制轉換爲numpy數組。但是,如果我寫:

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

它會導致編譯錯誤:「只能創建指針或數組cython.array」

關於如何將memoryview傳遞給函數OpenCV的任何幫助,或如何強制內存視圖到一個numpy數組而不復制數據將不勝感激!

+0

你從哪裏得到原始的內存視圖? – r3m0t

+0

我得到一個numpy數組(這是一個openCV圖像)的原始memoryview像這樣: cdef np.uint8_t [:,:1] im2 = im 然後,我操作im2,基本上提取一個子窗口(一個memoryview)然後我傳遞給cv2.matchTemplate此刻我使用np.asarray(子窗口),因爲我無法直接傳遞memoryview。 我想我可能錯誤地解釋了numpy文檔示例的強制性,在這個示例中,他們將一個指向memoryview的指針,然後用np.asarray將其轉換爲numpy數組,這與我正在做的是相同的。但是,我不確定它是強制還是複製。 – martinako

回答

5

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__需要的元組的屬性。

如果這不是更快,我會推斷您的解決方案已經不復制數據。

+0

感謝您的回答。我想試試你的建議是什麼,但是當我編譯代碼我得到和錯誤,我無法通過,錯誤是'數據= PyLong_FromVoidPtr( my_memoryview.view.buf)' 我得到 'memoryview_opencv .pyx:13:51:將臨時Python對象投射到非數字非Python類型上 你知道如何解決這個問題嗎? – martinako

+0

嗨martinako,中間變量'my_memoryview_c'(具有不同的Cython類型),該部分工作。我編輯了我的答案,但是我的電腦在我工作之前崩潰了。如果你得到'預計可讀的緩衝區接口',你*可能*需要使用註釋掉的'typestr'。 – r3m0t

+0

嗨,現在它構建,但是當我將OpenCVMemoryView傳遞給cv2.matchTemplate時出現運行時錯誤:'TypeError:不是一個numpy數組'我嘗試了註釋typestr,它沒有區別。 – martinako