Python 包装C++;使用Cython具有OpenCV参数的函数

Python 包装C++;使用Cython具有OpenCV参数的函数,python,c++,opencv,cython,Python,C++,Opencv,Cython,我有一个我用C写的类++ #include "segmenter_interface.h" #include "video_marker.cpp" #include <opencv2/imgcodecs.hpp> #include <opencv2/videoio/videoio.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/opencv.hpp> #include &l

我有一个我用C写的类++

#include "segmenter_interface.h"
#include "video_marker.cpp"
#include <opencv2/imgcodecs.hpp>
#include <opencv2/videoio/videoio.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/opencv.hpp>
#include <vector>

class UserDivide : public SegmenterInterface{
  public: 
    virtual void SegmentVideo(cv::VideoCapture *vc, 
        std::vector<Segment> *indices); 
}
错误消息如下所示:

Error compiling Cython file:
------------------------------------------------------------
...
    cdef UserDivide *thisptr # hold a C++ instance
    def __cinit__(self): 
        self.thisptr = new UserDivide()
    def __dealloc__(self): 
        del self.thisptr
    def SegmentVideo(self, VideoCapture *vc, vector[Segment] *indices): 
                          ^
------------------------------------------------------------

pyuser_divide.pyx:22:27: Cannot convert Python object argument to type 'VideoCapture *'

Error compiling Cython file:
------------------------------------------------------------
...
    cdef UserDivide *thisptr # hold a C++ instance
    def __cinit__(self): 
        self.thisptr = new UserDivide()
    def __dealloc__(self): 
        del self.thisptr
    def SegmentVideo(self, VideoCapture *vc, vector[Segment] *indices): 
                                            ^
------------------------------------------------------------

pyuser_divide.pyx:22:45: Cannot convert Python object argument to type 'vector[Segment] *'

不幸的是,这只是一个部分答案:我知道问题所在,但不知道解决办法

你的第二个问题很容易解决。问题在于它希望指向C++向量,但它得到了一个Python列表。Cython可以自动将列表转换为向量并返回,但在指针处会丢失

 # put this at the of your file top, and remove
 # cdef extern from "<vector>" namespace "std": (etc)
 #
 # Cython has automatically defined these!
 from libcpp.vector cimport vector

 # ... other code goes here ...

 # accept a list
 def SegmentVideo(self, VideoCapture *vc, list indices):
    cdef vector[Segment] indices_vector = indices # autoconversion happens
    output = self.thisptr.SegmentVideo(vc, &indices_vector)
    # are you expecting the vector to be changed, and do you want to keep the changes?
    # if so then do
    indices[:] = indices_vector
    # if you don't care about changes then don't bother
    return output
#将此文件放在文件顶部,然后删除
#来自“命名空间”std的cdef外部程序(等)
#
#Cython已经自动定义了这些!
从libcpp.vector cimport vector
# ... 其他代码在这里。。。
#接受名单
def段视频(自拍、视频捕获*vc、列表索引):
cdef向量[段]索引_向量=索引#发生自动转换
输出=self.thisptr.SegmentVideo(vc和索引\U向量)
#您是否希望向量发生更改,是否希望保留更改?
#如果是这样,那就做吧
索引[:]=索引向量
#如果你不在乎改变,那就不要麻烦了
返回输出
您的第一个问题(
无法将Python对象参数转换为类型“VideoCapture*”
)是我无法解决的问题。本质上,CV2模块生成Python对象(可能是围绕OpenCV中定义的C++指针的包装),并且没有明显的方法从那些Python对象生成C++指针——您必须确定它存储在哪里。 我不会完全重复的快速浏览表明VideoCapture python对象在我的系统上是32字节(空的python对象是16字节)。然而,在我看来,这两个额外的8字节空间的内容都不像指针


大多数OpenCV Python包装看起来是从C++代码中自生的(至少我可以说),这意味着它不太容易弄清楚它是如何包装的。一种可能有用的方法是尝试通过他们的代码生成器运行

UserDivide
,看看是否可以通过这种方式为其生成python绑定….

您能提供Cython报告的确切错误消息吗?您是对的,我不认为有一个很好的方法来使用我上面定义的VideoCapture对象。在为一个好的解决方案旋转轮子之后,我决定包装我需要的东西,以便将视频捕获对象传递给我的UserDivide对象。也就是说,我包装VideoCapture,实现VideoCapture(std::string&filename)构造函数,然后将VideoCapture python类传递给UserDivide python类。所以现在我不使用opencv提供的任何包装。
Error compiling Cython file:
------------------------------------------------------------
...
    cdef UserDivide *thisptr # hold a C++ instance
    def __cinit__(self): 
        self.thisptr = new UserDivide()
    def __dealloc__(self): 
        del self.thisptr
    def SegmentVideo(self, VideoCapture *vc, vector[Segment] *indices): 
                          ^
------------------------------------------------------------

pyuser_divide.pyx:22:27: Cannot convert Python object argument to type 'VideoCapture *'

Error compiling Cython file:
------------------------------------------------------------
...
    cdef UserDivide *thisptr # hold a C++ instance
    def __cinit__(self): 
        self.thisptr = new UserDivide()
    def __dealloc__(self): 
        del self.thisptr
    def SegmentVideo(self, VideoCapture *vc, vector[Segment] *indices): 
                                            ^
------------------------------------------------------------

pyuser_divide.pyx:22:45: Cannot convert Python object argument to type 'vector[Segment] *'
 # put this at the of your file top, and remove
 # cdef extern from "<vector>" namespace "std": (etc)
 #
 # Cython has automatically defined these!
 from libcpp.vector cimport vector

 # ... other code goes here ...

 # accept a list
 def SegmentVideo(self, VideoCapture *vc, list indices):
    cdef vector[Segment] indices_vector = indices # autoconversion happens
    output = self.thisptr.SegmentVideo(vc, &indices_vector)
    # are you expecting the vector to be changed, and do you want to keep the changes?
    # if so then do
    indices[:] = indices_vector
    # if you don't care about changes then don't bother
    return output