python调用opencv_从Python调用C opencv函数(将cv :: Mat发送到使用opencv的C dll)

您可以看一下OpenCV Python包装器.在modules / python / src2 / cv2.cpp中的OpenCV文件夹中(取决于版本,我使用OpenCV 2.4),OpenCV Python包装器使用了一些称为pyopencv_to的函数.其中之一用于将PyObject转换为cv :: Mat.您的“ FromPython”函数需要获取PyObject作为输入.我个人使用boost :: python :: object将Python OpenCV函数返回的numpy数组传递给C函数/类.您应该最终在C中拥有这样的东西:

///PythonToOCV.h

#ifndef __PYTHONTOOCV_H_INCLUDED__

#define __PYTHONTOOCV_H_INCLUDED__

#include

#include

#include

#include "numpy/ndarrayobject.h"

#include "opencv2/core/core.hpp"

/

/// \brief Import Numpy array. Necessary to avoid PyArray_Check() to crash

void doImport( );

int failmsg( const char *fmt, ... );

static size_t REFCOUNT_OFFSET = ( size_t )&((( PyObject* )0)->ob_refcnt ) +

( 0x12345678 != *( const size_t* )"\x78\x56\x34\x12\0\0\0\0\0" )*sizeof( int );

static inline PyObject* pyObjectFromRefcount( const int* refcount )

{

return ( PyObject* )(( size_t )refcount - REFCOUNT_OFFSET );

}

static inline int* refcountFromPyObject( const PyObject* obj )

{

return ( int* )(( size_t )obj + REFCOUNT_OFFSET );

}

class NumpyAllocator : public cv::MatAllocator

{

public:

NumpyAllocator( ) { }

~NumpyAllocator( ) { }

void allocate( int dims, const int* sizes, int type, int*& refcount,

uchar*& datastart, uchar*& data, size_t* step );

void deallocate( int* refcount, uchar* datastart, uchar* data );

};

/

/// \brief Convert a numpy array to a cv::Mat. This is used to import images

/// from Python.

/// This function is extracted from opencv/modules/python/src2/cv2.cpp

/// in OpenCV 2.4

int pyopencv_to( const PyObject* o, cv::Mat& m, const char* name = "", bool allowND=true );

#endif //__PYTHONTOOCV_H_INCLUDED__

///PythonToOCV.cpp

#include "PythonToOpenCV.h"

void doImport( )

{

import_array( );

}

int failmsg( const char *fmt, ... )

{

char str[1000];

va_list ap;

va_start( ap, fmt );

vsnprintf( str, sizeof( str ), fmt, ap );

va_end( ap );

PyErr_SetString( PyExc_TypeError, str );

return 0;

}

void NumpyAllocator::allocate( int dims, const int* sizes, int type, int*& refcount, uchar*& datastart, uchar*& data, size_t* step )

{

int depth = CV_MAT_DEPTH( type );

int cn = CV_MAT_CN( type );

const int f = ( int )( sizeof( size_t )/8 );

int typenum = depth == CV_8U ? NPY_UBYTE : depth == CV_8S ? NPY_BYTE :

depth == CV_16U ? NPY_USHORT : depth == CV_16S ? NPY_SHORT :

depth == CV_32S ? NPY_INT : depth == CV_32F ? NPY_FLOAT :

depth == CV_64F ? NPY_DOUBLE : f*NPY_ULONGLONG + (f^1)*NPY_UINT;

int i;

npy_intp _sizes[CV_MAX_DIM+1];

for( i = 0; i < dims; i++ )

_sizes[i] = sizes[i];

if( cn > 1 )

{

/*if( _sizes[dims-1] == 1 )

_sizes[dims-1] = cn;

else*/

_sizes[dims++] = cn;

}

PyObject* o = PyArray_SimpleNew( dims, _sizes, typenum );

if( !o )

CV_Error_(CV_StsError, ("The numpy array of typenum=%d, ndims=%d can not be created", typenum, dims));

refcount = refcountFromPyObject(o);

npy_intp* _strides = PyArray_STRIDES(o);

for( i = 0; i < dims - (cn > 1); i++ )

step[i] = (size_t)_strides[i];

datastart = data = (uchar*)PyArray_DATA(o);

}

void NumpyAllocator::deallocate( int* refcount, uchar* datastart, uchar* data )

{

if( !refcount )

return;

PyObject* o = pyObjectFromRefcount(refcount);

Py_INCREF(o);

Py_DECREF(o);

}

// Declare the object

NumpyAllocator g_numpyAllocator;

int pyopencv_to(const PyObject* o, cv::Mat& m, const char* name, bool allowND )

