c++ पायथन से सी++ ओपनसीवी फ़ंक्शंस कॉल करें(सीसी:: मेट से सी++ डेल जो कि ओपनसीवी का उपयोग कर रहा है भेजें)



python opencv (1)

मैंने सी ++ कोड को ओपनसीवी का उपयोग करते हुए लिखा है, मैंने सी ++ कोड को "डीएलएल" के रूप में परिवर्तित किया है और मुझे अजगर में इस डीएलएल से एक विधि कॉल करने की ज़रूरत है जो cv::Mat को डेटाटाइप प्राप्त करता है। लेकिन मुझे यहां त्रुटि मिल रही है नीचे सी ++ कोड और अजगर कोड के नमूने हैं।

Googling पर मैंने पाया कि हमें बूस्ट लाइब्रेरी का उपयोग करने की आवश्यकता है लेकिन मुझे यकीन नहीं है कि कैसे Python mat को सी ++ cv::Mat परिवर्तित किया जाए और उनके बीच इंटरफेस कैसे बनाया जाए।

सी + + डेल कोड:

DLLEXPORT int FromPython ( cv :: Mat InputSrc) {

    imshow ( "FromPython", InputSrc );

        return 0;
}

पायथन कोड

import cv2 as cv
from ctypes import cdll

cap = cv.VideoCapture(0)

while(1):
    ret, frame = cap.read()

    cv.imshow('frame',frame)
    mydll = cdll.LoadLibrary('C:\Users\Documents\FromPythonDLL.dll')
    i = mydll.FromPython(frame)
    print(i)

    k = cv.waitKey(1) & 0xff
    if k == 27:
        break

cap.release()
cv.destroyAllWindows()

आप OpenCV पायथन आवरण पर एक नज़र डाल सकते हैं। ओपनसीवी फ़ोल्डर में मॉड्यूल / अजगर / src2 / cv2.cpp में (संस्करण के आधार पर, मैं ओपनसीवी 2.4 का उपयोग करता हूं) ओपनसीवी पायथन आवरण द्वारा प्रयुक्त पीयोपेनसीवी के कुछ फ़ंक्शन हैं। इनमें से एक का उपयोग PyObject को cv :: Mat में परिवर्तित करने के लिए किया जाता है आपका "सेपीथन" फ़ंक्शन को इनपुट के रूप में PyObject प्राप्त करने की आवश्यकता है। मैं निजी तौर पर boost :: python :: object को पायथन ओपनसीवी फ़ंक्शंस द्वारा सी ++ फ़ंक्शन / क्लास में लौटाए गए एम्परेक्स को पास करने के लिए ऑब्जेक्ट का उपयोग करता हूं। आपको सी ++ में ऐसा कुछ करना चाहिए:

///PythonToOCV.h

#ifndef __PYTHONTOOCV_H_INCLUDED__
#define __PYTHONTOOCV_H_INCLUDED__

#include <iostream>
#include <Python.h>
#include <boost/python.hpp>
#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 = "<unknown>", 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 <boost/python.hpp>

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;
} 

पायथन से सुलभ होने के लिए यह फ़ंक्शन एक 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<PyArrayObject>( ) ); 
     def fromPython( "fromPython", &fromPython );
} 

फिर पायथन में आप बूस्ट आवरण द्वारा बनाई गई पायथन मॉड्यूल से अपने फ़ंक्शन को कॉल कर सकते हैं। मैं लिनक्स का उपयोग कर रहा हूं इसलिए मैं एक डायनामिक लाइब्रेरी (.so) प्राप्त करने के लिए उपर्युक्त कोड को संकलित करता हूं। मुझे यकीन नहीं है कि यह विंडोज में कितना अलग है मैं गतिशील पुस्तकालय से मॉड्यूल तक पहुंच सकता हूं:

import myWrapper
import cv2 

def myFunct():
    cap = cv2.VideoCapture(0)
    while(1):
        ret,frame = cap.read()
        myWrapper.fromPython(frame)

आप संभवतः बूस्ट के उपयोग से बच सकते हैं लेकिन मैंने अन्य तरीकों की कोशिश नहीं की है और मुझे सी ++ कक्षाओं को लपेटने के लिए सुविधाजनक सुविधा मिली। नोट: मैंने इस कोड का परीक्षण नहीं किया है क्योंकि मैंने इसे एक परियोजना से छीन लिया था लेकिन मुझे आशा है कि यह अभी भी उपयोगी हो सकता है।





dll