用Cython封装具有OpenCV参数的C++函数
Wrapping C++ Function That Has OpenCV Parameters with 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 <vector>
class UserDivide : public SegmenterInterface{
public:
virtual void SegmentVideo(cv::VideoCapture *vc,
std::vector<Segment> *indices);
}
实施细节并不重要。理想情况下,我想使用Cython将这个类公开给python。对象VideoCapture已经可以由python实例化,因为OpenCV已经包装了它的所有模块。据我所知,vector已经是Cython的一部分,因为它支持大多数C++标准库。
目前,我已经写了这么多。pyx:
cdef extern from "<vector>" namespace "std":
cdef cppclass vector [T]:
pass
cdef extern from "<opencv2/videoio/videoio.hpp>" namespace "cv":
cdef cppclass VideoCapture:
pass # Don't care, just need a pointer
cdef extern from "segmenter_interface.h":
cdef struct Segment:
pass # I will need this eventually...
cdef extern from "user_divide.h":
cdef cppclass UserDivide:
UserDivide()
void SegmentVideo(VideoCapture *vc, vector[Segment] *indices)
cdef class PyUserDivide:
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):
return self.thisptr.SegmentVideo(vc, indices)
问题是SegmentVideo中的参数——cython编译器抱怨无法转换它们。
我的问题是:如何在Cython中正确地包装对象指针,尤其是如果它不是标准的数据类型或结构,而是一个类?我是否采取了正确的方法?
我的目标是在Python 中执行以下操作
import cv2
cap = cv2.VideoCapture("my_video.mp4")
segments = []
ud = UserDivide()
ud.SegmentVideo(cap, segments)
# Do stuff with segments
错误消息如下:
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
你的第一个问题(Cannot convert Python object argument to type 'VideoCapture *'
)是我无法解决的问题。从本质上讲,cv2模块生成python对象(可能是OpenCV中定义的C++指针的包装器),并且没有明显的方法从这些python对象生成C++指针——你必须弄清楚它存储在哪里。
我不会完全重复的快速浏览表明,VideoCapture python对象在我的系统上是32字节(一个空的python对象是16字节)。然而,两个额外的8字节空间的内容对我来说都不是"指针">
大多数OpenCV python包装器看起来都是从C++代码中自行生成的(至少据我所知),这意味着它的包装方式并不特别容易。一种可能有用的方法是尝试通过代码生成器运行UserDivide
,看看是否可以通过这种方式为其生成python绑定。。。。
- 如何反转整数参数包
- 使用C++库在Android项目中修改gradle中的cmake参数,用于插入指令的测试
- 如何使用默认参数等选择模板专业化
- 模板参数替换失败,并且未完成隐式转换
- 具有默认模板参数的多态类的模板推导失败
- lambda参数转换为constexpr技巧,然后获取带链接的数组
- 将数组作为参数传递给函数安全吗?作为第三方职能部门,可以探索他们想要的之外的其他元素
- 函数调用中参数的顺序重要吗
- 部分定义/别名模板模板参数
- 模板-模板参数推导:三个不同的编译器三种不同的行为
- 使用不带参数的函数访问结构元素
- 基于另一个成员参数将函数调用从类传递给它的一个成员
- 如何在OMNET++中指定与命令行参数组合的输出文件名
- 如何使用Luacneneneba API正确读取字符串和表参数
- 在派生函数中指定void*参数
- 视图中的参数推导失败:take_while
- static_assert在宏中,但也可以扩展到可以用作函数参数的东西
- 使用指向成员的指针将成员函数作为参数传递
- 没有名称的C++模板参数
- 如何将enable-if与模板参数和参数包一起使用