{

// to avoid PyArray_Check() to crash even with valid array

doImport( );

if(!o || o == Py_None)

{

if( !m.data )

m.allocator = &g_numpyAllocator;

return true;

}

if( !PyArray_Check(o) )

{

failmsg("%s is not a numpy array", name);

return false;

}

// NPY_LONG (64 bit) is converted to CV_32S (32 bit)

int typenum = PyArray_TYPE(o);

int type = typenum == NPY_UBYTE ? CV_8U : typenum == NPY_BYTE ? CV_8S :

typenum == NPY_USHORT ? CV_16U : typenum == NPY_SHORT ? CV_16S :

typenum == NPY_INT || typenum == NPY_LONG ? CV_32S :

typenum == NPY_FLOAT ? CV_32F :

typenum == NPY_DOUBLE ? CV_64F : -1;

if( type < 0 )

{

failmsg("%s data type = %d is not supported", name, typenum);

return false;

}

int ndims = PyArray_NDIM(o);

if(ndims >= CV_MAX_DIM)

{

failmsg("%s dimensionality (=%d) is too high", name, ndims);

return false;

}

int size[CV_MAX_DIM+1];

size_t step[CV_MAX_DIM+1], elemsize = CV_ELEM_SIZE1(type);

const npy_intp* _sizes = PyArray_DIMS(o);

const npy_intp* _strides = PyArray_STRIDES(o);

bool transposed = false;

for(int i = 0; i < ndims; i++)

{

size[i] = (int)_sizes[i];

step[i] = (size_t)_strides[i];

}

if( ndims == 0 || step[ndims-1] > elemsize ) {

size[ndims] = 1;

step[ndims] = elemsize;

ndims++;

}

if( ndims >= 2 && step[0] < step[1] )

{

std::swap(size[0], size[1]);

std::swap(step[0], step[1]);

transposed = true;

}

if( ndims == 3 && size[2] <= CV_CN_MAX && step[1] == elemsize*size[2] )

{

ndims--;

type |= CV_MAKETYPE(0, size[2]);

}

if( ndims > 2 && !allowND )

{

failmsg("%s has more than 2 dimensions", name);

return false;

}

m = cv::Mat(ndims, size, type, PyArray_DATA(o), step);

if( m.data )

{

m.refcount = refcountFromPyObject(o);

m.addref(); // protect the original numpy array from deallocation

// (since Mat destructor will decrement the reference counter)

};

m.allocator = &g_numpyAllocator;

if( transposed )

{

cv::Mat tmp;

tmp.allocator = &g_numpyAllocator;

transpose(m, tmp);

m = tmp;

}

return true;

}

然后可以访问cv :: Mat的函数如下所示:

/// fromPython.h

#ifndef __FROMPYTHON_H_INCLUDED__

#define __FROMPYTHON_H_INCLUDED__

#include "PythonToOCV.h"

#include

int fromPython( boost::python::object &frame );

#endif //__FROMPYTHON_H_INCLUDED__

/// fromPython.cpp

#include "fromPython.h"

int fromPython( boost::python::object &frame )

{

cv::Mat image;

// this is the function from modules/python/src2/cv2.cpp (the third parameter might be ArgInfo in later OpenCV versions)

pyopencv_to( frame.ptr( ), image, "info", true );

///

/// HERE code using cv::Mat image

///

return 1;

}

要从Python访问此函数,需要将其包装在BOOST_PYTHON_MODULE中.像这样的东西:

#include "fromPython.h"

using namespace boost::python;

/// This function needs to be included to pass PyObjects as numpy array ( http://mail.python.org/pipermail/cplusplus-sig/2006-September/011021.html )

void* extract_pyarray( PyObject* x )

{

return PyObject_TypeCheck( x, &PyArray_Type ) ? x : 0;

}

BOOST_PYTHON_MODULE( myWrapper )

{

// This function needs to be included to pass PyObjects as numpy array ( http://mail.python.org/pipermail/cplusplus-sig/2006-September/011021.html )

boost::python::converter::registry::insert( &extract_pyarray, type_id( ) );

def fromPython( "fromPython", &fromPython );

}

然后,在Python中,您可以从Boost包装器创建的Python模块中调用函数.我正在使用Linux,所以我编译上面的代码以获取动态库(.so).我不确定Windows中有什么不同.我可以通过以下方式从动态库访问模块:

import myWrapper

import cv2

def myFunct():

cap = cv2.VideoCapture(0)

while(1):

ret,frame = cap.read()

myWrapper.fromPython(frame)

您可能可以避免使用Boost,但是我没有尝试其他方法,我发现Boost可以方便地包装C类.

注意:我没有测试此代码,因为我从项目中剥离了它,但我希望它仍然有用.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值