2017-05-07 676 views
2

對於我的課程項目之一,我需要使用OpenCV GPU庫。我正在使用OpenCV python的現有代碼,我的工作是尋找訪問OpenCV Cuda庫的方法,因爲現在沒有可訪問的OpenCV各種CUDA模塊的Python綁定。從python使用Opencv Cuda功能

我現在非常需要的兩個功能是cuda::warpPerspectivecv::cuda::DescriptorMatcher::knnMatch()

我試圖通過遵循@ostrumvulpes在Accessing OpenCV CUDA Functions from Python (No PyCUDA)中建議的方法來實現warpPerspective,並且它工作的很完美。現在我陷入了DescriptorMatcher::knnMatch()。更確切地說,我需要使用蠻力描述符匹配器knnmatch函數(CUDA)。我在網上搜索了用C++編寫的例子,以便我得到一個初步的想法如何通過cython轉換它使其工作。

大部分我發現的例子是類似以下內容:

Ptr<cuda::DescriptorMatcher> matcher = 
cuda::DescriptorMatcher::createBFMatcher(); 
vector< vector< DMatch> > matches; 
matcher->knnMatch(descriptors_object_Gpu, descriptors_scene_Gpu, matches, 2); 

要實現這三條線我第一次加入了我認爲在.pxd文件是必要的。我PXD文件如下所示:

GpuWrapper.pxd

from libcpp cimport bool 
from cpython.ref cimport PyObject 
from libcpp.vector cimport vector 

# References PyObject to OpenCV object conversion code borrowed from OpenCV's own conversion file, cv2.cpp 
cdef extern from 'pyopencv_converter.cpp': 
    #mrc689 April 20,2017 
    void import_array() 
    cdef PyObject* pyopencv_from(const Mat& m) 
    cdef bool pyopencv_to(PyObject* o, Mat& m) 

cdef extern from 'opencv2/imgproc.hpp' namespace 'cv': 
    cdef enum InterpolationFlags: 
     INTER_NEAREST = 0 
    cdef enum ColorConversionCodes: 
     COLOR_BGR2GRAY 

cdef extern from 'opencv2/core/core.hpp': 
    cdef int CV_8UC1 
    cdef int CV_32FC1 

cdef extern from 'opencv2/core/core.hpp' namespace 'cv': 
    cdef cppclass Size_[T]: 
     Size_() except + 
     Size_(T width, T height) except + 
     T width 
     T height 
    ctypedef Size_[int] Size2i 
    ctypedef Size2i Size 
    cdef cppclass Scalar[T]: 
     Scalar() except + 
     Scalar(T v0) except + 

cdef extern from 'opencv2/core/core.hpp' namespace 'cv': 
    cdef cppclass Mat: 
     Mat() except + 
     void create(int, int, int) except + 
     void* data 
     int rows 
     int cols 

    #added to test the Algorithm class inside core.hpp on May5th 12.52 AM. 
    cdef cppclass Algorithm: 
     Algorithm() except + 

cdef extern from 'opencv2/core/base.hpp' namespace 'cv': 
    cdef enum NormTypes: 
     NORM_INF= 1, 
     NORM_L1= 2, 
     NORM_L2= 4, 
     NORM_HAMMING= 6, 
     NORM_HAMMING2= 7, 

cdef extern from 'opencv2/core/cuda.hpp' namespace 'cv::cuda': 
    cdef cppclass GpuMat: 
     GpuMat() except + 
     void upload(Mat arr) except + 
     void download(Mat dst) const 
    cdef cppclass Stream: 
     Stream() except + 

cdef extern from 'opencv2/core/types.hpp' namespace 'cv': 
    cdef cppclass DMatch: 
     DMatch() except + 
     float distance 
     int imgIdx 
     int queryIdx 
     int trainIdx 

cdef extern from 'opencv2/core/cvstd.hpp' namespace 'cv': 
    cdef cppclass Ptr[T]: 
     T element_type 
     Ptr() except + 


cdef extern from 'opencv2/cudafeatures2d.hpp' namespace 'cv::cuda': 
    cdef cppclass DescriptorMatcher: 
     @staticmethod 
     Ptr[DescriptorMatcher] createBFMatcher(int normType) except+ 
     #Expected to see error here 
     void knnMatch(GpuMat queryDescriptors, GpuMat trainDescriptors, vector[vector[DMatch]] &matches,int k) 

