Files
openvino/samples/cpp/benchmark_app/utils.cpp
Zlobin Vladimir 787ba3de4f replace benchmark_app imean and iscale parameters (#14621)
* replace benchmark_app imean and iscale parameters

Tickets 80777 and 80900

* Warn about difference with imean and iscale, note that in help

* Clang format

* Clang format

* mean->scale

* Keep mean scale empty if not set

Co-authored-by: Andrei Kochin <andrei.kochin@intel.com>
2022-12-19 09:27:39 +04:00

888 lines
39 KiB
C++

// Copyright (C) 2018-2022 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include <format_reader_ptr.h>
#include <algorithm>
#include <map>
#include <regex>
#include <string>
#include <utility>
#include <vector>
// clang-format off
#include <samples/args_helper.hpp>
#include <samples/common.hpp>
#include <samples/slog.hpp>
#include "utils.hpp"
// clang-format on
#ifdef JSON_HEADER
# include <json.hpp>
#else
# include <nlohmann/json.hpp>
#endif
#ifdef USE_OPENCV
# include <opencv2/core.hpp>
#endif
namespace benchmark_app {
bool InputInfo::is_image() const {
if ((layout != "NCHW") && (layout != "NHWC") && (layout != "CHW") && (layout != "HWC"))
return false;
// If data_shape is still empty, assume this is still an Image and tensor shape will be filled later
return (dataShape.empty() || channels() == 3);
}
bool InputInfo::is_image_info() const {
if (layout != "NC")
return false;
return (channels() >= 2);
}
size_t InputInfo::width() const {
return dataShape.at(ov::layout::width_idx(layout));
}
size_t InputInfo::height() const {
return dataShape.at(ov::layout::height_idx(layout));
}
size_t InputInfo::channels() const {
return dataShape.at(ov::layout::channels_idx(layout));
}
size_t InputInfo::batch() const {
return dataShape.at(ov::layout::batch_idx(layout));
}
size_t InputInfo::depth() const {
return dataShape.at(ov::layout::depth_idx(layout));
}
} // namespace benchmark_app
uint32_t device_default_device_duration_in_seconds(const std::string& device) {
static const std::map<std::string, uint32_t> deviceDefaultDurationInSeconds{{"CPU", 60},
{"GPU", 60},
{"VPU", 60},
{"MYRIAD", 60},
{"HDDL", 60},
{"UNKNOWN", 120}};
uint32_t duration = 0;
for (const auto& deviceDurationInSeconds : deviceDefaultDurationInSeconds) {
if (device.find(deviceDurationInSeconds.first) != std::string::npos) {
duration = std::max(duration, deviceDurationInSeconds.second);
}
}
if (duration == 0) {
const auto unknownDeviceIt = find_if(deviceDefaultDurationInSeconds.begin(),
deviceDefaultDurationInSeconds.end(),
[](std::pair<std::string, uint32_t> deviceDuration) {
return deviceDuration.first == "UNKNOWN";
});
if (unknownDeviceIt == deviceDefaultDurationInSeconds.end()) {
throw std::logic_error("UNKNOWN device was not found in the device duration list");
}
duration = unknownDeviceIt->second;
slog::warn << "Default duration " << duration << " seconds for unknown device '" << device << "' is used"
<< slog::endl;
}
return duration;
}
std::vector<std::string> split(const std::string& s, char delim) {
std::vector<std::string> result;
std::stringstream ss(s);
std::string item;
while (getline(ss, item, delim)) {
result.push_back(item);
}
return result;
}
std::vector<float> split_float(const std::string& s, char delim) {
std::vector<float> result;
std::stringstream ss(s);
std::string item;
while (getline(ss, item, delim)) {
result.push_back(std::stof(item));
}
return result;
}
std::vector<std::string> parse_devices(const std::string& device_string) {
std::string comma_separated_devices = device_string;
auto colon = comma_separated_devices.find(":");
std::vector<std::string> result;
if (colon != std::string::npos) {
auto target_device = comma_separated_devices.substr(0, colon);
if (target_device == "AUTO" || target_device == "MULTI") {
result.push_back(target_device);
}
auto bracket = comma_separated_devices.find("("); // e.g. in BATCH:GPU(4)
comma_separated_devices = comma_separated_devices.substr(colon + 1, bracket - colon - 1);
}
auto devices = split(comma_separated_devices, ',');
result.insert(result.end(), devices.begin(), devices.end());
return result;
}
void parse_value_for_virtual_device(const std::string& device, std::map<std::string, std::string>& values_string) {
auto item_virtual = values_string.find(device);
if (item_virtual != values_string.end() && values_string.size() > 1) {
if (device == "MULTI") {
// Remove the element that the key is virtual device MULTI
// e.g. MULTI:xxx -nstreams 2 will set nstreams 2 to xxx.
values_string.erase(item_virtual);
} else if (device == "AUTO") {
// Just keep the element that the key is virtual device AUTO
// e.g. AUTO:xxx,xxx -nstreams 2 will trigger exception that AUTO plugin didn't support nstream property.
auto value = item_virtual->second;
values_string.clear();
values_string[device] = value;
return;
}
}
auto iter = values_string.begin();
while (iter != values_string.end()) {
if (iter->first == device) {
iter++;
continue;
}
values_string[device] += iter->first + " " + iter->second + " ";
iter = values_string.erase(iter);
}
if (values_string.find(device) != values_string.end()) {
auto& nstreams = values_string[device];
// Remove the space at the tail.
nstreams.pop_back();
}
return;
}
std::map<std::string, std::string> parse_value_per_device(const std::vector<std::string>& devices,
const std::string& values_string) {
// Format: <device1>:<value1>,<device2>:<value2> or just <value>
std::map<std::string, std::string> result;
auto device_value_strings = split(values_string, ',');
for (auto& device_value_string : device_value_strings) {
auto device_value_vec = split(device_value_string, ':');
if (device_value_vec.size() == 2) {
auto device_name = device_value_vec.at(0);
auto value = device_value_vec.at(1);
auto it = std::find(devices.begin(), devices.end(), device_name);
if (it != devices.end()) {
result[device_name] = value;
} else {
std::string devices_list = "";
for (auto& device : devices)
devices_list += device + " ";
devices_list.pop_back();
throw std::logic_error("Failed to set property to '" + device_name +
"' which is not found whthin the target devices list '" + devices_list + "'!");
}
} else if (device_value_vec.size() == 1) {
auto value = device_value_vec.at(0);
for (auto& device : devices) {
result[device] = value;
}
} else if (device_value_vec.size() != 0) {
throw std::runtime_error("Unknown string format: " + values_string);
}
}
return result;
}
size_t get_batch_size(const benchmark_app::InputsInfo& inputs_info) {
size_t batch_size = 0;
for (auto& info : inputs_info) {
if (ov::layout::has_batch(info.second.layout)) {
if (batch_size == 0)
batch_size = info.second.batch();
else if (batch_size != info.second.batch())
throw std::logic_error("Can't deterimine batch size: batch is "
"different for different inputs!");
}
}
if (batch_size == 0) {
batch_size = 1;
}
return batch_size;
}
std::string get_shapes_string(const benchmark_app::PartialShapes& shapes) {
std::stringstream ss;
for (auto& shape : shapes) {
if (!ss.str().empty())
ss << ", ";
ss << "\'" << shape.first << "': " << shape.second;
}
return ss.str();
}
std::map<std::string, std::vector<float>> parse_scale_or_mean(const std::string& scale_mean,
const benchmark_app::InputsInfo& inputs_info) {
// Format: data[255,255,255],info[255,255,255]
std::map<std::string, std::vector<float>> return_value;
std::string search_string = scale_mean;
auto start_pos = search_string.find_first_of('[');
while (start_pos != std::string::npos) {
auto end_pos = search_string.find_first_of(']');
if (end_pos == std::string::npos)
break;
auto input_name = search_string.substr(0, start_pos);
auto input_value_string = search_string.substr(start_pos + 1, end_pos - start_pos - 1);
auto input_value = split_float(input_value_string, ',');
if (!input_name.empty()) {
if (inputs_info.count(input_name)) {
return_value[input_name] = input_value;
}
// ignore wrong input name
} else {
for (auto& item : inputs_info) {
if (item.second.is_image())
return_value[item.first] = input_value;
}
search_string.clear();
break;
}
search_string = search_string.substr(end_pos + 1);
if (search_string.empty() || search_string.front() != ',')
break;
search_string = search_string.substr(1);
start_pos = search_string.find_first_of('[');
}
if (!search_string.empty())
throw std::logic_error("Can't parse input parameter string: " + scale_mean);
return return_value;
}
std::pair<std::string, std::vector<std::string>> parse_input_files(const std::string& file_paths_string) {
auto search_string = file_paths_string;
std::string input_name = "";
std::vector<std::string> file_paths;
// parse strings like <input1>:file1,file2,file3 and get name from them
size_t semicolon_pos = search_string.find_first_of(":");
size_t quote_pos = search_string.find_first_of("\"");
if (semicolon_pos != std::string::npos && quote_pos != std::string::npos && semicolon_pos > quote_pos) {
// if : is found after opening " symbol - this means that " belongs to pathname
semicolon_pos = std::string::npos;
}
if (search_string.length() > 2 && semicolon_pos == 1 && search_string[2] == '\\') {
// Special case like C:\ denotes drive name, not an input name
semicolon_pos = std::string::npos;
}
if (semicolon_pos != std::string::npos) {
input_name = search_string.substr(0, semicolon_pos);
search_string = search_string.substr(semicolon_pos + 1);
}
// parse file1,file2,file3 and get vector of paths
size_t coma_pos = 0;
do {
coma_pos = search_string.find_first_of(',');
file_paths.push_back(search_string.substr(0, coma_pos));
if (coma_pos == std::string::npos) {
search_string = "";
break;
}
search_string = search_string.substr(coma_pos + 1);
} while (coma_pos != std::string::npos);
if (!search_string.empty())
throw std::logic_error("Can't parse file paths for input " + input_name +
" in input parameter string: " + file_paths_string);
return {input_name, file_paths};
}
std::map<std::string, std::vector<std::string>> parse_input_arguments(const std::vector<std::string>& args) {
std::map<std::string, std::vector<std::string>> mapped_files = {};
auto args_it = begin(args);
const auto is_image_arg = [](const std::string& s) {
return s == "-i";
};
const auto is_arg = [](const std::string& s) {
return s.front() == '-';
};
while (args_it != args.end()) {
const auto files_start = std::find_if(args_it, end(args), is_image_arg);
if (files_start == end(args)) {
break;
}
const auto files_begin = std::next(files_start);
const auto files_end = std::find_if(files_begin, end(args), is_arg);
for (auto f = files_begin; f != files_end; ++f) {
auto files = parse_input_files(*f);
if (mapped_files.find(files.first) == mapped_files.end()) {
mapped_files[files.first] = {};
}
for (auto& file : files.second) {
if (file == "image_info" || file == "random") {
mapped_files[files.first].push_back(file);
} else {
readInputFilesArguments(mapped_files[files.first], file);
}
}
}
args_it = files_end;
}
size_t max_files = 20;
for (auto& files : mapped_files) {
if (files.second.size() <= max_files) {
slog::info << "For input " << files.first << " " << files.second.size() << " files were added. "
<< slog::endl;
} else {
slog::info << "For input " << files.first << " " << files.second.size() << " files were added. "
<< " The number of files will be limited to " << max_files << "." << slog::endl;
files.second.resize(20);
}
}
return mapped_files;
}
std::map<std::string, std::vector<std::string>> parse_input_parameters(
const std::string& parameter_string,
const std::vector<ov::Output<const ov::Node>>& input_info) {
// Parse parameter string like "input0[value0],input1[value1]" or "[value]" (applied to all
// inputs)
std::map<std::string, std::vector<std::string>> return_value;
std::string search_string = parameter_string;
auto start_pos = search_string.find_first_of('[');
auto input_name = search_string.substr(0, start_pos);
while (start_pos != std::string::npos) {
auto end_pos = search_string.find_first_of(']');
if (end_pos == std::string::npos)
break;
if (start_pos)
input_name = search_string.substr(0, start_pos);
auto input_value = search_string.substr(start_pos + 1, end_pos - start_pos - 1);
if (!input_name.empty()) {
return_value[parameter_name_to_tensor_name(input_name, input_info)].push_back(input_value);
} else {
for (auto& item : input_info) {
return_value[item.get_any_name()].push_back(input_value);
}
}
search_string = search_string.substr(end_pos + 1);
if (search_string.empty() || (search_string.front() != ',' && search_string.front() != '['))
break;
if (search_string.front() == ',')
search_string = search_string.substr(1);
start_pos = search_string.find_first_of('[');
}
if (!search_string.empty())
throw std::logic_error("Can't parse input parameter string: " + parameter_string);
return return_value;
}
std::vector<benchmark_app::InputsInfo> get_inputs_info(const std::string& shape_string,
const std::string& layout_string,
const size_t batch_size,
const std::string& data_shapes_string,
const std::map<std::string, std::vector<std::string>>& fileNames,
const std::string& scale_string,
const std::string& mean_string,
const std::vector<ov::Output<const ov::Node>>& input_info,
bool& reshape_required) {
std::map<std::string, std::vector<std::string>> shape_map = parse_input_parameters(shape_string, input_info);
std::map<std::string, std::vector<std::string>> data_shapes_map =
parse_input_parameters(data_shapes_string, input_info);
std::map<std::string, std::vector<std::string>> layout_map = parse_input_parameters(layout_string, input_info);
size_t min_size = 1, max_size = 1;
if (!data_shapes_map.empty()) {
min_size = std::min_element(data_shapes_map.begin(),
data_shapes_map.end(),
[](std::pair<std::string, std::vector<std::string>> a,
std::pair<std::string, std::vector<std::string>> b) {
return a.second.size() < b.second.size() && a.second.size() != 1;
})
->second.size();
max_size = std::max_element(data_shapes_map.begin(),
data_shapes_map.end(),
[](std::pair<std::string, std::vector<std::string>> a,
std::pair<std::string, std::vector<std::string>> b) {
return a.second.size() < b.second.size();
})
->second.size();
if (min_size != max_size) {
throw std::logic_error(
"Shapes number for every input should be either 1 or should be equal to shapes number of other inputs");
}
slog::info << "Number of test configurations is calculated basing on -data_shape parameter" << slog::endl;
} else if (fileNames.size() > 0) {
slog::info << "Number of test configurations is calculated basing on number of input images" << slog::endl;
min_size = std::min_element(fileNames.begin(),
fileNames.end(),
[](std::pair<std::string, std::vector<std::string>> a,
std::pair<std::string, std::vector<std::string>> b) {
return a.second.size() < b.second.size() && a.second.size() != 1;
})
->second.size();
max_size = std::max_element(fileNames.begin(),
fileNames.end(),
[](std::pair<std::string, std::vector<std::string>> a,
std::pair<std::string, std::vector<std::string>> b) {
return a.second.size() < b.second.size();
})
->second.size();
if (min_size != max_size) {
slog::warn << "Number of input files is different for some inputs, minimal number of files will be used ("
<< min_size << ")" << slog::endl;
}
}
reshape_required = false;
std::map<std::string, int> currentFileCounters;
for (auto& item : input_info) {
currentFileCounters[item.get_any_name()] = 0;
}
std::vector<benchmark_app::InputsInfo> info_maps;
for (size_t input_id = 0; input_id < min_size; ++input_id) {
benchmark_app::InputsInfo info_map;
bool is_there_at_least_one_batch_dim = false;
for (auto& item : input_info) {
benchmark_app::InputInfo info;
auto name = item.get_any_name();
// Layout
if (layout_map.count(name)) {
if (layout_map.at(name).size() > 1) {
throw std::logic_error(
"layout command line parameter doesn't support multiple layouts for one input.");
}
info.layout = ov::Layout(layout_map.at(name)[0]);
} else {
info.layout = dynamic_cast<const ov::op::v0::Parameter&>(*item.get_node()).get_layout();
}
// Calculating default layout values if needed
std::string newLayout = "";
if (info.layout.empty()) {
switch (item.get_partial_shape().size()) {
case 3:
newLayout = (item.get_partial_shape()[2].get_max_length() <= 4 &&
item.get_partial_shape()[0].get_max_length() > 4)
? "HWC"
: "CHW";
break;
case 4:
// Rough check for layout type, basing on max number of image channels
newLayout = (item.get_partial_shape()[3].get_max_length() <= 4 &&
item.get_partial_shape()[1].get_max_length() > 4)
? "NHWC"
: "NCHW";
break;
}
if (newLayout != "") {
info.layout = ov::Layout(newLayout);
}
if (info_maps.empty()) { // Show warnings only for 1st test case config, as for other test cases
// they will be the same
slog::warn << item.get_any_name() << ": layout is not set explicitly"
<< (newLayout != "" ? std::string(", so it is defaulted to ") + newLayout : "")
<< ". It is STRONGLY recommended to set layout manually to avoid further issues."
<< slog::endl;
}
}
// Precision
info.type = item.get_element_type();
// Partial Shape
if (shape_map.count(name)) {
if (shape_map.at(name).size() > 1) {
throw std::logic_error(
"shape command line parameter doesn't support multiple shapes for one input.");
}
info.partialShape = shape_map.at(name)[0];
reshape_required = true;
} else {
info.partialShape = item.get_partial_shape();
}
// Files might be mapped without input name. In case of only one input we may map them to the only input
// directly
std::string filesInputName =
fileNames.size() == 1 && input_info.size() == 1 && fileNames.begin()->first == "" ? "" : name;
// Tensor Shape
if (info.partialShape.is_dynamic() && data_shapes_map.count(name)) {
info.dataShape = data_shapes_map.at(name)[input_id % data_shapes_map.at(name).size()];
} else if (info.partialShape.is_dynamic() && fileNames.count(filesInputName) && info.is_image()) {
auto& namesVector = fileNames.at(filesInputName);
if (contains_binaries(namesVector)) {
throw std::logic_error("Input files list for input " + item.get_any_name() +
" contains binary file(s) and input shape is dynamic. Tensor shape should "
"be defined explicitly (using -data_shape).");
}
info.dataShape = ov::Shape(info.partialShape.size(), 0);
for (int i = 0; i < info.partialShape.size(); i++) {
auto& dim = info.partialShape[i];
if (dim.is_static()) {
info.dataShape[i] = dim.get_length();
}
}
size_t tensorBatchSize = std::max(batch_size, (size_t)1);
if (ov::layout::has_batch(info.layout)) {
if (info.batch()) {
tensorBatchSize = std::max(tensorBatchSize, info.batch());
} else {
info.dataShape[ov::layout::batch_idx(info.layout)] = tensorBatchSize;
}
}
size_t w = 0;
size_t h = 0;
size_t fileIdx = currentFileCounters[item.get_any_name()];
for (; fileIdx < currentFileCounters[item.get_any_name()] + tensorBatchSize; fileIdx++) {
if (fileIdx >= namesVector.size()) {
throw std::logic_error(
"Not enough files to fill in full batch (number of files should be a multiple of batch "
"size if -data_shape parameter is omitted and shape is dynamic)");
}
FormatReader::ReaderPtr reader(namesVector[fileIdx].c_str());
if ((w && w != reader->width()) || (h && h != reader->height())) {
throw std::logic_error("Image sizes putting into one batch should be of the same size if input "
"shape is dynamic and -data_shape is omitted. Problem file: " +
namesVector[fileIdx]);
}
w = reader->width();
h = reader->height();
}
currentFileCounters[item.get_any_name()] = fileIdx;
if (!info.dataShape[ov::layout::height_idx(info.layout)]) {
info.dataShape[ov::layout::height_idx(info.layout)] = h;
}
if (!info.dataShape[ov::layout::width_idx(info.layout)]) {
info.dataShape[ov::layout::width_idx(info.layout)] = w;
}
if (std::any_of(info.dataShape.begin(), info.dataShape.end(), [](size_t d) {
return d == 0;
})) {
throw std::logic_error("Not enough information in shape and image to determine tensor shape "
"automatically autmatically. Input: " +
item.get_any_name() + ", File name: " + namesVector[fileIdx - 1]);
}
} else if (info.partialShape.is_static()) {
info.dataShape = info.partialShape.get_shape();
if (data_shapes_map.find(name) != data_shapes_map.end()) {
throw std::logic_error(
"Model's input \"" + name +
"\" is static. Use -shape argument for static inputs instead of -data_shape.");
}
} else if (!data_shapes_map.empty()) {
throw std::logic_error("Can't find model input name \"" + name + "\" in \"-data_shape " +
data_shapes_string + "\" command line parameter");
} else {
throw std::logic_error("-i or -data_shape command line parameter should be set for all inputs in case "
"of model with dynamic shapes.");
}
// Update shape with batch if needed (only in static shape case)
// Update blob shape only not affecting network shape to trigger dynamic batch size case
if (batch_size != 0) {
if (ov::layout::has_batch(info.layout)) {
std::size_t batch_index = ov::layout::batch_idx(info.layout);
if (info.dataShape.at(batch_index) != batch_size) {
if (info.partialShape.is_static()) {
info.partialShape[batch_index] = batch_size;
}
info.dataShape[batch_index] = batch_size;
reshape_required = true;
is_there_at_least_one_batch_dim = true;
}
} else {
slog::warn << "Input '" << item.get_any_name()
<< "' doesn't have batch dimension in layout. -b option will be ignored for this input."
<< slog::endl;
}
}
info_map[name] = info;
}
if (batch_size > 1 && !is_there_at_least_one_batch_dim) {
throw std::runtime_error("-b option is provided in command line, but there's no inputs with batch(B) "
"dimension in input layout, so batch cannot be set. "
"You may specify layout explicitly using -layout option.");
}
// Update scale and mean
std::map<std::string, std::vector<float>> scale_map = parse_scale_or_mean(scale_string, info_map);
std::map<std::string, std::vector<float>> mean_map = parse_scale_or_mean(mean_string, info_map);
for (auto& item : info_map) {
if (item.second.is_image()) {
if (scale_map.count(item.first)) {
item.second.scale = scale_map.at(item.first);
}
if (mean_map.count(item.first)) {
item.second.mean = mean_map.at(item.first);
}
}
}
info_maps.push_back(info_map);
}
return info_maps;
}
std::vector<benchmark_app::InputsInfo> get_inputs_info(const std::string& shape_string,
const std::string& layout_string,
const size_t batch_size,
const std::string& tensors_shape_string,
const std::map<std::string, std::vector<std::string>>& fileNames,
const std::string& scale_string,
const std::string& mean_string,
const std::vector<ov::Output<const ov::Node>>& input_info) {
bool reshape_required = false;
return get_inputs_info(shape_string,
layout_string,
batch_size,
tensors_shape_string,
fileNames,
scale_string,
mean_string,
input_info,
reshape_required);
}
#ifdef USE_OPENCV
void dump_config(const std::string& filename, const std::map<std::string, ov::AnyMap>& config) {
slog::warn << "YAML and XML formats for config file won't be supported soon." << slog::endl;
auto plugin_to_opencv_format = [](const std::string& str) -> std::string {
if (str.find("_") != std::string::npos) {
slog::warn
<< "Device name contains \"_\" and will be changed during loading of configuration due to limitations."
"This configuration file could not be loaded correctly."
<< slog::endl;
}
std::string new_str(str);
auto pos = new_str.find(".");
if (pos != std::string::npos) {
new_str.replace(pos, 1, "_");
}
return new_str;
};
cv::FileStorage fs(filename, cv::FileStorage::WRITE);
if (!fs.isOpened())
throw std::runtime_error("Error: Can't open config file : " + filename);
for (auto device_it = config.begin(); device_it != config.end(); ++device_it) {
fs << plugin_to_opencv_format(device_it->first) << "{:";
std::stringstream strm;
for (auto param_it = device_it->second.begin(); param_it != device_it->second.end(); ++param_it) {
strm << param_it->first;
param_it->second.print(strm);
}
fs << strm.str();
fs << "}";
}
fs.release();
}
void load_config(const std::string& filename, std::map<std::string, ov::AnyMap>& config) {
slog::warn << "YAML and XML formats for config file won't be supported soon." << slog::endl;
auto opencv_to_plugin_format = [](const std::string& str) -> std::string {
std::string new_str(str);
auto pos = new_str.find("_");
if (pos != std::string::npos) {
new_str.replace(pos, 1, ".");
}
return new_str;
};
cv::FileStorage fs(filename, cv::FileStorage::READ);
if (!fs.isOpened())
throw std::runtime_error("Error: Can't load config file : " + filename);
cv::FileNode root = fs.root();
for (auto it = root.begin(); it != root.end(); ++it) {
auto device = *it;
if (!device.isMap()) {
throw std::runtime_error("Error: Can't parse config file : " + filename);
}
for (auto iit = device.begin(); iit != device.end(); ++iit) {
auto item = *iit;
config[opencv_to_plugin_format(device.name())][item.name()] = item.string();
}
}
}
#else
void dump_config(const std::string& filename, const std::map<std::string, ov::AnyMap>& config) {
nlohmann::json jsonConfig;
for (const auto& item : config) {
std::string deviceName = item.first;
std::map<std::string, ov::AnyMap> device_properties;
for (const auto& option : item.second) {
if (option.second.is<ov::AnyMap>()) {
// hw device properties
device_properties[option.first] = option.second.as<ov::AnyMap>();
} else {
// primary property
std::stringstream strm;
option.second.print(strm);
auto property_string = strm.str();
jsonConfig[deviceName][option.first] = property_string;
}
if (!device_properties.empty()) {
for (auto& item : device_properties) {
auto hw_device_name = item.first;
for (auto& property : item.second) {
jsonConfig[deviceName]["DEVICE_PROPERTIES"][hw_device_name][property.first] =
property.second.as<std::string>();
}
}
}
}
}
std::ofstream ofs(filename);
if (!ofs.is_open()) {
throw std::runtime_error("Can't load config file \"" + filename + "\".");
}
ofs << jsonConfig;
}
void load_config(const std::string& filename, std::map<std::string, ov::AnyMap>& config) {
std::ifstream ifs(filename);
if (!ifs.is_open()) {
throw std::runtime_error("Can't load config file \"" + filename + "\".");
}
nlohmann::json jsonConfig;
try {
ifs >> jsonConfig;
} catch (const std::exception& e) {
throw std::runtime_error("Can't parse config file \"" + filename + "\".\n" + e.what());
}
for (auto item = jsonConfig.cbegin(), end = jsonConfig.cend(); item != end; ++item) {
const std::string& deviceName = item.key();
const auto& itemValue = item.value();
for (auto option = itemValue.cbegin(), itemValueEnd = itemValue.cend(); option != itemValueEnd; ++option) {
if (option.key() != "DEVICE_PROPERTIES") {
config[deviceName][option.key()] = option.value().get<std::string>();
continue;
}
const auto& optionValue = option.value();
for (auto hw_properties = optionValue.cbegin(), optionValueEnd = optionValue.cend();
hw_properties != optionValueEnd;
++hw_properties) {
const std::string& hw_device_name = hw_properties.key();
std::map<std::string, ov::Any> hw_device_properties;
const auto& hw_propertiesValue = hw_properties.value();
for (auto property = hw_propertiesValue.cbegin(), hw_propertiesEnd = hw_propertiesValue.cend();
property != hw_propertiesEnd;
++property)
hw_device_properties[property.key()] = property.value().get<std::string>();
config[deviceName][hw_device_name] = hw_device_properties;
}
}
}
}
#endif
#ifdef USE_OPENCV
const std::vector<std::string> supported_image_extensions =
{"bmp", "dib", "jpeg", "jpg", "jpe", "jp2", "png", "pbm", "pgm", "ppm", "sr", "ras", "tiff", "tif"};
#else
const std::vector<std::string> supported_image_extensions = {"bmp"};
#endif
const std::vector<std::string> supported_binary_extensions = {"bin"};
std::string get_extension(const std::string& name) {
auto extensionPosition = name.rfind('.', name.size());
return extensionPosition == std::string::npos ? "" : name.substr(extensionPosition + 1, name.size() - 1);
};
bool is_binary_file(const std::string& filePath) {
auto extension = get_extension(filePath);
std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
return std::find(supported_binary_extensions.begin(), supported_binary_extensions.end(), extension) !=
supported_binary_extensions.end();
}
bool is_image_file(const std::string& filePath) {
auto extension = get_extension(filePath);
std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
return std::find(supported_binary_extensions.begin(), supported_binary_extensions.end(), extension) !=
supported_binary_extensions.end();
}
bool contains_binaries(const std::vector<std::string>& filePaths) {
std::vector<std::string> filtered;
for (auto& filePath : filePaths) {
auto extension = get_extension(filePath);
std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
if (std::find(supported_binary_extensions.begin(), supported_binary_extensions.end(), extension) !=
supported_binary_extensions.end()) {
return true;
}
}
return false;
}
std::vector<std::string> filter_files_by_extensions(const std::vector<std::string>& filePaths,
const std::vector<std::string>& extensions) {
std::vector<std::string> filtered;
for (auto& filePath : filePaths) {
auto extension = get_extension(filePath);
std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
if (std::find(extensions.begin(), extensions.end(), extension) != extensions.end()) {
filtered.push_back(filePath);
}
}
return filtered;
}
std::string parameter_name_to_tensor_name(const std::string& name,
const std::vector<ov::Output<const ov::Node>>& inputs_info,
const std::vector<ov::Output<const ov::Node>>& outputs_info) {
if (std::any_of(inputs_info.begin(), inputs_info.end(), [name](const ov::Output<const ov::Node>& port) {
try {
return port.get_names().count(name) > 0;
} catch (const ov::Exception&) {
return false; // Some ports might have no names - so this is workaround
}
})) {
return name;
} else if (std::any_of(outputs_info.begin(), outputs_info.end(), [name](const ov::Output<const ov::Node>& port) {
try {
return port.get_names().count(name) > 0;
} catch (const ov::Exception&) {
return false; // Some ports might have no names - so this is workaround
}
})) {
return name;
} else {
for (const auto& port : inputs_info) {
if (name == port.get_node()->get_friendly_name()) {
return port.get_any_name();
}
}
for (const auto& port : outputs_info) {
if (name == port.get_node()->get_input_node_ptr(0)->get_friendly_name()) {
return port.get_any_name();
}
}
}
throw std::runtime_error("Provided I/O name \"" + name +
"\" is not found neither in tensor names nor in nodes names.");
}