【问题标题】:Using Opencv Cuda functions from python从 python 中使用 Opencv Cuda 函数
【发布时间】:2017-10-05 08:27:02
【问题描述】:

对于我的一个课程项目,我需要使用 OpenCVs 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]' has no attribute 'knnMatch'

现在据我了解,Ptr 是DescriptorMatcher 类型的共享指针,所以我从 .pxd 文件定义 Ptr 的方式一定有问题。

我只是不知道如何解决它。如果有人能帮我解决这个问题,我将不胜感激。

【问题讨论】:

  • 你有没有让它工作。你用的是什么版本的python和opencv?
  • 您是否将代码上传到某个地方?

标签: c++ opencv cython


【解决方案1】:

我认为您没有正确使用 Ptr(它需要在 Cython 中取消引用才能到达 knnMatch)。

了解如何制作 Ptr 的好地方是 Cython 中内置的 C++ 标准库包装器 which wrap the similar classes std::shared_ptr and std::unique_ptr

您不想执行 T element_type 行,因为它不会被解释为 typedef(就像在 OpenCV 头文件中一样) - 它被解释为有一个名为 element_type 的成员,类型为 T(它不'不存在)。

您可能想要为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)

(剩下的代码我没有详细看,对不对不评论)

【讨论】:

  • 非常感谢。我能够成功编译它而没有任何错误。非常感谢您的帮助。
  • @MohammedRashidChowdhury 我正试图让它工作,但我在 Ptr 上遇到编译错误。有任何想法吗? GpuWrapper.pyx:77:44:无法将类型“Ptr[T]”分配给“Ptr[DescriptorMatcher]”回溯(最近一次调用最后):文件“setupGpuWrapper.py”,第 35 行,在 ext_modules=cythonize(扩展名)文件“/usr/local/lib/python3.5/dist-packages/Cython/Build/Dependencies.py”,第 1039 行,在 cythonize cythonize_one(*args)文件“/usr/local/lib/python3.5 /dist-packages/Cython/Build/Dependencies.py",第 1161 行,在 cythonize_one 中引发 CompileError(None, pyx_file)
  • @ThijsW 您几乎可以肯定在某处缺少模板指示符(即您正在做类似cdef Ptr[T] somethingcdef Ptr something 的事情,而您应该有cdef Ptr[DescriptiorMatcher] something)。它可能是一个函数返回值。如果这还不足以帮助我建议您提出自己的问题,因为没有代码很难分辨。
猜你喜欢
  • 2017-06-26
  • 2014-08-04
  • 2012-04-28
  • 1970-01-01
  • 2021-12-28
  • 2017-09-05
  • 1970-01-01
  • 2011-07-14
  • 2012-05-23
相关资源
最近更新 更多