cdef extern from 'opencv2/cudawarping.hpp' namespace 'cv::cuda': 
    cdef void warpPerspective(GpuMat src, GpuMat dst, Mat M, Size dsize, int flags, int borderMode, Scalar borderValue, Stream& stream) 
    # Function using default values 
    cdef void warpPerspective(GpuMat src, GpuMat dst, Mat M, Size dsize, int flags) 

和我PYX看起來是這樣的:

GpuWrapper.pyx

import numpy as np # Import Python functions, attributes, submodules of numpy 
cimport numpy as np # Import numpy C/C++ API 

def match_feature(np.ndarray[np.float32_t, ndim=3] _src, 
           np.ndarray[np.float32_t, ndim=2] _M): 

    np.import_array() 
    # Create GPU/device InputArray for src 
    cdef Mat src_mat 
    cdef GpuMat src_gpu 
    pyopencv_to(<PyObject*> _src, src_mat) 
    src_gpu.upload(src_mat) 

    cdef Mat src_mat_2 
    cdef GpuMat src_gpu_2 
    pyopencv_to(<PyObject*> _M, src_mat_2) 
    src_gpu_2.upload(src_mat_2) 

    cdef Ptr[DescriptorMatcher] matcher= Ptr() 
    matcher = DescriptorMatcher.createBFMatcher(4) 
    cdef vector[vector[DMatch]] matches 
    matcher.knnMatch(src_gpu,src_gpu_2,matches,2) 
    print("no problem so far") 

,當我試圖編譯它,我得到一個錯誤,說'Ptr[DescriptorMatcher]' has no attribute 'knnMatch'

現在據我瞭解,Ptr是DescriptorMatcher類型的共享指針,所以在從我的.pxd文件中定義Ptr的方式中肯定有些問題。

我只是不知道如何解決它。如果有人能幫助我解決問題,我將非常感激。

+0

你能否使它工作。你使用的是什麼版本的python和opencv? – Alvar

回答

1

我不認爲你正確使用Ptr(它需要在Cython中取消引用,然後才能到達knnMatch)。

查看如何製作Ptr的好地方是Cython which wrap the similar classes std::shared_ptr and std::unique_ptr內置的C++標準庫封裝器。

你不想做線T element_type,因爲這(在OpenCV頭等等)不被解釋爲一個typedef - 它解釋爲一個成員叫Telement_type(不存在)。

您可能想爲Ptr設置一些其他構造函數。就目前而言,你只包裝了默認的空白區域。 (從工廠函數中獲取它看起來不像你的代碼那麼重要)。

最重要的是,您還需要設置取消引用操作符(operator*)。這可能是所有你需要實現它的工作:

cdef cppclass Ptr[T]: 
    Ptr() except + 
    Ptr(Ptr*) except + 
    T& operator*() # probably no exceptions 

要使用它,你use the cython.operator.dereference

# at the top 
from cython.operator cimport dereference 

# later 
dereference(matcher).knnMatch(src_gpu,src_gpu_2,matches,2) 

(我沒有看過的代碼進行了詳細的其餘部分,以便我沒有評論它是否正確)

+0

非常感謝。我能夠成功編譯它,沒有任何錯誤。我非常感謝你的幫助。 –

+0

@MohammedRashidChowdhury我試圖讓這個工作,但我得到了Ptr的編譯錯誤。有任何想法嗎? GpuWrapper.pyx:77:44:不能分配型 'PTR [T]' 到 'PTR [DescriptorMatcher]' 回溯(最近最後調用): 文件 「setupGpuWrapper.py」,第35行,在 ext_modules = cythonize(擴展) cythonize中的文件「/usr/local/lib/python3.5/dist-packages/Cython/Build/Dependencies.py」,第1039行 cythonize_one(* args) 文件「/ usr/local /lib/python3.5/dist-packages/Cython/Build/Dependencies.py「,第1161行,在cythonize_one中 raise CompileError(None,pyx_file) – ThijsW

+1

@ThijsW你幾乎可以肯定在某處丟失了一個模板指示器(例如,當你需要'cdef Ptr [DescriptiorMatcher]時,重做'cdef Ptr [T] something'或'cdef Ptr something'。 something')。它可能是一個函數返回值。如果這還不足以幫助我建議問你自己的問題,因爲沒有代碼很難說。 – DavidW