未验证 提交 2104d61d 编写于 作者: A Alexander Smorkalov 提交者: GitHub

Merge pull request #23668 from TolyaTalamanov:at/fix-resize-applying-logic-ie-backend

WIP: [G-API] IE Backend: Update the condition for applying the resize preprocessing
...@@ -130,6 +130,47 @@ inline int toCV(IE::Precision prec) { ...@@ -130,6 +130,47 @@ inline int toCV(IE::Precision prec) {
return -1; 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;
}
// 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.
return cv::gapi::ie::TraitAs::TENSOR;
}
cv::gapi::ie::TraitAs clarifyTrait(const cv::GMetaArg &meta,
const IE::TensorDesc &tensor_desc) {
// 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);
}
inline IE::TensorDesc toIE(const cv::Mat &mat, cv::gapi::ie::TraitAs hint) { inline IE::TensorDesc toIE(const cv::Mat &mat, cv::gapi::ie::TraitAs hint) {
const auto &sz = mat.size; const auto &sz = mat.size;
// NB: For some reason RGB image is 2D image // NB: For some reason RGB image is 2D image
...@@ -1162,11 +1203,19 @@ static void configureInputReshapeByImage(const IE::InputInfo::Ptr& ii, ...@@ -1162,11 +1203,19 @@ static void configureInputReshapeByImage(const IE::InputInfo::Ptr& ii,
input_reshape_table.emplace(layer_name, input_dims); 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 configureInputInfo(const IE::InputInfo::Ptr& ii, const cv::GMetaArg mm) {
switch (mm.index()) { switch (mm.index()) {
case cv::GMetaArg::index_of<cv::GMatDesc>(): case cv::GMetaArg::index_of<cv::GMatDesc>():
{ {
ii->setPrecision(toIE(util::get<cv::GMatDesc>(mm).depth)); 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; break;
} }
case cv::GMetaArg::index_of<cv::GFrameDesc>(): case cv::GMetaArg::index_of<cv::GFrameDesc>():
...@@ -1186,6 +1235,8 @@ static void configureInputInfo(const IE::InputInfo::Ptr& ii, const cv::GMetaArg ...@@ -1186,6 +1235,8 @@ static void configureInputInfo(const IE::InputInfo::Ptr& ii, const cv::GMetaArg
GAPI_Error("Unsupported media format for IE backend"); GAPI_Error("Unsupported media format for IE backend");
} }
ii->setPrecision(toIE(CV_8U)); ii->setPrecision(toIE(CV_8U));
// NB: Always configure resize because media formats are images.
ii->getPreProcess().setResizeAlgorithm(IE::RESIZE_BILINEAR);
break; break;
} }
default: default:
...@@ -1193,25 +1244,38 @@ static void configureInputInfo(const IE::InputInfo::Ptr& ii, const cv::GMetaArg ...@@ -1193,25 +1244,38 @@ static void configureInputInfo(const IE::InputInfo::Ptr& ii, const cv::GMetaArg
} }
} }
static bool isApplicableForResize(const IE::TensorDesc& desc) { // NB: This function is used in order to configure
const auto layout = desc.getLayout(); // preprocessing for "Import" case networks.
const auto prec = desc.getPrecision();
return (layout == IE::Layout::NCHW || layout == IE::Layout::NHWC) &&
(prec == IE::Precision::FP32 || prec == IE::Precision::U8);
}
static IE::PreProcessInfo configurePreProcInfo(const IE::InputInfo::CPtr& ii, static IE::PreProcessInfo configurePreProcInfo(const IE::InputInfo::CPtr& ii,
const cv::GMetaArg& mm) { const cv::GMetaArg& mm) {
IE::PreProcessInfo info; IE::PreProcessInfo info;
if (cv::util::holds_alternative<cv::GFrameDesc>(mm)) { switch (mm.index()) {
auto desc = cv::util::get<cv::GFrameDesc>(mm); // 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;
}
// 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) { if (desc.fmt == cv::MediaFormat::NV12) {
info.setColorFormat(IE::ColorFormat::NV12); info.setColorFormat(IE::ColorFormat::NV12);
} }
} // NB: Always configure resize because media formats are images.
if (isApplicableForResize(ii->getTensorDesc())) {
info.setResizeAlgorithm(IE::RESIZE_BILINEAR); info.setResizeAlgorithm(IE::RESIZE_BILINEAR);
break;
} }
default:
util::throw_error(std::runtime_error("Unsupported input meta for IE backend"));
}
return info; return info;
} }
...@@ -1373,10 +1437,6 @@ struct Infer: public cv::detail::KernelTag { ...@@ -1373,10 +1437,6 @@ struct Infer: public cv::detail::KernelTag {
configureInputReshapeByImage(ii, mm, input_reshape_table); configureInputReshapeByImage(ii, mm, input_reshape_table);
} }
if (isApplicableForResize(ii->getTensorDesc())) {
ii->getPreProcess().setResizeAlgorithm(IE::RESIZE_BILINEAR);
}
// NB: configure input param for further preproc // NB: configure input param for further preproc
if (uu.net_input_params.is_applicable(mm)) { if (uu.net_input_params.is_applicable(mm)) {
const_cast<IEUnit::InputFramesDesc &>(uu.net_input_params) const_cast<IEUnit::InputFramesDesc &>(uu.net_input_params)
...@@ -1485,20 +1545,37 @@ struct InferROI: public cv::detail::KernelTag { ...@@ -1485,20 +1545,37 @@ struct InferROI: public cv::detail::KernelTag {
const auto &input_name = uu.params.input_names.at(0); const auto &input_name = uu.params.input_names.at(0);
auto &&mm = in_metas.at(1u); auto &&mm = in_metas.at(1u);
const auto &tensor_desc =
(uu.params.kind == cv::gapi::ie::detail::ParamDesc::Kind::Load)
? uu.net.getInputsInfo().at(input_name)->getTensorDesc()
: uu.this_network.GetInputsInfo().at(input_name)->getTensorDesc();
if (cv::util::holds_alternative<cv::GMatDesc>(mm) ||
cv::util::holds_alternative<cv::GFrameDesc>(mm)) {
const auto trait = clarifyTrait(mm, tensor_desc);
if (trait != cv::gapi::ie::TraitAs::IMAGE) {
util::throw_error(std::runtime_error(
"IE Backend: Only image is supported"
" as the 1th argument for InferROI"));
}
} else {
util::throw_error(std::runtime_error(
"IE Backend: Unsupported input meta for"
" 1th argument for InferROI"));
}
// NB: Configuring input precision and network reshape must be done // NB: Configuring input precision and network reshape must be done
// only in the loadNetwork case. // only in the loadNetwork case.
if (uu.params.kind == cv::gapi::ie::detail::ParamDesc::Kind::Load) { if (uu.params.kind == cv::gapi::ie::detail::ParamDesc::Kind::Load) {
// 0th is ROI, 1st is input image // 0th is ROI, 1st is input image
auto inputs = uu.net.getInputsInfo(); auto inputs = uu.net.getInputsInfo();
auto ii = inputs.at(input_name); auto ii = inputs.at(input_name);
configureInputInfo(ii, mm); configureInputInfo(ii, mm);
if (uu.params.layer_names_to_reshape.find(input_name) != if (uu.params.layer_names_to_reshape.find(input_name) !=
uu.params.layer_names_to_reshape.end()) { uu.params.layer_names_to_reshape.end()) {
configureInputReshapeByImage(ii, mm, input_reshape_table); configureInputReshapeByImage(ii, mm, input_reshape_table);
} }
if (isApplicableForResize(ii->getTensorDesc())) {
ii->getPreProcess().setResizeAlgorithm(IE::RESIZE_BILINEAR);
}
// FIXME: This isn't the best place to call reshape function. // FIXME: This isn't the best place to call reshape function.
// Сorrect solution would be to do this in compile() method of network, // Сorrect solution would be to do this in compile() method of network,
...@@ -1524,6 +1601,7 @@ struct InferROI: public cv::detail::KernelTag { ...@@ -1524,6 +1601,7 @@ struct InferROI: public cv::detail::KernelTag {
// FIXME: This isn't the best place to collect PreProcMap. // FIXME: This isn't the best place to collect PreProcMap.
auto* non_const_prepm = const_cast<IEUnit::PreProcMap*>(&uu.preproc_map); auto* non_const_prepm = const_cast<IEUnit::PreProcMap*>(&uu.preproc_map);
auto ii = inputs.at(input_name); auto ii = inputs.at(input_name);
non_const_prepm->emplace(input_name, configurePreProcInfo(ii, mm)); non_const_prepm->emplace(input_name, configurePreProcInfo(ii, mm));
// NB: configure intput param for further preproc // NB: configure intput param for further preproc
...@@ -1619,14 +1697,22 @@ struct InferList: public cv::detail::KernelTag { ...@@ -1619,14 +1697,22 @@ struct InferList: public cv::detail::KernelTag {
for (auto &&input_name : uu.params.input_names) { for (auto &&input_name : uu.params.input_names) {
auto ii = inputs.at(input_name); auto ii = inputs.at(input_name);
const auto & mm = in_metas[idx++]; 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());
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); configureInputInfo(ii, mm);
if (uu.params.layer_names_to_reshape.find(input_name) != if (uu.params.layer_names_to_reshape.find(input_name) !=
uu.params.layer_names_to_reshape.end()) { uu.params.layer_names_to_reshape.end()) {
configureInputReshapeByImage(ii, mm, input_reshape_table); configureInputReshapeByImage(ii, mm, input_reshape_table);
} }
if (isApplicableForResize(ii->getTensorDesc())) {
ii->getPreProcess().setResizeAlgorithm(IE::RESIZE_BILINEAR);
}
} }
// FIXME: This isn't the best place to call reshape function. // FIXME: This isn't the best place to call reshape function.
...@@ -1650,6 +1736,15 @@ struct InferList: public cv::detail::KernelTag { ...@@ -1650,6 +1736,15 @@ struct InferList: public cv::detail::KernelTag {
for (auto &&input_name : uu.params.input_names) { for (auto &&input_name : uu.params.input_names) {
auto ii = inputs.at(input_name); auto ii = inputs.at(input_name);
const auto & mm = in_metas[idx++]; 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());
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)); non_const_prepm->emplace(input_name, configurePreProcInfo(ii, mm));
} }
} }
...@@ -1744,28 +1839,26 @@ struct InferList2: public cv::detail::KernelTag { ...@@ -1744,28 +1839,26 @@ struct InferList2: public cv::detail::KernelTag {
// "blob"-based ones) // "blob"-based ones)
// FIXME: this is filtering not done, actually! GArrayDesc has // FIXME: this is filtering not done, actually! GArrayDesc has
// no hint for its underlying type! // no hint for its underlying type!
const auto &input_name_0 = uu.params.input_names.front();
const auto &mm_0 = in_metas[0u]; const auto &mm_0 = in_metas[0u];
switch (in_metas[0u].index()) { const auto &tensor_desc_0 =
case cv::GMetaArg::index_of<cv::GMatDesc>(): { (uu.params.kind == cv::gapi::ie::detail::ParamDesc::Kind::Load)
const auto &meta_0 = util::get<cv::GMatDesc>(mm_0); ? uu.net.getInputsInfo().at(input_name_0)->getTensorDesc()
GAPI_Assert( !meta_0.isND() : uu.this_network.GetInputsInfo().at(input_name_0)->getTensorDesc();
&& !meta_0.planar
&& "Only images are supported as the 0th argument"); if (cv::util::holds_alternative<cv::GMatDesc>(mm_0) ||
break; cv::util::holds_alternative<cv::GFrameDesc>(mm_0)) {
} const auto trait = clarifyTrait(mm_0, tensor_desc_0);
case cv::GMetaArg::index_of<cv::GFrameDesc>(): { if (trait != cv::gapi::ie::TraitAs::IMAGE) {
// FIXME: Is there any validation for GFrame ? util::throw_error(std::runtime_error(
break; "IE Backend: Only images is"
" supported as the 0th argument"));
} }
default: } else {
util::throw_error(std::runtime_error("Unsupported input meta for IE backend")); util::throw_error(std::runtime_error(
} "IE Backend: Unsupported input meta"
" for 0th argument in IE backend"));
if (util::holds_alternative<cv::GMatDesc>(mm_0)) {
const auto &meta_0 = util::get<cv::GMatDesc>(mm_0);
GAPI_Assert( !meta_0.isND()
&& !meta_0.planar
&& "Only images are supported as the 0th argument");
} }
std::size_t idx = 1u; std::size_t idx = 1u;
...@@ -1786,9 +1879,6 @@ struct InferList2: public cv::detail::KernelTag { ...@@ -1786,9 +1879,6 @@ struct InferList2: public cv::detail::KernelTag {
uu.params.layer_names_to_reshape.end()) { uu.params.layer_names_to_reshape.end()) {
configureInputReshapeByImage(ii, mm_0, input_reshape_table); configureInputReshapeByImage(ii, mm_0, input_reshape_table);
} }
if (isApplicableForResize(ii->getTensorDesc())) {
ii->getPreProcess().setResizeAlgorithm(IE::RESIZE_BILINEAR);
}
for (auto &&p : uu.params.const_inputs) { for (auto &&p : uu.params.const_inputs) {
inputs.at(p.first)->setPrecision(toIE(p.second.first.depth())); inputs.at(p.first)->setPrecision(toIE(p.second.first.depth()));
......
...@@ -2238,7 +2238,7 @@ TEST(TestAgeGenderIE, InferWithBatch) ...@@ -2238,7 +2238,7 @@ TEST(TestAgeGenderIE, InferWithBatch)
params.weights_path = findDataFile(SUBDIR + "age-gender-recognition-retail-0013.bin"); params.weights_path = findDataFile(SUBDIR + "age-gender-recognition-retail-0013.bin");
params.device_id = "CPU"; params.device_id = "CPU";
cv::Mat in_mat({batch_size, 3, 320, 240}, CV_8U); cv::Mat in_mat({batch_size, 3, 62, 62}, CV_8U);
cv::randu(in_mat, 0, 255); cv::randu(in_mat, 0, 255);
cv::Mat gapi_age, gapi_gender; cv::Mat gapi_age, gapi_gender;
...@@ -2248,7 +2248,8 @@ TEST(TestAgeGenderIE, InferWithBatch) ...@@ -2248,7 +2248,8 @@ TEST(TestAgeGenderIE, InferWithBatch)
{ {
auto plugin = cv::gimpl::ie::wrap::getPlugin(params); auto plugin = cv::gimpl::ie::wrap::getPlugin(params);
auto net = cv::gimpl::ie::wrap::readNetwork(params); auto net = cv::gimpl::ie::wrap::readNetwork(params);
setNetParameters(net); auto ii = net.getInputsInfo().at("data");
ii->setPrecision(IE::Precision::U8);
net.setBatchSize(batch_size); net.setBatchSize(batch_size);
auto this_network = cv::gimpl::ie::wrap::loadNetwork(plugin, net, params); auto this_network = cv::gimpl::ie::wrap::loadNetwork(plugin, net, params);
auto infer_request = this_network.CreateInferRequest(); auto infer_request = this_network.CreateInferRequest();
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册