我编写了一个适用于Basler相机的VideoCapture
类的实现。它的使用方式如下:
import cv2
import PyBaslerCamera
video = PyBaslerCamera.PyBaslerCamera()
video.open(0)
while True:
ret, image = video.read()
cv2.imshow("Test", image)
cv2.waitKey(1)
我的Cython文件如下所示:
# distutils: language = c++
# distutils: sources = BaslerCamera.cpp
from cython.operator cimport dereference as deref
from cpython.ref cimport PyObject
from libcpp cimport bool
cdef extern from "opencv2/core/core.hpp" namespace "cv":
cdef cppclass Mat:
bool empty() const
void release() const
cdef cppclass _OutputArray:
Mat getMat(int idx=-1) const
cdef extern from "cv2.cpp":
void import_array()
PyObject* pyopencv_from(const Mat&)
int pyopencv_to(PyObject*, Mat&)
cdef Mat np2mat(object array):
cdef Mat mat
cdef PyObject* pyobject = <PyObject*> array
pyopencv_to(pyobject, mat)
return <Mat>mat
cdef object mat2np(const Mat &mat):
return <object> pyopencv_from(mat)
cdef extern from "BaslerCamera.h" namespace "cv":
cdef cppclass BaslerCamera:
BaslerCamera()
bool open(int index)
bool isOpened()
void release()
bool grab()
Mat retrieve()
bool read(_OutputArray image)
Mat read()
bool set(int propId, double value)
double get(int propId)
BaslerCamera &operator>>(Mat &image)
cdef class PyBaslerCamera:
cdef BaslerCamera *thisptr
cdef Mat mat
def __cinit__(self):
print("PyBaslerCamera init")
import_array()
self.thisptr = new BaslerCamera()
def __dealloc__(self):
del self.thisptr
def open(self, int index = 0):
self.thisptr.open(index)
def read(self):
mat = self.thisptr.read()
if mat.empty():
return (False, None)
else:
out = mat2np(mat)
return (True, out)
我使用过OpenCV的cv2.cpp文件: https://github.com/Itseez/opencv/blob/master/modules/python/src2/cv2.cpp
现在,一切正常,我从摄像机获取视频流,但问题是它泄漏了很多(在几秒钟内它会填满我的ram,这让我相信它只是泄漏所有框架)。 Valgrind似乎证实了
==21435== 1,050,624,000 bytes in 152 blocks are possibly lost in loss record 5,939 of 5,939
==21435== at 0x4C2BBA0: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==21435== by 0x20D7F3AB: ??? (in /usr/lib/python3/dist-packages/numpy/core/multiarray.cpython-34m-x86_64-linux-gnu.so)
==21435== by 0x20D1BD89: ??? (in /usr/lib/python3/dist-packages/numpy/core/multiarray.cpython-34m-x86_64-linux-gnu.so)
==21435== by 0x251D55E1: NumpyAllocator::allocate(int, int const*, int, void*, unsigned long*, int, cv::UMatUsageFlags) const (cv2.cpp:156)
==21435== by 0xB983720: cv::Mat::create(int, int const*, int) (in /usr/local/lib/libopencv_core.so.3.0.0)
==21435== by 0xB9B54C7: cv::_OutputArray::create(int, int, int, int, bool, int) const (in /usr/local/lib/libopencv_core.so.3.0.0)
==21435== by 0xB810A7C: cv::Mat::copyTo(cv::_OutputArray const&) const (in /usr/local/lib/libopencv_core.so.3.0.0)
==21435== by 0x251D44F9: pyopencv_from<cv::Mat> (cv2.cpp:211)
==21435== by 0x251D44F9: __pyx_f_14PyBaslerCamera_mat2np (PyBaslerCamera.cpp:662)
==21435== by 0x251D44F9: __pyx_pf_14PyBaslerCamera_14PyBaslerCamera_6read(__pyx_obj_14PyBaslerCamera_PyBaslerCamera*) [clone .isra.9] (PyBaslerCamera.cpp:973)
==21435== by 0x503F5C: PyEval_EvalFrameEx (in /usr/bin/python3.4)
==21435== by 0x5A9CB4: PyEval_EvalCodeEx (in /usr/bin/python3.4)
==21435== by 0x5E7104: ??? (in /usr/bin/python3.4)
==21435== by 0x5E71C8: PyRun_FileExFlags (in /usr/bin/python3.4)
==21435==
==21435== LEAK SUMMARY:
==21435== definitely lost: 165,107 bytes in 262 blocks
==21435== indirectly lost: 179,724,840 bytes in 205 blocks
==21435== possibly lost: 1,057,720,529 bytes in 646 blocks
==21435== still reachable: 9,399,307 bytes in 10,288 blocks
==21435== suppressed: 0 bytes in 0 blocks
==21435== Reachable blocks (those to which a pointer was found) are not shown.
==21435== To see them, rerun with: --leak-check=full --show-leak-kinds=all
看起来Numpy分配器创建的ndarray
似乎没有被释放,但我对如何解决这个问题感到茫然。谁能告诉我如何正确释放这段记忆?
或者,如果有人对如何处理整个cv::Mat
到np array
业务提出了更好的建议,我可以接受这些想法。