Opencv 如何使用Cython包装SparsePyrLKOpticalFlow的Cuda版本?
我正在尝试使用Cython包装Cuda版本的Opencv 如何使用Cython包装SparsePyrLKOpticalFlow的Cuda版本?,opencv,cython,wrapper,opticalflow,Opencv,Cython,Wrapper,Opticalflow,我正在尝试使用Cython包装Cuda版本的SparsePyrLKOpticalFlowOpenCV算法。到目前为止,我的代码主要基于答案中的修改。我想我必须初始化SparsePyrLKOpticalFlow类的一个实例,然后使用该类从SparseOpticalFlow继承的成员函数calc 以下是我目前掌握的情况: Corner_Tracker.pxd from libcpp cimport bool from cpython.ref cimport PyObject from libcpp.
SparsePyrLKOpticalFlow
OpenCV算法。到目前为止,我的代码主要基于答案中的修改。我想我必须初始化SparsePyrLKOpticalFlow
类的一个实例,然后使用该类从SparseOpticalFlow
继承的成员函数calc
以下是我目前掌握的情况:
Corner_Tracker.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':
cdef 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
cdef cppclass Algorithm:
Algorithm() except +
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/cvstd.hpp' namespace 'cv':
cdef cppclass Ptr[T]:
Ptr() except +
Ptr(Ptr*) except +
T& operator* () except +
cdef extern from 'opencv2/cudaoptflow.hpp' namespace 'cv::cuda':
cdef cppclass SparseOpticalFlow:
void calc(GpuMat prevImg, GpuMat nextImg, GpuMat prevPts, GpuMat nextPts, GpuMat status) except +
cdef extern from 'opencv2/cudaoptflow.hpp' namespace 'cv::cuda::SparsePyrLKOpticalFlow':
cdef cppclass SparsePyrLKOpticalFlow(SparseOpticalFlow):
@staticmethod
Ptr[SparsePyrLKOpticalFlow] create(Size winSize, int maxLevel) except +
我怀疑我没有正确输入calc
参数类型,但我不确定还能做什么
Corner_Tracker.pyx
import numpy as np
import cv2
cimport numpy as np
from cython.operator cimport dereference
def cudaCalcFlowWrapper(
np.ndarray[np.uint8_t, ndim=2] prevImg,
np.ndarray[np.uint8_t, ndim=2] nextImg,
np.ndarray[np.float32_t, ndim=2] prevPts):
np.import_array()
cdef Ptr[SparsePyrLKOpticalFlow] flow_tracker = SparsePyrLKOpticalFlow.create(Size(15,15), 2)
cdef Mat prevImgMat
cdef GpuMat prevImgGpu
pyopencv_to(<PyObject*> prevImg, prevImgMat)
prevImgGpu.upload(prevImgMat)
cdef Mat nextImgMat
cdef GpuMat nextImgGpu
pyopencv_to(<PyObject*> nextImg, nextImgMat)
nextImgGpu.upload(nextImgMat)
cdef Mat prevPtsMat = Mat()
cdef GpuMat prevPtsGpu
pyopencv_to(<PyObject*> prevPts, prevPtsMat)
prevPtsGpu.upload(prevPtsMat)
cdef Mat nextPtsMat
cdef Mat statusMat
cdef GpuMat nextPtsGpu
cdef GpuMat statusGpu
dereference(flow_tracker).calc(prevImgGpu, nextImgGpu, prevPtsGpu, nextPtsGpu, statusGpu)
nextPtsGpu.download(nextPtsMat)
statusGpu.download(statusMat)
cdef np.ndarray nextPts = <np.ndarray> pyopencv_from(nextPtsMat)
cdef np.ndarray status = <np.ndarray> pyopencv_from(statusMat)
return nextPts, status
当我运行python setup.py build\u ext--inplace
时,我得到以下结果:
Compiling Corner_Tracker.pyx because it changed.
[1/1] Cythonizing Corner_Tracker.pyx
running build_ext
building 'Corner_Tracker' extension
x86_64-linux-gnu-gcc -pthread -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -fno-strict-aliasing -Wdate-time -D_FORTIFY_SOURCE=2 -g -fstack-protector-strong -Wformat -Werror=format-security -fPIC -I/home/sccarey/.virtualenvs/cv/local/lib/python2.7/site-packages/numpy/core/include -I-I/usr/local/include/opencv -I-I/usr/local/include -I/usr/include/python2.7 -c Corner_Tracker.cpp -o build/temp.linux-x86_64-2.7/Corner_Tracker.o
cc1plus: warning: command line option ‘-Wstrict-prototypes’ is valid for C/ObjC but not for C++
In file included from /home/sccarey/.virtualenvs/cv/local/lib/python2.7/site-packages/numpy/core/include/numpy/ndarraytypes.h:1816:0,
from /home/sccarey/.virtualenvs/cv/local/lib/python2.7/site-packages/numpy/core/include/numpy/ndarrayobject.h:18,
from pyopencv_converter.cpp:2,
from Corner_Tracker.cpp:623:
/home/sccarey/.virtualenvs/cv/local/lib/python2.7/site-packages/numpy/core/include/numpy/npy_1_7_deprecated_api.h:15:2: warning: #warning "Using deprecated NumPy API, disable it by " "#defining NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION" [-Wcpp]
#warning "Using deprecated NumPy API, disable it by " \
^
Corner_Tracker.cpp: In function ‘PyObject* __pyx_pf_14Corner_Tracker_cudaCalcFlowWrapper(PyObject*, PyArrayObject*, PyArrayObject*, PyArrayObject*)’:
Corner_Tracker.cpp:1843:67: error: type/value mismatch at argument 1 in template parameter list for ‘template<class T> struct cv::Ptr’
cv::Ptr<cv::cuda::SparsePyrLKOpticalFlow::SparsePyrLKOpticalFlow> __pyx_v_flow_tracker;
^
Corner_Tracker.cpp:1843:67: note: expected a type, got ‘cv::cuda::SparsePyrLKOpticalFlow::SparsePyrLKOpticalFlow’
Corner_Tracker.cpp:1866:67: error: type/value mismatch at argument 1 in template parameter list for ‘template<class T> struct cv::Ptr’
cv::Ptr<cv::cuda::SparsePyrLKOpticalFlow::SparsePyrLKOpticalFlow> __pyx_t_3;
^
Corner_Tracker.cpp:1866:67: note: expected a type, got ‘cv::cuda::SparsePyrLKOpticalFlow::SparsePyrLKOpticalFlow’
Corner_Tracker.cpp:1868:3: error: ‘cv::cuda::SparsePyrLKOpticalFlow::SparsePyrLKOpticalFlow’ names the constructor, not the type
cv::cuda::SparsePyrLKOpticalFlow::SparsePyrLKOpticalFlow __pyx_t_5;
^
Corner_Tracker.cpp:1868:60: error: expected ‘;’ before ‘__pyx_t_5’
cv::cuda::SparsePyrLKOpticalFlow::SparsePyrLKOpticalFlow __pyx_t_5;
^
Corner_Tracker.cpp:1868:69: error: statement cannot resolve address of overloaded function
cv::cuda::SparsePyrLKOpticalFlow::SparsePyrLKOpticalFlow __pyx_t_5;
^
Corner_Tracker.cpp:1923:81: error: invalid user-defined conversion from ‘cv::Ptr<cv::cuda::SparsePyrLKOpticalFlow>’ to ‘int’ [-fpermissive]
__pyx_t_3 = cv::cuda::SparsePyrLKOpticalFlow::SparsePyrLKOpticalFlow::create(__pyx_t_2, 2);
^
In file included from /usr/local/include/opencv2/core/cvstd.hpp:1067:0,
from /usr/local/include/opencv2/core/base.hpp:56,
from /usr/local/include/opencv2/core.hpp:54,
from /usr/local/include/opencv2/core/core.hpp:48,
from pyopencv_converter.cpp:3,
from Corner_Tracker.cpp:623:
/usr/local/include/opencv2/core/ptr.inl.hpp:222:1: note: candidate is: cv::Ptr<T>::operator T*() const [with T = cv::cuda::SparsePyrLKOpticalFlow] <near match>
Ptr<T>::operator T* () const
^
/usr/local/include/opencv2/core/ptr.inl.hpp:222:1: note: no known conversion from ‘cv::cuda::SparsePyrLKOpticalFlow*’ to ‘int’
Corner_Tracker.cpp:2022:5: error: ‘__pyx_t_5’ was not declared in this scope
__pyx_t_5 = * __pyx_v_flow_tracker;
^
Corner_Tracker.cpp:2022:19: error: invalid type argument of unary ‘*’ (have ‘int’)
__pyx_t_5 = * __pyx_v_flow_tracker;
^
Corner_Tracker.cpp:2028:5: error: ‘__pyx_t_5’ was not declared in this scope
__pyx_t_5.calc(__pyx_v_prevImgGpu, __pyx_v_nextImgGpu, __pyx_v_prevPtsGpu, __pyx_v_nextPtsGpu, __pyx_v_statusGpu);
^
error: command 'x86_64-linux-gnu-gcc' failed with exit status 1
根据错误消息,您的主要问题是名称空间声明
cdef extern from 'opencv2/cudaoptflow.hpp' namespace 'cv::cuda::SparsePyrLKOpticalFlow':
cdef cppclass SparsePyrLKOpticalFlow(SparseOpticalFlow):
# ...
编译器输出正在报告
错误:“cv::cuda::SparsePyrLKOpticalFlow::SparsePyrLKOpticalFlow”命名构造函数,而不是类型
因此,您希望将此类的命名空间更改为'cv::cuda'
这不是bug,但是如果您将
pyopencv\u从/to
声明为
cdef object pyopencv_from(const Mat& m)
cdef bool pyopencv_to(object, Mat& m)
这样您就不必强制转换到PyObject*
抽象变量的问题来自于行
dereference(flow_tracker).calc(prevImgGpu, nextImgGpu, prevPtsGpu, nextPtsGpu, statusGpu)
这是因为它试图(粗略地)做到:
由于SparsePyrLKOptical
是抽象的,因此您只能创建它的派生类,而不能直接创建该类
如果从行
T&operator*()except+
中删除except+
,则Cython不会创建错误检查代码,因此不需要临时代码。我怀疑这是正确的,操作符*
实际上不能抛出异常,但如果可以,它有可能停止您的程序。这两个建议似乎都奏效了!谢谢现在我又犯了一个错误。我会把它钉在我的文章的末尾。它被编译了!不知道我花了多长时间才能找到。非常感谢你!!别担心。(将来,如果您查看生成的.cpp文件,它会包含注释,向您显示与之匹配的Cython代码。这将有助于您缩小问题范围(如果不是解决方案的话)!谢谢
cdef object pyopencv_from(const Mat& m)
cdef bool pyopencv_to(object, Mat& m)
dereference(flow_tracker).calc(prevImgGpu, nextImgGpu, prevPtsGpu, nextPtsGpu, statusGpu)
SparsePyrLKOptical tmp_variable
try {
tmp_variable = dereference(flow_tracker)
}
catch(...) {
// handle errors
}
tmp_variable.calc(...)