2017-05-07 335 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