使用Python调用Opencv Cuda函数

4

我需要在我的课程项目中使用OpenCV的GPU库。我正在处理一个现有的代码,其中使用了OpenCV Python,我的任务是找到一种方法来访问OpenCV的CUDA库,因为现在没有可访问的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]'没有属性'knnMatch'

据我理解,Ptr是DescriptorMatcher类型的共享指针,所以我的从.pxd文件中定义Ptr的方式应该有问题。

我不知道如何解决它。如果有人能帮助我解决这个问题,我会非常感激。


1
你能让它工作了吗?你使用的是哪个版本的 Python 和 OpenCV? - Alvar
你把代码上传到某个地方了吗? - bendaf
1个回答

1

我认为你没有正确使用Ptr(在使用knnMatch之前需要在Cython中进行解引用)。

一个很好的参考资料是Cython内置的C ++标准库包装器,它们包装了类似的类std::shared_ptrstd::unique_ptr

你不想执行T element_type这一行,因为这不是一个typedef(就像在OpenCV头文件中一样),而是被解释为具有类型为T的成员element_type(该成员不存在)。

你可能希望设置Ptr的其他构造函数。目前你只包装了默认的空构造函数。(因为你从工厂函数中获取它,所以看起来并不重要)。

最重要的是,你还需要设置解引用运算符(operator*)。这可能是你需要实现的全部内容:

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

为了使用它,您需要使用cython.operator.dereference
# at the top
from cython.operator cimport dereference

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

我没有详细查看代码,因此对其是否正确没有评论。


非常感谢。我已经成功编译它,没有任何错误。我非常感激你的帮助。 - Rashid
@MohammedRashidChowdhury 我正在尝试让它工作,但是在Ptr上我得到了一个编译错误。有什么想法吗?GpuWrapper.pyx:77:44: 无法将类型“Ptr [T]”分配给“Ptr [DescriptorMatcher]” Traceback(最近的调用最先): File“setupGpuWrapper.py”,第35行,在<module>中 ext_modules = cythonize(extensions) File“/usr/local/lib/python3.5/dist-packages/Cython/Build/Dependencies.py”,第1039行,cythonize cythonize_one(* args) File“/usr/local/lib/python3.5/dist-packages/Cython/Build/Dependencies.py”,第1161行,cythonize_one raise CompileError(None,pyx_file) - ThijsW
1
@ThijsW 你很可能在某个地方缺少模板指示器(例如,你正在做类似于 cdef Ptr[T] somethingcdef Ptr something 的事情,而应该是 cdef Ptr[DescriptiorMatcher] something)。它也可能是一个函数返回值。如果这还不足以帮助你,我建议你提出自己的问题,因为没有代码很难判断。 - DavidW

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接