@ -2,7 +2,7 @@
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
//
// Copyright (C) 2018-2022 Intel Corporation
// Copyright (C) 2018-2023 Intel Corporation
# include "precomp.hpp"
@ -71,6 +71,28 @@ namespace IE = InferenceEngine;
namespace {
IE : : Layout toIE ( const std : : string & layout ) {
const std : : unordered_map < std : : string , IE : : Layout > layouts = {
{ " NCDHW " , IE : : Layout : : NCDHW } ,
{ " NDHWC " , IE : : Layout : : NDHWC } ,
{ " NHWC " , IE : : Layout : : NHWC } ,
{ " NCHW " , IE : : Layout : : NCHW } ,
{ " CHW " , IE : : Layout : : CHW } ,
{ " HWC " , IE : : Layout : : HWC } ,
{ " HW " , IE : : Layout : : HW } ,
{ " NC " , IE : : Layout : : NC } ,
{ " CN " , IE : : Layout : : CN } ,
{ " C " , IE : : Layout : : C } ,
} ;
const auto it = layouts . find ( layout ) ;
if ( it = = layouts . end ( ) ) {
cv : : util : : throw_error (
std : : logic_error ( " IE Backend: Unsupported layout: " + layout ) ) ;
}
return it - > second ;
} ;
inline IE : : ROI toIE ( const cv : : Rect & rc ) {
return IE : : ROI
{ 0u
@ -130,52 +152,90 @@ inline int toCV(IE::Precision prec) {
return - 1 ;
}
// NB: In short: Tensor - ND or 2D + precision != U8.
cv : : gapi : : ie : : TraitAs clarifyTrait ( const cv : : GMatDesc & mat_desc ,
const IE : : TensorDesc & tensor_desc ) {
// NB: This check does not include 2D matrices like {32, 16},
// which also falls under the category of tensors.
// The reason for this is that RGB images are also considered 2D
// as the channel component is not taken into account in this case.
if ( mat_desc . isND ( ) | | mat_desc . planar ) {
return cv : : gapi : : ie : : TraitAs : : TENSOR ;
}
// NB: If user provided 2D data in U8 precision
// and network expects NHWC/NCHW layout - data is image (most likely).
const auto layout = tensor_desc . getLayout ( ) ;
if ( layout = = IE : : Layout : : NCHW | | layout = = IE : : Layout : : NHWC ) {
if ( mat_desc . depth = = CV_8U ) {
return cv : : gapi : : ie : : TraitAs : : IMAGE ;
inline IE : : ResizeAlgorithm toIEInterp ( int interpolation ) {
switch ( interpolation ) {
case cv : : INTER_LINEAR : return IE : : RESIZE_BILINEAR ;
case cv : : INTER_AREA : return IE : : RESIZE_AREA ;
default : GAPI_Error ( " IE Backend: Unsupported resize algorithm " ) ;
}
// Unreachable code
GAPI_Assert ( false ) ;
}
template < typename Attr >
using AttrMap = cv : : gapi : : ie : : detail : : AttrMap < Attr > ;
template < typename Attr >
using LayerVariantAttr = cv : : gapi : : ie : : detail : : LayerVariantAttr < Attr > ;
template < typename Attr > AttrMap < Attr >
broadcastLayerAttr ( const LayerVariantAttr < Attr > & layer_attr ,
const std : : vector < std : : string > & layer_names ) {
AttrMap < Attr > map ;
if ( cv : : util : : holds_alternative < AttrMap < Attr > > ( layer_attr ) ) {
map = cv : : util : : get < AttrMap < Attr > > ( layer_attr ) ;
// NB: Validate map:
std : : unordered_set < std : : string > existing_layers =
{ layer_names . begin ( ) , layer_names . end ( ) } ;
for ( const auto & p : map ) {
const auto it = existing_layers . find ( p . first ) ;
if ( it = = existing_layers . end ( ) ) {
cv : : util : : throw_error (
std : : logic_error ( " IE Backend: Failed to "
" find layer with name: " + p . first ) ) ;
}
}
// NB: 2D data with precision != U8 provided for 4D layout.
std : : stringstream ss ;
ss < < " IE Backend: An inconsistency has been detected between "
" the provided data: " < < mat_desc < <
" and the network layout: " < < layout ;
cv : : util : : throw_error ( std : : logic_error ( ss . str ( ) ) ) ;
}
// NB: Otherwise trait is TENSOR.
// If there is an inconsistency between the data dimensions
// and the network layout, the "setBlob" will fail.
} else if ( cv : : util : : holds_alternative < Attr > ( layer_attr ) ) {
// NB: Broadcast value to all layers.
auto elem = cv : : util : : get < Attr > ( layer_attr ) ;
for ( auto & & layer_name : layer_names ) {
map . emplace ( layer_name , elem ) ;
}
}
return map ;
}
// TODO: Move it to some common place
template < typename K , typename V >
cv : : optional < V > lookUp ( const std : : map < K , V > & map , const K & key ) {
const auto it = map . find ( key ) ;
if ( it = = map . end ( ) ) {
return { } ;
}
return cv : : util : : make_optional ( std : : move ( it - > second ) ) ;
}
static bool isImage ( const cv : : GMatDesc & desc ,
const IE : : SizeVector & model_dims ) {
return ( model_dims . size ( ) = = 4u ) & &
( ! desc . isND ( ) ) /* dims == 2 */ & &
( desc . chan = = 1 | | desc . chan = = 3 ) & &
( desc . size . height ! = 1 & & desc . size . width ! = 1 ) & &
( desc . depth = = CV_8U ) ;
}
cv : : gapi : : ie : : TraitAs clarifyTrait ( const cv : : GMatDesc & mat_desc ,
const IE : : SizeVector & model_dims ) {
if ( isImage ( mat_desc , model_dims ) ) {
return cv : : gapi : : ie : : TraitAs : : IMAGE ;
}
return cv : : gapi : : ie : : TraitAs : : TENSOR ;
}
cv : : gapi : : ie : : TraitAs clarifyTrait ( const cv : : GMetaArg & meta ,
const IE : : TensorDesc & tensor_desc ) {
const IE : : SizeVector & model_dims ) {
// NB: All media formats: BGR, NV12, Gray
// are traited as image.
if ( cv : : util : : holds_alternative < cv : : GFrameDesc > ( meta ) ) {
return cv : : gapi : : ie : : TraitAs : : IMAGE ;
}
GAPI_Assert ( cv : : util : : holds_alternative < cv : : GMatDesc > ( meta ) ) ;
return clarifyTrait ( cv : : util : : get < cv : : GMatDesc > ( meta ) , tensor_desc ) ;
return clarifyTrait ( cv : : util : : get < cv : : GMatDesc > ( meta ) , model_dims ) ;
}
inline IE : : TensorDesc toIE ( const cv : : Mat & mat , cv : : gapi : : ie : : TraitAs hint ) {
const auto & sz = mat . size ;
// NB: For some reason RGB image is 2D image
// (since channel component is not counted here).
// Note: regular 2D vectors also fall into this category
if ( sz . dims ( ) = = 2 & & hint = = cv : : gapi : : ie : : TraitAs : : IMAGE )
{
// NB: This logic is mainly taken from IE samples
@ -196,8 +256,72 @@ inline IE::TensorDesc toIE(const cv::Mat &mat, cv::gapi::ie::TraitAs hint) {
return IE : : TensorDesc ( toIE ( mat . depth ( ) ) , toIE ( sz ) , toIELayout ( sz . dims ( ) ) ) ;
}
inline IE : : Blob : : Ptr wrapIE ( const cv : : Mat & mat , cv : : gapi : : ie : : TraitAs hint ) {
const auto tDesc = toIE ( mat , hint ) ;
// NB: Inference dimmensions always follow NCDHW order
// even though the real layout is different.
// E.g if user provided Mat({1, 240, 320, 3}, CV_8U) + NHWC layout
// need to create Blob(U8, {1, 3, 240, 320}, NHWC).
inline IE : : SizeVector toIEDims ( const IE : : SizeVector & dims ,
const IE : : Layout layout ) {
switch ( layout ) {
case IE : : Layout : : NDHWC : // NCDHW
return { dims [ 0 ] , dims [ 4 ] , dims [ 1 ] , dims [ 2 ] , dims [ 3 ] } ;
case IE : : Layout : : NHWC : // NCHW
return { dims [ 0 ] , dims [ 3 ] , dims [ 1 ] , dims [ 2 ] } ;
case IE : : Layout : : HWC : // CHW
return { dims [ 2 ] , dims [ 0 ] , dims [ 1 ] } ;
default : return dims ;
}
GAPI_Assert ( false ) ;
}
// NB: Inference dimmensions always follow NCDHW order
// even though the real layout is different.
// E.g if U8 blob has {1, 3, 240, 320} dims and NHWC layout
// need to create cv::Mat({1, 240, 320, 3}, CV_8U);
inline std : : vector < int > toCVDims ( const std : : vector < int > & dims ,
const IE : : Layout layout ) {
switch ( layout ) {
case IE : : Layout : : NDHWC : // NCDHW
return { dims [ 0 ] , dims [ 2 ] , dims [ 3 ] , dims [ 4 ] , dims [ 1 ] } ;
case IE : : Layout : : NHWC : // NCHW
return { dims [ 0 ] , dims [ 2 ] , dims [ 3 ] , dims [ 1 ] } ;
case IE : : Layout : : HWC : // CHW
return { dims [ 1 ] , dims [ 2 ] , dims [ 0 ] } ;
default : return dims ;
}
GAPI_Assert ( false ) ;
}
inline IE : : TensorDesc toIE ( const cv : : Mat & mat ,
const cv : : gapi : : ie : : TraitAs hint ,
const IE : : Layout layout ) {
const auto & sz = mat . size ;
if ( sz . dims ( ) = = 2 & & hint = = cv : : gapi : : ie : : TraitAs : : IMAGE )
{
// NB: This logic is mainly taken from IE samples
const size_t channels = mat . channels ( ) ;
const size_t height = mat . size ( ) . height ;
const size_t width = mat . size ( ) . width ;
const size_t strideH = mat . step1 ( ) ;
IE : : BlockingDesc bdesc ( { 1 , height , width , channels } /* blocking dims */ ,
{ 0 , 2 , 3 , 1 } /* order for NHWC */ ,
0 /* offset */ ,
{ 0 , 0 , 0 , 0 } /* offsets for dims */ ,
{ strideH * height , strideH , channels , 1 } /* strides for dims */ ) ;
return IE : : TensorDesc ( toIE ( mat . depth ( ) ) ,
IE : : SizeVector { 1 , channels , height , width } , bdesc ) ;
}
return IE : : TensorDesc ( toIE ( mat . depth ( ) ) ,
toIEDims ( toIE ( sz ) , layout ) ,
layout ) ;
}
inline IE : : Blob : : Ptr wrapIE ( const cv : : Mat & mat ,
cv : : gapi : : ie : : TraitAs hint ,
const IE : : Layout layout = IE : : Layout : : ANY ) {
const auto tDesc = toIE ( mat , hint , layout ) ;
switch ( mat . depth ( ) ) {
// NB: Seems there's no way to create an untyped (T-less) Blob::Ptr
// in IE given only precision via TensorDesc. So we have to do this:
@ -344,6 +468,7 @@ struct IEUnit {
} ;
InputFramesDesc net_input_params ;
std : : unordered_map < std : : string , cv : : gapi : : ie : : TraitAs > inputs_type ;
explicit IEUnit ( const cv : : gapi : : ie : : detail : : ParamDesc & pp )
: params ( pp ) {
@ -522,6 +647,8 @@ public:
cv : : GRunArgP output ( std : : size_t idx ) ;
cv : : Mat & outMatR ( std : : size_t idx ) ;
cv : : gapi : : ie : : TraitAs getInputType ( const std : : string & layer_name ) const ;
const IEUnit & uu ;
cv : : gimpl : : GIslandExecutable : : IOutput & out ;
@ -565,6 +692,9 @@ private:
// keep alive preprocessed frames
std : : mutex keep_alive_frames_mutex ;
std : : unordered_map < req_key_t , cv : : MediaFrame > keep_alive_pp_frames ;
// NB: Hint to wrap input data properly into IE::Blob (see: wrapIE)
std : : unordered_map < std : : string , cv : : gapi : : ie : : TraitAs > input_type ;
} ;
IECallContext : : IECallContext ( const IEUnit & unit ,
@ -599,6 +729,16 @@ IECallContext::IECallContext(const IEUnit &
}
}
cv : : gapi : : ie : : TraitAs
IECallContext : : getInputType ( const std : : string & layer_name ) const {
const auto it = uu . inputs_type . find ( layer_name ) ;
if ( it = = uu . inputs_type . end ( ) ) {
cv : : util : : throw_error ( std : : logic_error (
" Failed to find input type for layer: \" " + layer_name + " \" " ) ) ;
}
return it - > second ;
}
const cv : : GArgs & IECallContext : : inArgs ( ) const {
return m_args ;
}
@ -773,7 +913,8 @@ cv::MediaFrame preprocess_frame_impl(cv::MediaFrame &&in_frame, const std::strin
inline IE : : Blob : : Ptr extractBlob ( IECallContext & ctx ,
std : : size_t i ,
cv : : gapi : : ie : : TraitAs hint ,
const cv : : gapi : : ie : : TraitAs hint ,
const IE : : Layout & layout ,
const std : : string & layer_name ,
const cv : : util : : optional < cv : : Rect > & opt_roi ,
cv : : MediaFrame * out_keep_alive_frame = nullptr ,
@ -821,7 +962,7 @@ inline IE::Blob::Ptr extractBlob(IECallContext& ctx,
return wrapIE ( * ( ctx . views . back ( ) ) , frame . desc ( ) ) ;
}
case cv : : GShape : : GMAT : {
return wrapIE ( ctx . inMat ( i ) , hint ) ;
return wrapIE ( ctx . inMat ( i ) , hint , layout ) ;
}
default :
GAPI_Assert ( " Unsupported input shape for IE backend " ) ;
@ -829,7 +970,6 @@ inline IE::Blob::Ptr extractBlob(IECallContext& ctx,
GAPI_Error ( " InternalError " ) ;
}
static void setBlob ( InferenceEngine : : InferRequest & req ,
const std : : string & layer_name ,
const IE : : Blob : : Ptr & blob ,
@ -1203,79 +1343,110 @@ static void configureInputReshapeByImage(const IE::InputInfo::Ptr& ii,
input_reshape_table . emplace ( layer_name , input_dims ) ;
}
// NB: This function is used in order to configure
// preprocessing for "Load" case networks.
static void configureInputInfo ( const IE : : InputInfo : : Ptr & ii , const cv : : GMetaArg mm ) {
static void cfgInputPrecision ( const IE : : InputInfo : : Ptr & ii , const cv : : GMetaArg mm ) {
switch ( mm . index ( ) ) {
case cv : : GMetaArg : : index_of < cv : : GMatDesc > ( ) :
{
case cv : : GMetaArg : : index_of < cv : : GMatDesc > ( ) : {
const auto & desc = util : : get < cv : : GMatDesc > ( mm ) ;
ii - > setPrecision ( toIE ( desc . depth ) ) ;
// NB: Configure resize only for images.
const auto trait = clarifyTrait ( desc , ii - > getTensorDesc ( ) ) ;
if ( trait = = cv : : gapi : : ie : : TraitAs : : IMAGE ) {
ii - > getPreProcess ( ) . setResizeAlgorithm ( IE : : RESIZE_BILINEAR ) ;
}
break ;
}
case cv : : GMetaArg : : index_of < cv : : GFrameDesc > ( ) :
{
const auto & meta = util : : get < cv : : GFrameDesc > ( mm ) ;
switch ( meta . fmt ) {
case cv : : MediaFormat : : NV12 :
ii - > getPreProcess ( ) . setColorFormat ( IE : : ColorFormat : : NV12 ) ;
break ;
case cv : : MediaFormat : : BGR :
// NB: Do nothing
break ;
case cv : : MediaFormat : : GRAY :
// NB: Do nothing
break ;
default :
GAPI_Error ( " Unsupported media format for IE backend " ) ;
}
ii - > setPrecision ( toIE ( CV_8U ) ) ;
// NB: Always configure resize because media formats are images.
ii - > getPreProcess ( ) . setResizeAlgorithm ( IE : : RESIZE_BILINEAR ) ;
break ;
}
default :
util : : throw_error ( std : : runtime_error ( " Unsupported input meta for IE backend " ) ) ;
}
}
static void cfgImagePreprocessing ( const IE : : InputInfo : : Ptr & ii ,
const cv : : GMetaArg & mm ,
const IE : : ResizeAlgorithm interp ) {
if ( ! cv : : util : : holds_alternative < cv : : GMatDesc > ( mm ) & &
! cv : : util : : holds_alternative < cv : : GFrameDesc > ( mm ) ) {
util : : throw_error ( std : : runtime_error ( " Unsupported input meta for IE backend " ) ) ;
}
ii - > getPreProcess ( ) . setResizeAlgorithm ( interp ) ;
if ( cv : : util : : holds_alternative < cv : : GFrameDesc > ( mm ) ) {
const auto & meta = util : : get < cv : : GFrameDesc > ( mm ) ;
if ( meta . fmt = = cv : : MediaFormat : : NV12 ) {
ii - > getPreProcess ( ) . setColorFormat ( IE : : ColorFormat : : NV12 ) ;
}
}
}
// NB: This function is used in order to configure
// preprocessing for "Import" case networks.
static IE : : PreProcessInfo configurePreProcInfo ( const IE : : InputInfo : : CPtr & ii ,
const cv : : GMetaArg & mm ) {
IE : : PreProcessInfo info ;
switch ( mm . index ( ) ) {
// NB: Note that it doesn't specify precision.
case cv : : GMetaArg : : index_of < cv : : GMatDesc > ( ) :
{
// NB: Configure resize only for images.
const auto & desc = cv : : util : : get < cv : : GMatDesc > ( mm ) ;
const auto trait = clarifyTrait ( desc , ii - > getTensorDesc ( ) ) ;
if ( trait = = cv : : gapi : : ie : : TraitAs : : IMAGE ) {
info . setResizeAlgorithm ( IE : : RESIZE_BILINEAR ) ;
}
break ;
// preprocessing for "Load" case networks.
static void cfgInputPreprocessing ( const cv : : gapi : : ie : : TraitAs trait ,
const IE : : InputInfo : : Ptr & ii ,
const cv : : GMetaArg & mm ,
const std : : string & layer_name ,
const AttrMap < std : : string > & layout_map ,
const AttrMap < int > & interp_map ) {
cfgInputPrecision ( ii , mm ) ;
const auto explicit_input_layout = lookUp ( layout_map , layer_name ) ;
const auto explicit_resize = lookUp ( interp_map , layer_name ) ;
if ( trait = = cv : : gapi : : ie : : TraitAs : : IMAGE ) {
// NB: Image case - preprocessing is configured automatically.
GAPI_LOG_DEBUG ( NULL , " IE Backend: Input: \" " < <
layer_name < < " " < < mm < < " \" is image. " ) ;
// NB: BlockingDesc is used instead (see wrapIE)
if ( explicit_input_layout ) {
util : : throw_error ( std : : logic_error ( " Input data provided for layer: \" " +
layer_name + " \" is recognized as \" image \" . Explicitly " +
" specified layout is prohibited. " ) ) ;
}
// NB: Note that it doesn't specify precision.
case cv : : GMetaArg : : index_of < cv : : GFrameDesc > ( ) :
{
const auto & desc = cv : : util : : get < cv : : GFrameDesc > ( mm ) ;
if ( desc . fmt = = cv : : MediaFormat : : NV12 ) {
info . setColorFormat ( IE : : ColorFormat : : NV12 ) ;
}
// NB: Always configure resize because media formats are images.
info . setResizeAlgorithm ( IE : : RESIZE_BILINEAR ) ;
break ;
const auto interp = explicit_resize ? toIEInterp ( * explicit_resize )
: IE : : RESIZE_BILINEAR ;
cfgImagePreprocessing ( ii , mm , interp ) ;
} else {
// NB: Tensor case - preprocessing is configured only if user asked.
GAPI_LOG_DEBUG ( NULL , " IE Backend: Input: \" " < <
layer_name < < " \" " < < mm < < " is tensor. " ) ;
if ( explicit_input_layout ) {
GAPI_LOG_DEBUG ( NULL , " IE Backend: Set input layout \" " < <
* explicit_input_layout < < " \" for layer \" " < < layer_name < < " \" " ) ;
ii - > setLayout ( toIE ( * explicit_input_layout ) ) ;
}
if ( explicit_resize ) {
GAPI_LOG_DEBUG ( NULL , " IE Backend: Set resize for layer \" " < < layer_name < < " \" " ) ;
ii - > getPreProcess ( ) . setResizeAlgorithm ( toIEInterp ( * explicit_resize ) ) ;
}
default :
util : : throw_error ( std : : runtime_error ( " Unsupported input meta for IE backend " ) ) ;
}
}
static IE : : PreProcessInfo createImagePreProcInfo ( const cv : : GMetaArg & mm ,
const IE : : ResizeAlgorithm interp ) {
if ( ! cv : : util : : holds_alternative < cv : : GMatDesc > ( mm ) & &
! cv : : util : : holds_alternative < cv : : GFrameDesc > ( mm ) ) {
util : : throw_error ( std : : runtime_error ( " Unsupported input meta for IE backend " ) ) ;
}
IE : : PreProcessInfo info ;
info . setResizeAlgorithm ( interp ) ;
if ( cv : : util : : holds_alternative < cv : : GFrameDesc > ( mm ) ) {
const auto & meta = util : : get < cv : : GFrameDesc > ( mm ) ;
if ( meta . fmt = = cv : : MediaFormat : : NV12 ) {
info . setColorFormat ( IE : : ColorFormat : : NV12 ) ;
}
}
return info ;
}
// NB: This function is used in order to create
// preprocessing for "Import" case networks.
static IE : : PreProcessInfo createPreProcInfo ( const cv : : gapi : : ie : : TraitAs trait ,
const cv : : GMetaArg & mm ,
const cv : : optional < int > explicit_resize ) {
if ( trait = = cv : : gapi : : ie : : TraitAs : : IMAGE ) {
const auto interp = explicit_resize ? toIEInterp ( * explicit_resize )
: IE : : RESIZE_BILINEAR ;
return createImagePreProcInfo ( mm , interp ) ;
}
// NB: In case "tensor" only resize can't be spefied for "import" models.
IE : : PreProcessInfo info ;
if ( explicit_resize ) {
info . setResizeAlgorithm ( toIEInterp ( * explicit_resize ) ) ;
}
return info ;
}
@ -1301,6 +1472,13 @@ static void configureOutputPrecision(const IE::OutputsDataMap &outputs
) ;
}
static void configureOutputLayout ( const IE : : OutputsDataMap & outputs_info ,
const AttrMap < std : : string > & output_layout ) {
for ( const auto it : output_layout ) {
outputs_info . at ( it . first ) - > setLayout ( toIE ( it . second ) ) ;
}
}
// NB: This is a callback used by async infer
// to post outputs blobs (cv::GMat's).
static void PostOutputs ( InferenceEngine : : InferRequest & request ,
@ -1420,6 +1598,10 @@ struct Infer: public cv::detail::KernelTag {
GAPI_Assert ( uu . params . input_names . size ( ) = = in_metas . size ( )
& & " Known input layers count doesn't match input meta count " ) ;
const auto input_layout = broadcastLayerAttr ( uu . params . input_layout ,
uu . params . input_names ) ;
const auto interpolation = broadcastLayerAttr ( uu . params . interpolation ,
uu . params . input_names ) ;
// NB: Configuring input/output precision and network reshape must be done
// only in the loadNetwork case.
using namespace cv : : gapi : : ie : : detail ;
@ -1429,21 +1611,24 @@ struct Infer: public cv::detail::KernelTag {
ade : : util : : toRange ( in_metas ) ) ) {
const auto & input_name = std : : get < 0 > ( it ) ;
auto ii = inputs . at ( input_name ) ;
const auto & mm = std : : get < 1 > ( it ) ;
const auto & mm = std : : get < 1 > ( it ) ;
configureInputInfo ( ii , mm ) ;
if ( uu . params . layer_names_to_reshape . find ( input_name ) ! =
uu . params . layer_names_to_reshape . end ( ) ) {
configureInputReshapeByImage ( ii , mm , input_reshape_table ) ;
}
const auto trait = clarifyTrait ( mm , ii - > getTensorDesc ( ) . getDims ( ) ) ;
// FIXME: This is the only place where information about input type
// can be stored for the futher execution.
const_cast < IEUnit & > ( uu ) . inputs_type . emplace ( input_name , trait ) ;
cfgInputPreprocessing ( trait , ii , mm , input_name ,
input_layout , interpolation ) ;
// NB: configure input param for further preproc
if ( uu . net_input_params . is_applicable ( mm ) ) {
const_cast < IEUnit : : InputFramesDesc & > ( uu . net_input_params )
. set_param ( input_name , ii - > getTensorDesc ( ) ) ;
}
}
for ( auto & & p : uu . params . const_inputs ) {
const auto ii = inputs . at ( p . first ) ;
ii - > setPrecision ( toIE ( p . second . first . depth ( ) ) ) ;
@ -1455,6 +1640,10 @@ struct Infer: public cv::detail::KernelTag {
if ( ! input_reshape_table . empty ( ) ) {
const_cast < IE : : CNNNetwork * > ( & uu . net ) - > reshape ( input_reshape_table ) ;
}
const auto output_layout = broadcastLayerAttr ( uu . params . output_layout ,
uu . params . output_names ) ;
configureOutputLayout ( uu . net . getOutputsInfo ( ) , output_layout ) ;
configureOutputPrecision ( uu . net . getOutputsInfo ( ) , uu . params . output_precision ) ;
} else {
GAPI_Assert ( uu . params . kind = = ParamDesc : : Kind : : Import ) ;
@ -1466,7 +1655,13 @@ struct Infer: public cv::detail::KernelTag {
const auto & input_name = std : : get < 0 > ( it ) ;
auto ii = inputs . at ( input_name ) ;
const auto & mm = std : : get < 1 > ( it ) ;
non_const_prepm - > emplace ( input_name , configurePreProcInfo ( ii , mm ) ) ;
const auto trait = clarifyTrait ( mm , ii - > getTensorDesc ( ) . getDims ( ) ) ;
// FIXME: This is the only place where information about input type
// can be stored for the futher execution.
const_cast < IEUnit & > ( uu ) . inputs_type . emplace ( input_name , trait ) ;
const auto explicit_resize = lookUp ( interpolation , input_name ) ;
non_const_prepm - > emplace (
input_name , createPreProcInfo ( trait , mm , explicit_resize ) ) ;
// NB: configure input param for further preproc
if ( uu . net_input_params . is_applicable ( mm ) ) {
@ -1488,7 +1683,7 @@ struct Infer: public cv::detail::KernelTag {
: uu . this_network . GetOutputsInfo ( ) . at ( out_name ) - > getTensorDesc ( ) ;
cv : : GMatDesc outm ( toCV ( desc . getPrecision ( ) ) ,
toCV ( desc . getDims ( ) ) ) ;
toCVDims ( toCV ( desc . getDims ( ) ) , desc . getLayout ( ) ) ) ;
result . emplace_back ( outm ) ;
}
return result ;
@ -1504,15 +1699,10 @@ struct Infer: public cv::detail::KernelTag {
// - assumes all inputs/outputs are always Mats
for ( auto i : ade : : util : : iota ( ctx - > uu . params . num_in ) ) {
const auto & layer_name = ctx - > uu . params . input_names [ i ] ;
auto layout =
ctx - > uu . this_network . GetInputsInfo ( ) .
at ( layer_name ) - > getTensorDesc ( ) . getLayout ( ) ;
auto hint =
( layout = = IE : : Layout : : NCHW | | layout = = IE : : Layout : : NHWC )
? cv : : gapi : : ie : : TraitAs : : IMAGE : cv : : gapi : : ie : : TraitAs : : TENSOR ;
const auto hint = ctx - > getInputType ( layer_name ) ;
const auto layout = req . GetBlob ( layer_name ) - > getTensorDesc ( ) . getLayout ( ) ;
IE : : Blob : : Ptr this_blob = extractBlob ( * ctx , i , hint ,
layer_name ,
layout , layer_name ,
cv : : util : : optional < cv : : Rect > { } ) ;
setBlob ( req , layer_name , this_blob , * ctx ) ;
}
@ -1552,7 +1742,7 @@ struct InferROI: public cv::detail::KernelTag {
if ( cv : : util : : holds_alternative < cv : : GMatDesc > ( mm ) | |
cv : : util : : holds_alternative < cv : : GFrameDesc > ( mm ) ) {
const auto trait = clarifyTrait ( mm , tensor_desc ) ;
const auto trait = clarifyTrait ( mm , tensor_desc . getDims ( ) ) ;
if ( trait ! = cv : : gapi : : ie : : TraitAs : : IMAGE ) {
util : : throw_error ( std : : runtime_error (
" IE Backend: Only image is supported "
@ -1566,16 +1756,22 @@ struct InferROI: public cv::detail::KernelTag {
// NB: Configuring input precision and network reshape must be done
// only in the loadNetwork case.
const auto input_layout = broadcastLayerAttr ( uu . params . input_layout ,
uu . params . input_names ) ;
const auto interpolation = broadcastLayerAttr ( uu . params . interpolation ,
uu . params . input_names ) ;
const auto trait = cv : : gapi : : ie : : TraitAs : : IMAGE ;
if ( uu . params . kind = = cv : : gapi : : ie : : detail : : ParamDesc : : Kind : : Load ) {
// 0th is ROI, 1st is input image
auto inputs = uu . net . getInputsInfo ( ) ;
auto ii = inputs . at ( input_name ) ;
configureInputInfo ( ii , mm ) ;
if ( uu . params . layer_names_to_reshape . find ( input_name ) ! =
uu . params . layer_names_to_reshape . end ( ) ) {
configureInputReshapeByImage ( ii , mm , input_reshape_table ) ;
}
cfgInputPreprocessing ( trait , ii , mm , input_name ,
input_layout , interpolation ) ;
// FIXME: This isn't the best place to call reshape function.
// Сorrect solution would be to do this in compile() method of network,
@ -1594,6 +1790,9 @@ struct InferROI: public cv::detail::KernelTag {
inputs . at ( p . first ) - > setPrecision ( toIE ( p . second . first . depth ( ) ) ) ;
}
const auto output_layout = broadcastLayerAttr ( uu . params . output_layout ,
uu . params . output_names ) ;
configureOutputLayout ( uu . net . getOutputsInfo ( ) , output_layout ) ;
configureOutputPrecision ( uu . net . getOutputsInfo ( ) , uu . params . output_precision ) ;
} else {
GAPI_Assert ( uu . params . kind = = cv : : gapi : : ie : : detail : : ParamDesc : : Kind : : Import ) ;
@ -1601,8 +1800,9 @@ struct InferROI: public cv::detail::KernelTag {
// FIXME: This isn't the best place to collect PreProcMap.
auto * non_const_prepm = const_cast < IEUnit : : PreProcMap * > ( & uu . preproc_map ) ;
auto ii = inputs . at ( input_name ) ;
non_const_prepm - > emplace ( input_name , configurePreProcInfo ( ii , mm ) ) ;
const auto explicit_resize = lookUp ( interpolation , input_name ) ;
non_const_prepm - > emplace (
input_name , createPreProcInfo ( trait , mm , explicit_resize ) ) ;
// NB: configure intput param for further preproc
if ( uu . net_input_params . is_applicable ( mm ) ) {
@ -1623,7 +1823,7 @@ struct InferROI: public cv::detail::KernelTag {
: uu . this_network . GetOutputsInfo ( ) . at ( out_name ) - > getTensorDesc ( ) ;
cv : : GMatDesc outm ( toCV ( desc . getPrecision ( ) ) ,
toCV ( desc . getDims ( ) ) ) ;
toCVDims ( toCV ( desc . getDims ( ) ) , desc . getLayout ( ) ) ) ;
result . emplace_back ( outm ) ;
}
return result ;
@ -1646,6 +1846,7 @@ struct InferROI: public cv::detail::KernelTag {
bool preprocessed = false ;
IE : : Blob : : Ptr this_blob =
extractBlob ( * ctx , 1 , cv : : gapi : : ie : : TraitAs : : IMAGE ,
IE : : Layout : : ANY ,
* ( ctx - > uu . params . input_names . begin ( ) ) ,
cv : : util : : make_optional ( this_roi ) ,
slot_ptr , & preprocessed ) ;
@ -1691,6 +1892,10 @@ struct InferList: public cv::detail::KernelTag {
// NB: Configuring input precision and network reshape must be done
// only in the loadNetwork case.
const auto input_layout = broadcastLayerAttr ( uu . params . input_layout ,
uu . params . input_names ) ;
const auto interpolation = broadcastLayerAttr ( uu . params . interpolation ,
uu . params . input_names ) ;
if ( uu . params . kind = = cv : : gapi : : ie : : detail : : ParamDesc : : Kind : : Load ) {
std : : size_t idx = 1u ;
auto inputs = uu . net . getInputsInfo ( ) ;
@ -1699,20 +1904,19 @@ struct InferList: public cv::detail::KernelTag {
const auto & mm = in_metas [ idx + + ] ;
// NB: InferList expects the input starts with index 1 wil be the images.
const auto input_trait = clarifyTrait ( mm , ii - > getTensorDesc ( ) ) ;
const auto input_trait = clarifyTrait ( mm , ii - > getTensorDesc ( ) . getDims ( ) ) ;
if ( input_trait ! = cv : : gapi : : ie : : TraitAs : : IMAGE ) {
util : : throw_error ( std : : runtime_error (
" IE Backend: Only image is supported "
" as the " + std : : to_string ( idx ) + " th argument for InferList " ) ) ;
}
configureInputInfo ( ii , mm ) ;
if ( uu . params . layer_names_to_reshape . find ( input_name ) ! =
uu . params . layer_names_to_reshape . end ( ) ) {
configureInputReshapeByImage ( ii , mm , input_reshape_table ) ;
}
cfgInputPreprocessing ( input_trait , ii , mm ,
input_name , input_layout , interpolation ) ;
}
// FIXME: This isn't the best place to call reshape function.
@ -1727,6 +1931,9 @@ struct InferList: public cv::detail::KernelTag {
ii - > setPrecision ( toIE ( p . second . first . depth ( ) ) ) ;
}
const auto output_layout = broadcastLayerAttr ( uu . params . output_layout ,
uu . params . output_names ) ;
configureOutputLayout ( uu . net . getOutputsInfo ( ) , output_layout ) ;
configureOutputPrecision ( uu . net . getOutputsInfo ( ) , uu . params . output_precision ) ;
} else {
GAPI_Assert ( uu . params . kind = = cv : : gapi : : ie : : detail : : ParamDesc : : Kind : : Import ) ;
@ -1738,14 +1945,16 @@ struct InferList: public cv::detail::KernelTag {
const auto & mm = in_metas [ idx + + ] ;
// NB: InferList expects the input starts with index 1 wil be the images.
const auto input_trait = clarifyTrait ( mm , ii - > getTensorDesc ( ) ) ;
const auto input_trait = clarifyTrait ( mm , ii - > getTensorDesc ( ) . getDims ( ) ) ;
if ( input_trait ! = cv : : gapi : : ie : : TraitAs : : IMAGE ) {
util : : throw_error ( std : : runtime_error (
" IE Backend: Only image is supported "
" as the " + std : : to_string ( idx ) + " th argument for InferList " ) ) ;
}
non_const_prepm - > emplace ( input_name , configurePreProcInfo ( ii , mm ) ) ;
const auto explicit_resize = lookUp ( interpolation , input_name ) ;
non_const_prepm - > emplace (
input_name , createPreProcInfo ( input_trait , mm , explicit_resize ) ) ;
}
}
@ -1773,6 +1982,7 @@ struct InferList: public cv::detail::KernelTag {
// NB: This blob will be used to make roi from its, so
// it should be treated as image
IE : : Blob : : Ptr this_blob = extractBlob ( * ctx , 1 , cv : : gapi : : ie : : TraitAs : : IMAGE ,
IE : : Layout : : ANY ,
ctx - > uu . params . input_names [ 0u ] ,
cv : : util : : optional < cv : : Rect > { } ) ;
@ -1783,7 +1993,7 @@ struct InferList: public cv::detail::KernelTag {
ctx - > uu . params . kind = = cv : : gapi : : ie : : detail : : ParamDesc : : Kind : : Load
? ctx - > uu . net . getOutputsInfo ( ) . at ( out_name ) - > getTensorDesc ( )
: ctx - > uu . this_network . GetOutputsInfo ( ) . at ( out_name ) - > getTensorDesc ( ) ;
cached_dims [ i ] = toCV ( desc . getDims ( ) ) ;
cached_dims [ i ] = toCVDims ( toCV ( desc . getDims ( ) ) , desc . getLayout ( ) ) ;
// FIXME: Isn't this should be done automatically
// by some resetInternalData(), etc? (Probably at the GExecutor level)
auto & out_vec = ctx - > outVecR < cv : : Mat > ( i ) ;
@ -1849,7 +2059,7 @@ struct InferList2: public cv::detail::KernelTag {
if ( cv : : util : : holds_alternative < cv : : GMatDesc > ( mm_0 ) | |
cv : : util : : holds_alternative < cv : : GFrameDesc > ( mm_0 ) ) {
const auto trait = clarifyTrait ( mm_0 , tensor_desc_0 ) ;
const auto trait = clarifyTrait ( mm_0 , tensor_desc_0 . getDims ( ) ) ;
if ( trait ! = cv : : gapi : : ie : : TraitAs : : IMAGE ) {
util : : throw_error ( std : : runtime_error (
" IE Backend: Only images is "
@ -1862,23 +2072,29 @@ struct InferList2: public cv::detail::KernelTag {
}
std : : size_t idx = 1u ;
const auto input_layout = broadcastLayerAttr ( uu . params . input_layout ,
uu . params . input_names ) ;
const auto interpolation = broadcastLayerAttr ( uu . params . interpolation ,
uu . params . input_names ) ;
for ( auto & & input_name : uu . params . input_names ) {
const auto & mm = in_metas [ idx ] ;
GAPI_Assert ( util : : holds_alternative < cv : : GArrayDesc > ( mm )
& & " Non-array inputs are not supported " ) ;
if ( op . k . inKinds [ idx ] = = cv : : detail : : OpaqueKind : : CV_RECT ) {
const auto input_trait = cv : : gapi : : ie : : TraitAs : : IMAGE ;
// NB: Configuring input precision and network reshape must be done
// only in the loadNetwork case.
if ( uu . params . kind = = cv : : gapi : : ie : : detail : : ParamDesc : : Kind : : Load ) {
auto inputs = uu . net . getInputsInfo ( ) ;
// This is a cv::Rect -- configure the IE preprocessing
auto ii = inputs . at ( input_name ) ;
configureInputInfo ( ii , mm_0 ) ;
if ( uu . params . layer_names_to_reshape . find ( input_name ) ! =
uu . params . layer_names_to_reshape . end ( ) ) {
configureInputReshapeByImage ( ii , mm_0 , input_reshape_table ) ;
}
cfgInputPreprocessing ( input_trait , ii , mm_0 ,
input_name , input_layout , interpolation ) ;
for ( auto & & p : uu . params . const_inputs ) {
inputs . at ( p . first ) - > setPrecision ( toIE ( p . second . first . depth ( ) ) ) ;
@ -1890,19 +2106,32 @@ struct InferList2: public cv::detail::KernelTag {
if ( ! input_reshape_table . empty ( ) ) {
const_cast < IE : : CNNNetwork * > ( & uu . net ) - > reshape ( input_reshape_table ) ;
}
const auto output_layout = broadcastLayerAttr ( uu . params . output_layout ,
uu . params . output_names ) ;
configureOutputLayout ( uu . net . getOutputsInfo ( ) , output_layout ) ;
configureOutputPrecision ( uu . net . getOutputsInfo ( ) , uu . params . output_precision ) ;
} else {
GAPI_Assert ( uu . params . kind = = cv : : gapi : : ie : : detail : : ParamDesc : : Kind : : Import ) ;
auto inputs = uu . this_network . GetInputsInfo ( ) ;
auto * non_const_prepm = const_cast < IEUnit : : PreProcMap * > ( & uu . preproc_map ) ;
auto ii = inputs . at ( input_name ) ;
non_const_prepm - > emplace ( input_name , configurePreProcInfo ( ii , mm_0 ) ) ;
const auto explicit_resize = lookUp ( interpolation , input_name ) ;
non_const_prepm - > emplace (
input_name , createPreProcInfo ( input_trait , mm_0 , explicit_resize ) ) ;
}
} else {
// This is a cv::GMat (equals to: cv::Mat)
// Just validate that it is really the type
// (other types are prohibited here)
GAPI_Assert ( op . k . inKinds [ idx ] = = cv : : detail : : OpaqueKind : : CV_MAT ) ;
// NB: Well, it's even impossible to specify the precision since
// there is not such info in GArray<cv::GMat>
const auto explicit_resize = lookUp ( interpolation , input_name ) ;
const auto explicit_layout = lookUp ( input_layout , input_name ) ;
if ( explicit_resize | | explicit_layout ) {
util : : throw_error ( std : : logic_error (
" InferList2 doesn't support preprocessing for \" tensor \" 's arguments! " ) ) ;
}
}
idx + + ; // NB: Never forget to increment the counter
}
@ -1922,6 +2151,7 @@ struct InferList2: public cv::detail::KernelTag {
// NB: This blob will be used to make roi from its, so
// it should be treated as image
IE : : Blob : : Ptr blob_0 = extractBlob ( * ctx , 0 , cv : : gapi : : ie : : TraitAs : : IMAGE ,
IE : : Layout : : ANY ,
ctx - > uu . params . input_names [ 0u ] ,
cv : : util : : optional < cv : : Rect > { } ) ;
const auto list_size = ctx - > inArg < cv : : detail : : VectorRef > ( 1u ) . size ( ) ;
@ -1941,7 +2171,7 @@ struct InferList2: public cv::detail::KernelTag {
ctx - > uu . params . kind = = cv : : gapi : : ie : : detail : : ParamDesc : : Kind : : Load
? ctx - > uu . net . getOutputsInfo ( ) . at ( out_name ) - > getTensorDesc ( )
: ctx - > uu . this_network . GetOutputsInfo ( ) . at ( out_name ) - > getTensorDesc ( ) ;
cached_dims [ i ] = toCV ( desc . getDims ( ) ) ;
cached_dims [ i ] = toCVDims ( toCV ( desc . getDims ( ) ) , desc . getLayout ( ) ) ;
// FIXME: Isn't this should be done automatically
// by some resetInternalData(), etc? (Probably at the GExecutor level)
auto & out_vec = ctx - > outVecR < cv : : Mat > ( i ) ;
@ -1964,8 +2194,10 @@ struct InferList2: public cv::detail::KernelTag {
} else if ( this_vec . getKind ( ) = = cv : : detail : : OpaqueKind : : CV_MAT ) {
const auto & vec = this_vec . rref < cv : : Mat > ( ) ;
const auto & mat = vec [ list_idx ] ;
setBlob ( req , ctx - > uu . params . input_names [ in_idx ] ,
wrapIE ( mat , cv : : gapi : : ie : : TraitAs : : TENSOR ) ,
const auto layer_name = ctx - > uu . params . input_names [ in_idx ] ;
const auto layout = req . GetBlob ( layer_name ) - > getTensorDesc ( ) . getLayout ( ) ;
setBlob ( req , layer_name ,
wrapIE ( mat , cv : : gapi : : ie : : TraitAs : : TENSOR , layout ) ,
* ctx ) ;
} else {
GAPI_Assert ( false & &