@ -50,9 +50,73 @@
# include <iostream>
# include <vector>
# if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
static IppStatus sts = ippInit ( ) ;
# endif
namespace cv
{
# if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
typedef IppStatus ( CV_STDCALL * ippiSetFunc ) ( const void * , void * , int , IppiSize ) ;
typedef IppStatus ( CV_STDCALL * ippiWarpPerspectiveBackFunc ) ( const void * , IppiSize , int , IppiRect , void * , int , IppiRect , double [ 3 ] [ 3 ] , int ) ;
typedef IppStatus ( CV_STDCALL * ippiWarpAffineBackFunc ) ( const void * , IppiSize , int , IppiRect , void * , int , IppiRect , double [ 2 ] [ 3 ] , int ) ;
typedef IppStatus ( CV_STDCALL * ippiResizeSqrPixelFunc ) ( const void * , IppiSize , int , IppiRect , void * , int , IppiRect , double , double , double , double , int , Ipp8u * ) ;
template < int channels , typename Type >
bool IPPSetSimple ( cv : : Scalar value , void * dataPointer , int step , IppiSize & size , ippiSetFunc func )
{
Type values [ channels ] ;
for ( int i = 0 ; i < channels ; i + + )
values [ i ] = ( Type ) value [ i ] ;
return func ( values , dataPointer , step , size ) > = 0 ;
}
bool IPPSet ( const cv : : Scalar & value , void * dataPointer , int step , IppiSize & size , int channels , int depth )
{
if ( channels = = 1 )
{
switch ( depth )
{
case CV_8U :
return ippiSet_8u_C1R ( ( Ipp8u ) value [ 0 ] , ( Ipp8u * ) dataPointer , step , size ) > = 0 ;
case CV_16U :
return ippiSet_16u_C1R ( ( Ipp16u ) value [ 0 ] , ( Ipp16u * ) dataPointer , step , size ) > = 0 ;
case CV_32F :
return ippiSet_32f_C1R ( ( Ipp32f ) value [ 0 ] , ( Ipp32f * ) dataPointer , step , size ) > = 0 ;
}
}
else
{
if ( channels = = 3 )
{
switch ( depth )
{
case CV_8U :
return IPPSetSimple < 3 , Ipp8u > ( value , dataPointer , step , size , ( ippiSetFunc ) ippiSet_8u_C3R ) ;
case CV_16U :
return IPPSetSimple < 3 , Ipp16u > ( value , dataPointer , step , size , ( ippiSetFunc ) ippiSet_16u_C3R ) ;
case CV_32F :
return IPPSetSimple < 3 , Ipp32f > ( value , dataPointer , step , size , ( ippiSetFunc ) ippiSet_32f_C3R ) ;
}
}
else if ( channels = = 4 )
{
switch ( depth )
{
case CV_8U :
return IPPSetSimple < 4 , Ipp8u > ( value , dataPointer , step , size , ( ippiSetFunc ) ippiSet_8u_C4R ) ;
case CV_16U :
return IPPSetSimple < 4 , Ipp16u > ( value , dataPointer , step , size , ( ippiSetFunc ) ippiSet_16u_C4R ) ;
case CV_32F :
return IPPSetSimple < 4 , Ipp32f > ( value , dataPointer , step , size , ( ippiSetFunc ) ippiSet_32f_C4R ) ;
}
}
}
return false ;
}
# endif
/************** interpolation formulas and tables ***************/
const int INTER_RESIZE_COEF_BITS = 11 ;
@ -1604,6 +1668,45 @@ static int computeResizeAreaTab( int ssize, int dsize, int cn, double scale, Dec
return k ;
}
# if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
class IPPresizeInvoker :
public ParallelLoopBody
{
public :
IPPresizeInvoker ( Mat & _src , Mat & _dst , double & _inv_scale_x , double & _inv_scale_y , int _mode , ippiResizeSqrPixelFunc _func , bool * _ok ) :
ParallelLoopBody ( ) , src ( _src ) , dst ( _dst ) , inv_scale_x ( _inv_scale_x ) , inv_scale_y ( _inv_scale_y ) , mode ( _mode ) , func ( _func ) , ok ( _ok )
{
* ok = true ;
}
virtual void operator ( ) ( const Range & range ) const
{
int cn = src . channels ( ) ;
IppiRect srcroi = { 0 , range . start , src . cols , range . end - range . start } ;
int dsty = CV_IMIN ( cvRound ( range . start * inv_scale_y ) , dst . rows ) ;
int dstwidth = CV_IMIN ( cvRound ( src . cols * inv_scale_x ) , dst . cols ) ;
int dstheight = CV_IMIN ( cvRound ( range . end * inv_scale_y ) , dst . rows ) ;
IppiRect dstroi = { 0 , dsty , dstwidth , dstheight - dsty } ;
int bufsize ;
ippiResizeGetBufSize ( srcroi , dstroi , cn , mode , & bufsize ) ;
Ipp8u * buf ;
buf = ippsMalloc_8u ( bufsize ) ;
IppStatus sts ;
if ( func ( src . data , ippiSize ( src . cols , src . rows ) , ( int ) src . step [ 0 ] , srcroi , dst . data , ( int ) dst . step [ 0 ] , dstroi , inv_scale_x , inv_scale_y , 0 , 0 , mode , buf ) < 0 )
* ok = false ;
ippsFree ( buf ) ;
}
private :
Mat & src ;
Mat & dst ;
double inv_scale_x ;
double inv_scale_y ;
int mode ;
ippiResizeSqrPixelFunc func ;
bool * ok ;
const IPPresizeInvoker & operator = ( const IPPresizeInvoker & ) ;
} ;
# endif
}
@ -1746,6 +1849,34 @@ void cv::resize( InputArray _src, OutputArray _dst, Size dsize,
double scale_x = 1. / inv_scale_x , scale_y = 1. / inv_scale_y ;
int k , sx , sy , dx , dy ;
# if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
int mode = interpolation = = INTER_LINEAR ? IPPI_INTER_LINEAR : 0 ;
int type = src . type ( ) ;
ippiResizeSqrPixelFunc ippFunc =
type = = CV_8UC1 ? ( ippiResizeSqrPixelFunc ) ippiResizeSqrPixel_8u_C1R :
type = = CV_8UC3 ? ( ippiResizeSqrPixelFunc ) ippiResizeSqrPixel_8u_C3R :
type = = CV_8UC4 ? ( ippiResizeSqrPixelFunc ) ippiResizeSqrPixel_8u_C4R :
type = = CV_16UC1 ? ( ippiResizeSqrPixelFunc ) ippiResizeSqrPixel_16u_C1R :
type = = CV_16UC3 ? ( ippiResizeSqrPixelFunc ) ippiResizeSqrPixel_16u_C3R :
type = = CV_16UC4 ? ( ippiResizeSqrPixelFunc ) ippiResizeSqrPixel_16u_C4R :
type = = CV_16SC1 ? ( ippiResizeSqrPixelFunc ) ippiResizeSqrPixel_16s_C1R :
type = = CV_16SC3 ? ( ippiResizeSqrPixelFunc ) ippiResizeSqrPixel_16s_C3R :
type = = CV_16SC4 ? ( ippiResizeSqrPixelFunc ) ippiResizeSqrPixel_16s_C4R :
type = = CV_32FC1 ? ( ippiResizeSqrPixelFunc ) ippiResizeSqrPixel_32f_C1R :
type = = CV_32FC3 ? ( ippiResizeSqrPixelFunc ) ippiResizeSqrPixel_32f_C3R :
type = = CV_32FC4 ? ( ippiResizeSqrPixelFunc ) ippiResizeSqrPixel_32f_C4R :
0 ;
if ( ippFunc & & mode ! = 0 )
{
bool ok ;
Range range ( 0 , src . rows ) ;
IPPresizeInvoker invoker ( src , dst , inv_scale_x , inv_scale_y , mode , ippFunc , & ok ) ;
parallel_for_ ( range , invoker , dst . total ( ) / ( double ) ( 1 < < 16 ) ) ;
if ( ok )
return ;
}
# endif
if ( interpolation = = INTER_NEAREST )
{
resizeNN ( src , dst , inv_scale_x , inv_scale_y ) ;
@ -3257,6 +3388,49 @@ private:
double * M ;
} ;
# if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
class IPPwarpAffineInvoker :
public ParallelLoopBody
{
public :
IPPwarpAffineInvoker ( Mat & _src , Mat & _dst , double ( & _coeffs ) [ 2 ] [ 3 ] , int & _interpolation , int & _borderType , const Scalar & _borderValue , ippiWarpAffineBackFunc _func , bool * _ok ) :
ParallelLoopBody ( ) , src ( _src ) , dst ( _dst ) , mode ( _interpolation ) , coeffs ( _coeffs ) , borderType ( _borderType ) , borderValue ( _borderValue ) , func ( _func ) , ok ( _ok )
{
* ok = true ;
}
virtual void operator ( ) ( const Range & range ) const
{
IppiSize srcsize = { src . cols , src . rows } ;
IppiRect srcroi = { 0 , 0 , src . cols , src . rows } ;
IppiRect dstroi = { 0 , range . start , dst . cols , range . end - range . start } ;
int cnn = src . channels ( ) ;
if ( borderType = = BORDER_CONSTANT )
{
IppiSize setSize = { dst . cols , range . end - range . start } ;
void * dataPointer = dst . data + dst . step [ 0 ] * range . start ;
if ( ! IPPSet ( borderValue , dataPointer , ( int ) dst . step [ 0 ] , setSize , cnn , src . depth ( ) ) )
{
* ok = false ;
return ;
}
}
if ( func ( src . data , srcsize , ( int ) src . step [ 0 ] , srcroi , dst . data , ( int ) dst . step [ 0 ] , dstroi , coeffs , mode ) < 0 ) ////Aug 2013: problem in IPP 7.1, 8.0 : sometimes function return ippStsCoeffErr
* ok = false ;
}
private :
Mat & src ;
Mat & dst ;
double ( & coeffs ) [ 2 ] [ 3 ] ;
int mode ;
int borderType ;
Scalar borderValue ;
ippiWarpAffineBackFunc func ;
bool * ok ;
const IPPwarpAffineInvoker & operator = ( const IPPwarpAffineInvoker & ) ;
} ;
# endif
}
@ -3303,6 +3477,50 @@ void cv::warpAffine( InputArray _src, OutputArray _dst,
const int AB_BITS = MAX ( 10 , ( int ) INTER_BITS ) ;
const int AB_SCALE = 1 < < AB_BITS ;
# if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
int depth = src . depth ( ) ;
int channels = src . channels ( ) ;
if ( ( depth = = CV_8U | | depth = = CV_16U | | depth = = CV_32F ) & &
( channels = = 1 | | channels = = 3 | | channels = = 4 ) & &
( borderType = = cv : : BORDER_TRANSPARENT | | ( borderType = = cv : : BORDER_CONSTANT ) ) )
{
int type = src . type ( ) ;
ippiWarpAffineBackFunc ippFunc =
type = = CV_8UC1 ? ( ippiWarpAffineBackFunc ) ippiWarpAffineBack_8u_C1R :
type = = CV_8UC3 ? ( ippiWarpAffineBackFunc ) ippiWarpAffineBack_8u_C3R :
type = = CV_8UC4 ? ( ippiWarpAffineBackFunc ) ippiWarpAffineBack_8u_C4R :
type = = CV_16UC1 ? ( ippiWarpAffineBackFunc ) ippiWarpAffineBack_16u_C1R :
type = = CV_16UC3 ? ( ippiWarpAffineBackFunc ) ippiWarpAffineBack_16u_C3R :
type = = CV_16UC4 ? ( ippiWarpAffineBackFunc ) ippiWarpAffineBack_16u_C4R :
type = = CV_32FC1 ? ( ippiWarpAffineBackFunc ) ippiWarpAffineBack_32f_C1R :
type = = CV_32FC3 ? ( ippiWarpAffineBackFunc ) ippiWarpAffineBack_32f_C3R :
type = = CV_32FC4 ? ( ippiWarpAffineBackFunc ) ippiWarpAffineBack_32f_C4R :
0 ;
int mode =
flags = = INTER_LINEAR ? IPPI_INTER_LINEAR :
flags = = INTER_NEAREST ? IPPI_INTER_NN :
flags = = INTER_CUBIC ? IPPI_INTER_CUBIC :
0 ;
if ( mode & & ippFunc )
{
double coeffs [ 2 ] [ 3 ] ;
for ( int i = 0 ; i < 2 ; i + + )
{
for ( int j = 0 ; j < 3 ; j + + )
{
coeffs [ i ] [ j ] = matM . at < double > ( i , j ) ;
}
}
bool ok ;
Range range ( 0 , dst . rows ) ;
IPPwarpAffineInvoker invoker ( src , dst , coeffs , mode , borderType , borderValue , ippFunc , & ok ) ;
parallel_for_ ( range , invoker , dst . total ( ) / ( double ) ( 1 < < 16 ) ) ;
if ( ok )
return ;
}
}
# endif
for ( x = 0 ; x < dst . cols ; x + + )
{
adelta [ x ] = saturate_cast < int > ( M [ 0 ] * x * AB_SCALE ) ;
@ -3410,6 +3628,50 @@ private:
Scalar borderValue ;
} ;
# if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
class IPPwarpPerspectiveInvoker :
public ParallelLoopBody
{
public :
IPPwarpPerspectiveInvoker ( Mat & _src , Mat & _dst , double ( & _coeffs ) [ 3 ] [ 3 ] , int & _interpolation , int & _borderType , const Scalar & _borderValue , ippiWarpPerspectiveBackFunc _func , bool * _ok ) :
ParallelLoopBody ( ) , src ( _src ) , dst ( _dst ) , mode ( _interpolation ) , coeffs ( _coeffs ) , borderType ( _borderType ) , borderValue ( _borderValue ) , func ( _func ) , ok ( _ok )
{
* ok = true ;
}
virtual void operator ( ) ( const Range & range ) const
{
IppiSize srcsize = { src . cols , src . rows } ;
IppiRect srcroi = { 0 , 0 , src . cols , src . rows } ;
IppiRect dstroi = { 0 , range . start , dst . cols , range . end - range . start } ;
int cnn = src . channels ( ) ;
if ( borderType = = BORDER_CONSTANT )
{
IppiSize setSize = { dst . cols , range . end - range . start } ;
void * dataPointer = dst . data + dst . step [ 0 ] * range . start ;
if ( ! IPPSet ( borderValue , dataPointer , ( int ) dst . step [ 0 ] , setSize , cnn , src . depth ( ) ) )
{
* ok = false ;
return ;
}
}
if ( func ( src . data , srcsize , ( int ) src . step [ 0 ] , srcroi , dst . data , ( int ) dst . step [ 0 ] , dstroi , coeffs , mode ) < 0 )
* ok = false ;
}
private :
Mat & src ;
Mat & dst ;
double ( & coeffs ) [ 3 ] [ 3 ] ;
int mode ;
int borderType ;
const Scalar borderValue ;
ippiWarpPerspectiveBackFunc func ;
bool * ok ;
const IPPwarpPerspectiveInvoker & operator = ( const IPPwarpPerspectiveInvoker & ) ;
} ;
# endif
}
void cv : : warpPerspective ( InputArray _src , OutputArray _dst , InputArray _M0 ,
@ -3440,6 +3702,50 @@ void cv::warpPerspective( InputArray _src, OutputArray _dst, InputArray _M0,
if ( ! ( flags & WARP_INVERSE_MAP ) )
invert ( matM , matM ) ;
# if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
int depth = src . depth ( ) ;
int channels = src . channels ( ) ;
if ( ( depth = = CV_8U | | depth = = CV_16U | | depth = = CV_32F ) & &
( channels = = 1 | | channels = = 3 | | channels = = 4 ) & &
( borderType = = cv : : BORDER_TRANSPARENT | | borderType = = cv : : BORDER_CONSTANT ) )
{
int type = src . type ( ) ;
ippiWarpPerspectiveBackFunc ippFunc =
type = = CV_8UC1 ? ( ippiWarpPerspectiveBackFunc ) ippiWarpPerspectiveBack_8u_C1R :
type = = CV_8UC3 ? ( ippiWarpPerspectiveBackFunc ) ippiWarpPerspectiveBack_8u_C3R :
type = = CV_8UC4 ? ( ippiWarpPerspectiveBackFunc ) ippiWarpPerspectiveBack_8u_C4R :
type = = CV_16UC1 ? ( ippiWarpPerspectiveBackFunc ) ippiWarpPerspectiveBack_16u_C1R :
type = = CV_16UC3 ? ( ippiWarpPerspectiveBackFunc ) ippiWarpPerspectiveBack_16u_C3R :
type = = CV_16UC4 ? ( ippiWarpPerspectiveBackFunc ) ippiWarpPerspectiveBack_16u_C4R :
type = = CV_32FC1 ? ( ippiWarpPerspectiveBackFunc ) ippiWarpPerspectiveBack_32f_C1R :
type = = CV_32FC3 ? ( ippiWarpPerspectiveBackFunc ) ippiWarpPerspectiveBack_32f_C3R :
type = = CV_32FC4 ? ( ippiWarpPerspectiveBackFunc ) ippiWarpPerspectiveBack_32f_C4R :
0 ;
int mode =
flags = = INTER_LINEAR ? IPPI_INTER_LINEAR :
flags = = INTER_NEAREST ? IPPI_INTER_NN :
flags = = INTER_CUBIC ? IPPI_INTER_CUBIC :
0 ;
if ( mode & & ippFunc )
{
double coeffs [ 3 ] [ 3 ] ;
for ( int i = 0 ; i < 3 ; i + + )
{
for ( int j = 0 ; j < 3 ; j + + )
{
coeffs [ i ] [ j ] = matM . at < double > ( i , j ) ;
}
}
bool ok ;
Range range ( 0 , dst . rows ) ;
IPPwarpPerspectiveInvoker invoker ( src , dst , coeffs , mode , borderType , borderValue , ippFunc , & ok ) ;
parallel_for_ ( range , invoker , dst . total ( ) / ( double ) ( 1 < < 16 ) ) ;
if ( ok )
return ;
}
}
# endif
Range range ( 0 , dst . rows ) ;
warpPerspectiveInvoker invoker ( src , dst , M , interpolation , borderType , borderValue ) ;
parallel_for_ ( range , invoker , dst . total ( ) / ( double ) ( 1 < < 16 ) ) ;