use*_*030 5 c++ python 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 <vector>
class UserDivide : public SegmenterInterface{
public:
virtual void SegmentVideo(cv::VideoCapture *vc,
std::vector<Segment> *indices);
}
Run Code Online (Sandbox Code Playgroud)
实施细节并不重要.理想情况下,我想使用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)
Run Code Online (Sandbox Code Playgroud)
问题是SegmentVideo中的参数 - cython编译器抱怨转换它们.
我的问题是:如何在Cython中正确包装对象指针,特别是如果它不是标准数据类型或结构,而是一个类?我甚至采取了正确的方法吗?
我的目标是在Python中执行以下操作
import cv2
cap = cv2.VideoCapture("my_video.mp4")
segments = []
ud = UserDivide()
ud.SegmentVideo(cap, segments)
# Do stuff with segments
Run Code Online (Sandbox Code Playgroud)
错误消息如下:
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] *'
Run Code Online (Sandbox Code Playgroud)
不幸的是,这是一个部分答案:我知道问题,但我不知道解决方案。
你的第二个问题很容易解决。问题是它需要一个指向 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
Run Code Online (Sandbox Code Playgroud)
你的第一个问题(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 绑定......
| 归档时间: |
|
| 查看次数: |
1008 次 |
| 最近记录: |