@ -45,6 +45,20 @@ static int failmsg(const char *fmt, ...)
return 0 ;
}
struct ArgInfo
{
const char * name ;
bool outputarg ;
// more fields may be added if necessary
ArgInfo ( const char * name_ , bool outputarg_ )
: name ( name_ )
, outputarg ( outputarg_ ) { }
// to match with older pyopencv_to function signature
operator const char * ( ) const { return name ; }
} ;
class PyAllowThreads
{
public :
@ -199,7 +213,8 @@ NumpyAllocator g_numpyAllocator;
enum { ARG_NONE = 0 , ARG_MAT = 1 , ARG_SCALAR = 2 } ;
static int pyopencv_to ( const PyObject * o , Mat & m , const char * name = " <unknown> " , bool allowND = true )
// special case, when the convertor needs full ArgInfo structure
static int pyopencv_to ( const PyObject * o , Mat & m , const ArgInfo info , bool allowND = true )
{
if ( ! o | | o = = Py_None )
{
@ -210,7 +225,7 @@ static int pyopencv_to(const PyObject* o, Mat& m, const char* name = "<unknown>"
if ( ! PyArray_Check ( o ) )
{
failmsg ( " %s is not a numpy array " , name ) ;
failmsg ( " %s is not a numpy array " , info . name ) ;
return false ;
}
@ -223,14 +238,14 @@ static int pyopencv_to(const PyObject* o, Mat& m, const char* name = "<unknown>"
if ( type < 0 )
{
failmsg ( " %s data type = %d is not supported " , name , typenum ) ;
failmsg ( " %s data type = %d is not supported " , info . name , typenum ) ;
return false ;
}
int ndims = PyArray_NDIM ( o ) ;
if ( ndims > = CV_MAX_DIM )
{
failmsg ( " %s dimensionality (=%d) is too high " , name , ndims ) ;
failmsg ( " %s dimensionality (=%d) is too high " , info . name , ndims ) ;
return false ;
}
@ -238,7 +253,21 @@ static int pyopencv_to(const PyObject* o, Mat& m, const char* name = "<unknown>"
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 ;
bool ismultichannel = ndims = = 3 & & _sizes [ 2 ] < = CV_CN_MAX ;
bool needcopy = ( _strides [ ndims - 1 ] ! = elemsize )
| | ( ismultichannel & & _strides [ ndims - 2 ] ! = elemsize * _sizes [ ndims - 1 ] ) ;
if ( needcopy )
{
if ( info . outputarg )
{
failmsg ( " output array %s is not row-contiguous (step[ndims-1] != elemsize) " , info . name ) ;
return false ;
}
o = ( PyObject * ) PyArray_GETCONTIGUOUS ( ( PyArrayObject * ) o ) ;
_strides = PyArray_STRIDES ( o ) ;
}
for ( int i = 0 ; i < ndims ; i + + )
{
@ -246,20 +275,14 @@ static int pyopencv_to(const PyObject* o, Mat& m, const char* name = "<unknown>"
step [ i ] = ( size_t ) _strides [ i ] ;
}
if ( ndims = = 0 | | step [ ndims - 1 ] > elemsize ) {
// handle degenerate case
if ( ndims = = 0 ) {
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 ] )
if ( ismultichannel )
{
ndims - - ;
type | = CV_MAKETYPE ( 0 , size [ 2 ] ) ;
@ -267,7 +290,7 @@ static int pyopencv_to(const PyObject* o, Mat& m, const char* name = "<unknown>"
if ( ndims > 2 & & ! allowND )
{
failmsg ( " %s has more than 2 dimensions " , name ) ;
failmsg ( " %s has more than 2 dimensions " , info . name ) ;
return false ;
}
@ -276,18 +299,14 @@ static int pyopencv_to(const PyObject* o, Mat& m, const char* name = "<unknown>"
if ( m . data )
{
m . refcount = refcountFromPyObject ( o ) ;
m . addref ( ) ; // protect the original numpy array from deallocation
// (since Mat destructor will decrement the reference counter)
if ( ! needcopy )
{
m . addref ( ) ; // protect the original numpy array from deallocation
// (since Mat destructor will decrement the reference counter)
}
} ;
m . allocator = & g_numpyAllocator ;
if ( transposed )
{
Mat tmp ;
tmp . allocator = & g_numpyAllocator ;
transpose ( m , tmp ) ;
m = tmp ;
}
return true ;
}
@ -593,7 +612,7 @@ static inline PyObject* pyopencv_from(const Point2d& p)
template < typename _Tp > struct pyopencvVecConverter
{
static bool to ( PyObject * obj , vector < _Tp > & value , const char * name = " <unknown> " )
static bool to ( PyObject * obj , vector < _Tp > & value , const ArgInfo info )
{
typedef typename DataType < _Tp > : : channel_type _Cp ;
if ( ! obj | | obj = = Py_None )
@ -601,12 +620,12 @@ template<typename _Tp> struct pyopencvVecConverter
if ( PyArray_Check ( obj ) )
{
Mat m ;
pyopencv_to ( obj , m , name ) ;
pyopencv_to ( obj , m , info ) ;
m . copyTo ( value ) ;
}
if ( ! PySequence_Check ( obj ) )
return false ;
PyObject * seq = PySequence_Fast ( obj , name ) ;
PyObject * seq = PySequence_Fast ( obj , info . name ) ;
if ( seq = = NULL )
return false ;
int i , j , n = ( int ) PySequence_Fast_GET_SIZE ( seq ) ;
@ -635,7 +654,7 @@ template<typename _Tp> struct pyopencvVecConverter
if ( PyArray_Check ( item ) )
{
Mat src ;
pyopencv_to ( item , src , name ) ;
pyopencv_to ( item , src , info ) ;
if ( src . dims ! = 2 | | src . channels ( ) ! = 1 | |
( ( src . cols ! = 1 | | src . rows ! = channels ) & &
( src . cols ! = channels | | src . rows ! = 1 ) ) )
@ -647,7 +666,7 @@ template<typename _Tp> struct pyopencvVecConverter
continue ;
}
seq_i = PySequence_Fast ( item , name ) ;
seq_i = PySequence_Fast ( item , info . name ) ;
if ( ! seq_i | | ( int ) PySequence_Fast_GET_SIZE ( seq_i ) ! = channels )
{
Py_XDECREF ( seq_i ) ;
@ -694,9 +713,9 @@ template<typename _Tp> struct pyopencvVecConverter
} ;
template < typename _Tp > static inline bool pyopencv_to ( PyObject * obj , vector < _Tp > & value , const char * name = " <unknown> " )
template < typename _Tp > static inline bool pyopencv_to ( PyObject * obj , vector < _Tp > & value , const ArgInfo info )
{
return pyopencvVecConverter < _Tp > : : to ( obj , value , name ) ;
return pyopencvVecConverter < _Tp > : : to ( obj , value , info ) ;
}
template < typename _Tp > static inline PyObject * pyopencv_from ( const vector < _Tp > & value )
@ -707,13 +726,13 @@ template<typename _Tp> static inline PyObject* pyopencv_from(const vector<_Tp>&
static PyObject * pyopencv_from ( const KeyPoint & ) ;
static PyObject * pyopencv_from ( const DMatch & ) ;
template < typename _Tp > static inline bool pyopencv_to_generic_vec ( PyObject * obj , vector < _Tp > & value , const char * name = " <unknown> " )
template < typename _Tp > static inline bool pyopencv_to_generic_vec ( PyObject * obj , vector < _Tp > & value , const ArgInfo info )
{
if ( ! obj | | obj = = Py_None )
return true ;
if ( ! PySequence_Check ( obj ) )
return false ;
PyObject * seq = PySequence_Fast ( obj , name ) ;
PyObject * seq = PySequence_Fast ( obj , info . name ) ;
if ( seq = = NULL )
return false ;
int i , n = ( int ) PySequence_Fast_GET_SIZE ( seq ) ;
@ -724,7 +743,7 @@ template<typename _Tp> static inline bool pyopencv_to_generic_vec(PyObject* obj,
for ( i = 0 ; i < n ; i + + )
{
PyObject * item = items [ i ] ;
if ( ! pyopencv_to ( item , value [ i ] , name ) )
if ( ! pyopencv_to ( item , value [ i ] , info ) )
break ;
}
Py_DECREF ( seq ) ;
@ -766,9 +785,9 @@ template<typename _Tp> struct pyopencvVecConverter<vector<_Tp> >
template < > struct pyopencvVecConverter < Mat >
{
static bool to ( PyObject * obj , vector < Mat > & value , const char * name = " <unknown> " )
static bool to ( PyObject * obj , vector < Mat > & value , const ArgInfo info )
{
return pyopencv_to_generic_vec ( obj , value , name ) ;
return pyopencv_to_generic_vec ( obj , value , info ) ;
}
static PyObject * from ( const vector < Mat > & value )
@ -779,9 +798,9 @@ template<> struct pyopencvVecConverter<Mat>
template < > struct pyopencvVecConverter < KeyPoint >
{
static bool to ( PyObject * obj , vector < KeyPoint > & value , const char * name = " <unknown> " )
static bool to ( PyObject * obj , vector < KeyPoint > & value , const ArgInfo info )
{
return pyopencv_to_generic_vec ( obj , value , name ) ;
return pyopencv_to_generic_vec ( obj , value , info ) ;
}
static PyObject * from ( const vector < KeyPoint > & value )
@ -792,9 +811,9 @@ template<> struct pyopencvVecConverter<KeyPoint>
template < > struct pyopencvVecConverter < DMatch >
{
static bool to ( PyObject * obj , vector < DMatch > & value , const char * name = " <unknown> " )
static bool to ( PyObject * obj , vector < DMatch > & value , const ArgInfo info )
{
return pyopencv_to_generic_vec ( obj , value , name ) ;
return pyopencv_to_generic_vec ( obj , value , info ) ;
}
static PyObject * from ( const vector < DMatch > & value )
@ -805,9 +824,9 @@ template<> struct pyopencvVecConverter<DMatch>
template < > struct pyopencvVecConverter < string >
{
static bool to ( PyObject * obj , vector < string > & value , const char * name = " <unknown> " )
static bool to ( PyObject * obj , vector < string > & value , const ArgInfo info )
{
return pyopencv_to_generic_vec ( obj , value , name ) ;
return pyopencv_to_generic_vec ( obj , value , info ) ;
}
static PyObject * from ( const vector < string > & value )