@ -40,7 +40,7 @@ GAPI_FLUID_KERNEL(FCopy, TCopy, false)
}
} ;
GAPI_FLUID_KERNEL ( FResizeNN , cv : : gapi : : core : : GResize , false )
GAPI_FLUID_KERNEL ( FResizeNN1Lpi , cv : : gapi : : core : : GResize , false )
{
static const int Window = 1 ;
static const auto Kind = GFluidKernel : : Kind : : Resize ;
@ -49,22 +49,25 @@ GAPI_FLUID_KERNEL(FResizeNN, cv::gapi::core::GResize, false)
cv : : gapi : : fluid : : Buffer & out )
{
auto length = out . length ( ) ;
double vRatio = ( double ) in . meta ( ) . size . height / out . meta ( ) . size . height ;
double hRatio = ( double ) in . length ( ) / length ;
auto y = out . y ( ) ;
auto inY = in . y ( ) ;
auto sy = static_cast < int > ( y * vRatio ) ;
int idx = sy - inY ;
const auto src = in . InLine < unsigned char > ( idx ) ;
auto dst = out . OutLine < unsigned char > ( ) ;
for ( int l = 0 ; l < out . lpi ( ) ; l + + )
{
auto sy = static_cast < int > ( ( y + l ) * vRatio ) ;
int idx = sy - inY ;
double horRatio = ( double ) in . length ( ) / out . length ( ) ;
const auto src = in . InLine < unsigned char > ( idx ) ;
auto dst = out . OutLine < unsigned char > ( l ) ;
for ( int x = 0 ; x < out . length ( ) ; x + + )
{
auto inX = static_cast < int > ( x * horRatio ) ;
dst [ x ] = src [ inX ] ;
for ( int x = 0 ; x < length ; x + + )
{
auto inX = static_cast < int > ( x * hRatio ) ;
dst [ x ] = src [ inX ] ;
}
}
}
} ;
@ -101,25 +104,33 @@ template <class Mapper>
inline void calcRow ( const cv : : gapi : : fluid : : View & in , cv : : gapi : : fluid : : Buffer & out , cv : : gapi : : fluid : : Buffer & scratch )
{
double vRatio = ( double ) in . meta ( ) . size . height / out . meta ( ) . size . height ;
auto mapY = Mapper : : map ( vRatio , in . y ( ) , in . meta ( ) . size . height , out . y ( ) ) ;
const auto src0 = in . InLine < unsigned char > ( mapY . s0 ) ;
const auto src1 = in . InLine < unsigned char > ( mapY . s1 ) ;
auto dst = out . OutLine < unsigned char > ( ) ;
auto mapX = scratch . OutLine < typename Mapper : : Unit > ( ) ;
auto inY = in . y ( ) ;
auto inH = in . meta ( ) . size . height ;
auto outY = out . y ( ) ;
auto length = out . length ( ) ;
for ( int x = 0 ; x < out . length ( ) ; x + + )
for ( int l = 0 ; l < out . lpi ( ) ; l + + )
{
auto alpha0 = mapX [ x ] . alpha0 ;
auto alpha1 = mapX [ x ] . alpha1 ;
auto sx0 = mapX [ x ] . s0 ;
auto sx1 = mapX [ x ] . s1 ;
auto mapY = Mapper : : map ( vRatio , inY , inH , outY + l ) ;
int res0 = src0 [ sx0 ] * alpha0 + src0 [ sx1 ] * alpha1 ;
int res1 = src1 [ sx0 ] * alpha0 + src1 [ sx1 ] * alpha1 ;
const auto src0 = in . InLine < unsigned char > ( mapY . s0 ) ;
const auto src1 = in . InLine < unsigned char > ( mapY . s1 ) ;
dst [ x ] = uchar ( ( ( ( mapY . alpha0 * ( res0 > > 4 ) ) > > 16 ) + ( ( mapY . alpha1 * ( res1 > > 4 ) ) > > 16 ) + 2 ) > > 2 ) ;
auto dst = out . OutLine < unsigned char > ( l ) ;
for ( int x = 0 ; x < length ; x + + )
{
auto alpha0 = mapX [ x ] . alpha0 ;
auto alpha1 = mapX [ x ] . alpha1 ;
auto sx0 = mapX [ x ] . s0 ;
auto sx1 = mapX [ x ] . s1 ;
int res0 = src0 [ sx0 ] * alpha0 + src0 [ sx1 ] * alpha1 ;
int res1 = src1 [ sx0 ] * alpha0 + src1 [ sx1 ] * alpha1 ;
dst [ x ] = uchar ( ( ( ( mapY . alpha0 * ( res0 > > 4 ) ) > > 16 ) + ( ( mapY . alpha1 * ( res1 > > 4 ) ) > > 16 ) + 2 ) > > 2 ) ;
}
}
}
} // namespace func
@ -191,7 +202,7 @@ struct Mapper
} // namespace areaUpscale
} // anonymous namespace
GAPI_FLUID_KERNEL ( FResizeLinear , cv : : gapi : : core : : GResize , true )
GAPI_FLUID_KERNEL ( FResizeLinear1Lpi , cv : : gapi : : core : : GResize , true )
{
static const int Window = 1 ;
static const auto Kind = GFluidKernel : : Kind : : Resize ;
@ -226,7 +237,7 @@ auto endInCoord = [](int outCoord, double ratio) {
} ;
} // namespace
GAPI_FLUID_KERNEL ( FResizeArea , cv : : gapi : : core : : GResize , false )
GAPI_FLUID_KERNEL ( FResizeArea1Lpi , cv : : gapi : : core : : GResize , false )
{
static const int Window = 1 ;
static const auto Kind = GFluidKernel : : Kind : : Resize ;
@ -235,57 +246,62 @@ GAPI_FLUID_KERNEL(FResizeArea, cv::gapi::core::GResize, false)
cv : : gapi : : fluid : : Buffer & out )
{
auto y = out . y ( ) ;
auto firstOutLineIdx = out . y ( ) ;
auto firstViewLineIdx = in . y ( ) ;
auto length = out . length ( ) ;
double vRatio = ( double ) in . meta ( ) . size . height / out . meta ( ) . size . height ;
double hRatio = ( double ) in . length ( ) / length ;
int startY = startInCoord ( y , vRatio ) ;
int endY = endInCoord ( y , vRatio ) ;
auto dst = out . OutLine < unsigned char > ( ) ;
double hRatio = ( double ) in . length ( ) / out . length ( ) ;
for ( int x = 0 ; x < out . length ( ) ; x + + )
for ( int l = 0 ; l < out . lpi ( ) ; l + + )
{
float res = 0.0 ;
int outY = firstOutLineIdx + l ;
int startY = startInCoord ( outY , vRatio ) ;
int endY = endInCoord ( outY , vRatio ) ;
int startX = startInCoord ( x , hRatio ) ;
int endX = endInCoord ( x , hRatio ) ;
auto dst = out . OutLine < unsigned char > ( l ) ;
for ( int inY = startY ; inY < endY ; inY + + )
for ( int x = 0 ; x < length ; x + + )
{
double startCoordY = inY / vRatio ;
double endCoordY = startCoordY + 1 / vRatio ;
float res = 0.0 ;
if ( startCoordY < y ) startCoordY = y ;
if ( endCoordY > y + 1 ) endCoordY = y + 1 ;
int startX = startInCoord ( x , hRatio ) ;
int endX = endInCoord ( x , hRatio ) ;
float fracY = static_cast < float > ( ( inY = = startY | | inY = = endY - 1 ) ? endCoordY - startCoordY : 1 / vRatio ) ;
for ( int inY = startY ; inY < endY ; inY + + )
{
double startCoordY = inY / vRatio ;
double endCoordY = startCoordY + 1 / vRatio ;
const auto src = in . InLine < unsigned char > ( inY - startY ) ;
if ( startCoordY < outY ) startCoordY = outY ;
if ( endCoordY > outY + 1 ) endCoordY = outY + 1 ;
float rowSum = 0.0f ;
float fracY = static_cast < float > ( ( inY = = startY | | inY = = endY - 1 ) ? endCoordY - startCoordY : 1 / vRatio ) ;
for ( int inX = startX ; inX < endX ; inX + + )
{
double startCoordX = inX / hRatio ;
double endCoordX = startCoordX + 1 / hRatio ;
const auto src = in . InLine < unsigned char > ( inY - firstViewLineIdx ) ;
float rowSum = 0.0f ;
if ( startCoordX < x ) startCoordX = x ;
if ( endCoordX > x + 1 ) endCoordX = x + 1 ;
for ( int inX = startX ; inX < endX ; inX + + )
{
double startCoordX = inX / hRatio ;
double endCoordX = startCoordX + 1 / hRatio ;
float fracX = static_cast < float > ( ( inX = = startX | | inX = = endX - 1 ) ? endCoordX - startCoordX : 1 / hRatio ) ;
if ( startCoordX < x ) startCoordX = x ;
if ( endCoordX > x + 1 ) endCoordX = x + 1 ;
rowSum + = src [ inX ] * fracX ;
float fracX = static_cast < float > ( ( inX = = startX | | inX = = endX - 1 ) ? endCoordX - startCoordX : 1 / hRatio ) ;
rowSum + = src [ inX ] * fracX ;
}
res + = rowSum * fracY ;
}
res + = rowSum * fracY ;
dst [ x ] = static_cast < unsigned char > ( std : : rint ( res ) ) ;
}
dst [ x ] = static_cast < unsigned char > ( std : : rint ( res ) ) ;
}
}
} ;
GAPI_FLUID_KERNEL ( FResizeAreaUpscale , cv : : gapi : : core : : GResize , true )
GAPI_FLUID_KERNEL ( FResizeAreaUpscale1Lpi , cv : : gapi : : core : : GResize , true )
{
static const int Window = 1 ;
static const auto Kind = GFluidKernel : : Kind : : Resize ;
@ -307,31 +323,80 @@ GAPI_FLUID_KERNEL(FResizeAreaUpscale, cv::gapi::core::GResize, true)
}
} ;
static auto fluidResizeTestPackage = [ ] ( int interpolation , cv : : Size szIn , cv : : Size szOut )
# define ADD_RESIZE_KERNEL_WITH_LPI(interp, lpi, scratch) \
struct Resize # # interp # # lpi # # LpiHelper : public FResize # # interp # # 1L pi { static const int LPI = lpi ; } ; \
struct FResize # # interp # # lpi # # Lpi : public cv : : GFluidKernelImpl < Resize # # interp # # lpi # # LpiHelper , cv : : gapi : : core : : GResize , scratch > { } ;
ADD_RESIZE_KERNEL_WITH_LPI ( NN , 2 , false )
ADD_RESIZE_KERNEL_WITH_LPI ( NN , 3 , false )
ADD_RESIZE_KERNEL_WITH_LPI ( NN , 4 , false )
ADD_RESIZE_KERNEL_WITH_LPI ( Linear , 2 , true )
ADD_RESIZE_KERNEL_WITH_LPI ( Linear , 3 , true )
ADD_RESIZE_KERNEL_WITH_LPI ( Linear , 4 , true )
ADD_RESIZE_KERNEL_WITH_LPI ( Area , 2 , false )
ADD_RESIZE_KERNEL_WITH_LPI ( Area , 3 , false )
ADD_RESIZE_KERNEL_WITH_LPI ( Area , 4 , false )
ADD_RESIZE_KERNEL_WITH_LPI ( AreaUpscale , 2 , true )
ADD_RESIZE_KERNEL_WITH_LPI ( AreaUpscale , 3 , true )
ADD_RESIZE_KERNEL_WITH_LPI ( AreaUpscale , 4 , true )
# undef ADD_RESIZE_KERNEL_WITH_LPI
static auto fluidResizeTestPackage = [ ] ( int interpolation , cv : : Size szIn , cv : : Size szOut , int lpi = 1 )
{
using namespace cv ;
using namespace cv : : gapi ;
bool upscale = szIn . width < szOut . width | | szIn . height < szOut . height ;
cv : : gapi : : GKernelPackage pkg ;
# define RESIZE_CASE(interp, lpi) \
case lpi : pkg = kernels < FCopy , FResize # # interp # # lpi # # Lpi > ( ) ; break ;
# define RESIZE_SWITCH(interp) \
switch ( lpi ) \
{ \
RESIZE_CASE ( interp , 1 ) \
RESIZE_CASE ( interp , 2 ) \
RESIZE_CASE ( interp , 3 ) \
RESIZE_CASE ( interp , 4 ) \
default : CV_Assert ( false ) ; \
}
GKernelPackage pkg ;
switch ( interpolation )
{
case cv : : INTER_NEAREST : pkg = cv : : gapi : : kernels < FCopy , FResizeNN > ( ) ; break ;
case cv : : INTER_LINEAR : pkg = cv : : gapi : : kernels < FCopy , FResizeLinear > ( ) ; break ;
case cv : : INTER_AREA : pkg = upscale ? cv : : gapi : : kernels < FCopy , FResizeAreaUpscale > ( )
: cv : : gapi : : kernels < FCopy , FResizeArea > ( ) ; break ;
case INTER_NEAREST : RESIZE_SWITCH ( NN ) ; break ;
case INTER_LINEAR : RESIZE_SWITCH ( Linear ) ; break ;
case INTER_AREA :
{
if ( upscale )
{
RESIZE_SWITCH ( AreaUpscale )
}
else
{
RESIZE_SWITCH ( Area ) ;
}
} break ;
default : CV_Assert ( false ) ;
}
return cv : : gapi : : combine ( pkg , fluidTestPackage , cv : : unite_policy : : KEEP ) ;
return combine ( pkg , fluidTestPackage , unite_policy : : KEEP ) ;
# undef RESIZE_SWITCH
# undef RESIZE_CASE
} ;
struct ResizeTestFluid : public TestWithParam < std : : tuple < int , int , cv : : Size , std : : tuple < cv : : Size , cv : : Rect > , double > > { } ;
struct ResizeTestFluid : public TestWithParam < std : : tuple < int , int , cv : : Size , std : : tuple < cv : : Size , cv : : Rect > , int , double > > { } ;
TEST_P ( ResizeTestFluid , SanityTest )
{
int type = 0 , interp = 0 ;
cv : : Size sz_in , sz_out ;
int lpi = 0 ;
double tolerance = 0.0 ;
cv : : Rect outRoi ;
std : : tuple < cv : : Size , cv : : Rect > outSizeAndRoi ;
std : : tie ( type , interp , sz_in , outSizeAndRoi , tolerance ) = GetParam ( ) ;
std : : tie ( type , interp , sz_in , outSizeAndRoi , lpi , tolerance ) = GetParam ( ) ;
std : : tie ( sz_out , outRoi ) = outSizeAndRoi ;
if ( outRoi = = cv : : Rect { } ) outRoi = { 0 , 0 , sz_out . width , sz_out . height } ;
if ( outRoi . width = = 0 ) outRoi . width = sz_out . width ;
@ -351,7 +416,7 @@ TEST_P(ResizeTestFluid, SanityTest)
auto out = cv : : gapi : : resize ( mid , sz_out , fx , fy , interp ) ;
cv : : GComputation c ( in , out ) ;
c . apply ( in_mat1 , out_mat , cv : : compile_args ( GFluidOutputRois { { outRoi } } , fluidResizeTestPackage ( interp , sz_in , sz_out ) ) ) ;
c . apply ( in_mat1 , out_mat , cv : : compile_args ( GFluidOutputRois { { outRoi } } , fluidResizeTestPackage ( interp , sz_in , sz_out , lpi ) ) ) ;
cv : : Mat mid_mat ;
cv : : blur ( in_mat1 , mid_mat , { 3 , 3 } , { - 1 , - 1 } , cv : : BORDER_REPLICATE ) ;
@ -383,6 +448,7 @@ INSTANTIATE_TEST_CASE_P(ResizeTestCPU, ResizeTestFluid,
std : : make_tuple ( cv : : Size ( 8 , 4 ) , cv : : Rect { 0 , 0 , 0 , 3 } ) ,
std : : make_tuple ( cv : : Size ( 8 , 4 ) , cv : : Rect { 0 , 1 , 0 , 2 } ) ,
std : : make_tuple ( cv : : Size ( 8 , 4 ) , cv : : Rect { 0 , 3 , 0 , 1 } ) ) ,
Values ( 1 , 2 , 3 , 4 ) , // lpi
Values ( 0.0 ) ) ) ;
INSTANTIATE_TEST_CASE_P ( ResizeAreaTestCPU , ResizeTestFluid ,
@ -406,6 +472,7 @@ INSTANTIATE_TEST_CASE_P(ResizeAreaTestCPU, ResizeTestFluid,
std : : make_tuple ( cv : : Size ( 8 , 4 ) , cv : : Rect { 0 , 0 , 0 , 3 } ) ,
std : : make_tuple ( cv : : Size ( 8 , 4 ) , cv : : Rect { 0 , 1 , 0 , 2 } ) ,
std : : make_tuple ( cv : : Size ( 8 , 4 ) , cv : : Rect { 0 , 3 , 0 , 1 } ) ) ,
Values ( 1 , 2 , 3 , 4 ) , // lpi
// Actually this tolerance only for cases where OpenCV
// uses ResizeAreaFast
Values ( 1.0 ) ) ) ;
@ -441,6 +508,7 @@ INSTANTIATE_TEST_CASE_P(ResizeUpscaleTestCPU, ResizeTestFluid,
std : : make_tuple ( cv : : Size ( 16 , 25 ) , cv : : Rect { 0 , 0 , 16 , 25 } ) ,
std : : make_tuple ( cv : : Size ( 16 , 7 ) , cv : : Rect { } ) ,
std : : make_tuple ( cv : : Size ( 16 , 8 ) , cv : : Rect { } ) ) ,
Values ( 1 , 2 , 3 , 4 ) , // lpi
Values ( 0.0 ) ) ) ;
INSTANTIATE_TEST_CASE_P ( ResizeUpscaleOneDimDownscaleAnother , ResizeTestFluid ,
@ -473,6 +541,7 @@ INSTANTIATE_TEST_CASE_P(ResizeUpscaleOneDimDownscaleAnother, ResizeTestFluid,
std : : make_tuple ( cv : : Size ( 5 , 11 ) , cv : : Rect { 0 , 3 , 0 , 3 } ) ,
std : : make_tuple ( cv : : Size ( 5 , 11 ) , cv : : Rect { 0 , 6 , 0 , 3 } ) ,
std : : make_tuple ( cv : : Size ( 5 , 11 ) , cv : : Rect { 0 , 9 , 0 , 2 } ) ) ,
Values ( 1 , 2 , 3 , 4 ) , // lpi
Values ( 0.0 ) ) ) ;
INSTANTIATE_TEST_CASE_P ( Resize400_384TestCPU , ResizeTestFluid ,
@ -480,6 +549,7 @@ INSTANTIATE_TEST_CASE_P(Resize400_384TestCPU, ResizeTestFluid,
Values ( cv : : INTER_NEAREST , cv : : INTER_LINEAR , cv : : INTER_AREA ) ,
Values ( cv : : Size ( 128 , 400 ) ) ,
Values ( std : : make_tuple ( cv : : Size ( 128 , 384 ) , cv : : Rect { } ) ) ,
Values ( 1 , 2 , 3 , 4 ) , // lpi
Values ( 0.0 ) ) ) ;
INSTANTIATE_TEST_CASE_P ( Resize220_400TestCPU , ResizeTestFluid ,
@ -487,6 +557,7 @@ INSTANTIATE_TEST_CASE_P(Resize220_400TestCPU, ResizeTestFluid,
Values ( cv : : INTER_LINEAR ) ,
Values ( cv : : Size ( 220 , 220 ) ) ,
Values ( std : : make_tuple ( cv : : Size ( 400 , 400 ) , cv : : Rect { } ) ) ,
Values ( 1 , 2 , 3 , 4 ) , // lpi
Values ( 0.0 ) ) ) ;
static auto cvBlur = [ ] ( const cv : : Mat & in , cv : : Mat & out , int kernelSize )