Files
openvino/samples/cpp/hello_reshape_ssd/main.cpp
Ilya Lavrenov a883dc0b85 DOCS: ported changes from 2022.1 release branch (#11206)
* Extensibility guide with FE extensions and remove OV_FRAMEWORK_MAP from docs

* Rework of Extensibility Intro, adopted examples to missing OPENVINO_FRAMEWORK_MAP

* Removed OPENVINO_FRAMEWORK_MAP reference

* Frontend extension detailed documentation

* Fixed distributed snippets

* Fixed snippet inclusion in FE extension document and chapter headers

* Fixed wrong name in a snippet reference

* Fixed test for template extension due to changed number of loaded extensions

* Update docs/Extensibility_UG/frontend_extensions.md

Co-authored-by: Ivan Tikhonov <ivan.tikhonov@intel.com>

* Minor fixes in extension snippets

* Small grammar fix

Co-authored-by: Ivan Tikhonov <ivan.tikhonov@intel.com>

Co-authored-by: Ivan Tikhonov <ivan.tikhonov@intel.com>

* DOCS: transition banner (#10973)

* transition banner

* minor fix

* update transition banner

* updates

* update custom.js

* updates

* updates

* Documentation fixes (#11044)

* Benchmark app usage

* Fixed link to the devices

* More fixes

* Update docs/OV_Runtime_UG/multi_device.md

Co-authored-by: Sergey Lyubimtsev <sergey.lyubimtsev@intel.com>

* Removed several hardcoded links

Co-authored-by: Sergey Lyubimtsev <sergey.lyubimtsev@intel.com>

* Updated documentation for compile_tool (#11049)

* Added deployment guide (#11060)

* Added deployment guide

* Added local distribution

* Updates

* Fixed more indentations

* Removed obsolete code snippets (#11061)

* Removed obsolete code snippets

* NCC style

* Fixed NCC for BA

* Add a troubleshooting issue for PRC installation (#11074)

* updates

* adding gna to linux

* add missing reference

* update

* Update docs/install_guides/installing-model-dev-tools.md

Co-authored-by: Sergey Lyubimtsev <sergey.lyubimtsev@intel.com>

* Update docs/install_guides/installing-model-dev-tools.md

Co-authored-by: Sergey Lyubimtsev <sergey.lyubimtsev@intel.com>

* Update docs/install_guides/installing-model-dev-tools.md

Co-authored-by: Sergey Lyubimtsev <sergey.lyubimtsev@intel.com>

* Update docs/install_guides/installing-model-dev-tools.md

Co-authored-by: Sergey Lyubimtsev <sergey.lyubimtsev@intel.com>

* Update docs/install_guides/installing-model-dev-tools.md

Co-authored-by: Sergey Lyubimtsev <sergey.lyubimtsev@intel.com>

* update

* minor updates

* add gna item to yum and apt

* add gna to get started page

* update reference formatting

* merge commit

* add a troubleshooting issue

* update

* update

* fix CVS-71846

Co-authored-by: Sergey Lyubimtsev <sergey.lyubimtsev@intel.com>

* DOCS: fixed hardcoded links  (#11100)

* Fixes

* Use links

* applying reviewers comments to the Opt Guide (#11093)

* applying reviewrs comments

* fixed refs, more structuring (bold, bullets, etc)

* refactoring tput/latency sections

* next iteration (mostly latency), also brushed the auto-batching and other sections

* updates sync/async images

* common opts brushed

* WIP tput redesigned

* minor brushing of common and auto-batching

* Tput fully refactored

* fixed doc name in the link

* moved int8 perf counters to the right section

* fixed links

* fixed broken quotes

* fixed more links

* add ref to the internals to the TOC

* Added a note on the batch size

Co-authored-by: Andrey Zaytsev <andrey.zaytsev@intel.com>

* [80085] New images for docs (#11114)

* change doc structure

* fix manager tools

* fix manager tools 3 step

* fix manager tools 3 step

* new img

* new img for OV Runtime

* fix steps

* steps

* fix intendents

* change list

* fix space

* fix space

* code snippets fix

* change display

* Benchmarks 2022 1 (#11130)

* Minor fixes

* Updates for 2022.1

* Edits according to the review

* Edits according to review comments

* Edits according to review comments

* Edits according to review comments

* Fixed table

* Edits according to review comments

* Removed config for Intel® Core™ i7-11850HE

* Removed forward-tacotron-duration-prediction-241 graph

* Added resnet-18-pytorch

* Add info about Docker images in Deployment guide (#11136)

* Renamed user guides (#11137)

* fix screenshot (#11140)

* More conservative recommendations on dynamic shapes usage in docs (#11161)

* More conservative recommendations about using dynamic shapes

* Duplicated statement from C++ part to Python part of reshape doc (no semantical changes)

* Update ShapeInference.md (#11168)

* Benchmarks 2022 1 updates (#11180)

* Updated graphs

* Quick fix for TODO in Dynamic Shapes article

* Anchor link fixes

* Fixed DM config (#11199)

* DOCS: doxy sphinxtabs (#11027)

* initial implementation of doxy sphinxtabs

* fixes

* fixes

* fixes

* fixes

* fixes

* WA for ignored visibility attribute

* Fixes

Co-authored-by: Sergey Lyalin <sergey.lyalin@intel.com>
Co-authored-by: Ivan Tikhonov <ivan.tikhonov@intel.com>
Co-authored-by: Nikolay Tyukaev <nikolay.tyukaev@intel.com>
Co-authored-by: Sergey Lyubimtsev <sergey.lyubimtsev@intel.com>
Co-authored-by: Yuan Xu <yuan1.xu@intel.com>
Co-authored-by: Maxim Shevtsov <maxim.y.shevtsov@intel.com>
Co-authored-by: Andrey Zaytsev <andrey.zaytsev@intel.com>
Co-authored-by: Tatiana Savina <tatiana.savina@intel.com>
Co-authored-by: Ilya Naumov <ilya.naumov@intel.com>
Co-authored-by: Evgenya Stepyreva <evgenya.stepyreva@intel.com>
2022-03-24 22:27:29 +03:00

211 lines
8.9 KiB
C++

// Copyright (C) 2018-2022 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include <memory>
#include <string>
#include <vector>
// clang-format off
#include "openvino/openvino.hpp"
#include "ngraph/ngraph.hpp"
#include "format_reader_ptr.h"
#include "samples/args_helper.hpp"
#include "samples/common.hpp"
#include "samples/slog.hpp"
// clang-format on
// thickness of a line (in pixels) to be used for bounding boxes
constexpr int BBOX_THICKNESS = 2;
using namespace ov::preprocess;
int main(int argc, char* argv[]) {
try {
// -------- Get OpenVINO runtime version -----------------------------
slog::info << ov::get_openvino_version() << slog::endl;
// --------------------------- Parsing and validation of input arguments
if (argc != 4) {
std::cout << "Usage : " << argv[0] << " <path_to_model> <path_to_image> <device>" << std::endl;
return EXIT_FAILURE;
}
const std::string model_path{argv[1]};
const std::string image_path{argv[2]};
const std::string device_name{argv[3]};
// -------------------------------------------------------------------
// Step 1. Initialize OpenVINO Runtime core
ov::Core core;
// -------------------------------------------------------------------
// Step 2. Read a model
slog::info << "Loading model files: " << model_path << slog::endl;
std::shared_ptr<ov::Model> model = core.read_model(model_path);
printInputAndOutputsInfo(*model);
// Step 3. Validate model inputs and outputs
OPENVINO_ASSERT(model->inputs().size() == 1, "Sample supports models with 1 input only");
OPENVINO_ASSERT(model->outputs().size() == 1, "Sample supports models with 1 output only");
// SSD has an additional post-processing DetectionOutput layer that simplifies output filtering,
// try to find it.
ov::NodeVector ops = model->get_ops();
auto it = std::find_if(ops.begin(), ops.end(), [](std::shared_ptr<ov::Node> node) {
return node->get_type_info() == ngraph::op::DetectionOutput::get_type_info_static();
});
if (it == ops.end()) {
throw std::logic_error("model does not contain DetectionOutput layer");
}
// -------------------------------------------------------------------
// Step 4. Read input image
// Read input image without resize
FormatReader::ReaderPtr reader(image_path.c_str());
if (reader.get() == nullptr) {
std::cout << "Image " + image_path + " cannot be read!" << std::endl;
return 1;
}
std::shared_ptr<unsigned char> image_data = reader->getData();
size_t image_channels = 3;
size_t image_width = reader->width();
size_t image_height = reader->height();
// -------------------------------------------------------------------
// Step 5. Reshape model to image size and batch size
// assume model layout NCHW
const ov::Layout model_layout{"NCHW"};
ov::Shape tensor_shape = model->input().get_shape();
size_t batch_size = 1;
tensor_shape[ov::layout::batch_idx(model_layout)] = batch_size;
tensor_shape[ov::layout::channels_idx(model_layout)] = image_channels;
tensor_shape[ov::layout::height_idx(model_layout)] = image_height;
tensor_shape[ov::layout::width_idx(model_layout)] = image_width;
std::cout << "Reshape network to the image size = [" << image_height << "x" << image_width << "] " << std::endl;
model->reshape({{model->input().get_any_name(), tensor_shape}});
printInputAndOutputsInfo(*model);
// -------------------------------------------------------------------
// Step 6. Configure model preprocessing
const ov::Layout tensor_layout{"NHWC"};
// clang-format off
ov::preprocess::PrePostProcessor ppp = ov::preprocess::PrePostProcessor(model);
// 1) input() with no args assumes a model has a single input
ov::preprocess::InputInfo& input_info = ppp.input();
// 2) Set input tensor information:
// - precision of tensor is supposed to be 'u8'
// - layout of data is 'NHWC'
input_info.tensor().
set_element_type(ov::element::u8).
set_layout(tensor_layout);
// 3) Adding explicit preprocessing steps:
// - convert u8 to f32
// - convert layout to 'NCHW' (from 'NHWC' specified above at tensor layout)
ppp.input().preprocess().
convert_element_type(ov::element::f32).
convert_layout("NCHW");
// 4) Here we suppose model has 'NCHW' layout for input
input_info.model().set_layout("NCHW");
// 5) output () with no args assumes a model has a single output
ov::preprocess::OutputInfo& output_info = ppp.output();
// 6) declare output element type as FP32
output_info.tensor().set_element_type(ov::element::f32);
// 7) Apply preprocessing modifing the original 'model'
model = ppp.build();
// clang-format on
// -------------------------------------------------------------------
// Step 7. Loading a model to the device
ov::CompiledModel compiled_model = core.compile_model(model, device_name);
// -------------------------------------------------------------------
// Step 8. Create an infer request
ov::InferRequest infer_request = compiled_model.create_infer_request();
// Step 9. Fill model with input data
ov::Tensor input_tensor = infer_request.get_input_tensor();
// copy NHWC data from image to tensor with batch
unsigned char* image_data_ptr = image_data.get();
unsigned char* tensor_data_ptr = input_tensor.data<unsigned char>();
size_t image_size = image_width * image_height * image_channels;
for (size_t i = 0; i < image_size; i++) {
tensor_data_ptr[i] = image_data_ptr[i];
}
// -------------------------------------------------------------------
// Step 10. Do inference synchronously
infer_request.infer();
// Step 11. Get output data from the model
ov::Tensor output_tensor = infer_request.get_output_tensor();
ov::Shape output_shape = model->output().get_shape();
const size_t ssd_object_count = output_shape[2];
const size_t ssd_object_size = output_shape[3];
const float* detections = output_tensor.data<const float>();
// -------------------------------------------------------------------
std::vector<int> boxes;
std::vector<int> classes;
// Step 12. Parse SSD output
for (size_t object = 0; object < ssd_object_count; object++) {
int image_id = static_cast<int>(detections[object * ssd_object_size + 0]);
if (image_id < 0) {
break;
}
// detection, has the format: [image_id, label, conf, x_min, y_min, x_max, y_max]
int label = static_cast<int>(detections[object * ssd_object_size + 1]);
float confidence = detections[object * ssd_object_size + 2];
int xmin = static_cast<int>(detections[object * ssd_object_size + 3] * image_width);
int ymin = static_cast<int>(detections[object * ssd_object_size + 4] * image_height);
int xmax = static_cast<int>(detections[object * ssd_object_size + 5] * image_width);
int ymax = static_cast<int>(detections[object * ssd_object_size + 6] * image_height);
if (confidence > 0.5f) {
// collect only objects with >50% probability
classes.push_back(label);
boxes.push_back(xmin);
boxes.push_back(ymin);
boxes.push_back(xmax - xmin);
boxes.push_back(ymax - ymin);
std::cout << "[" << object << "," << label << "] element, prob = " << confidence << ", (" << xmin
<< "," << ymin << ")-(" << xmax << "," << ymax << ")" << std::endl;
}
}
// draw bounding boxes on the image
addRectangles(image_data.get(), image_height, image_width, boxes, classes, BBOX_THICKNESS);
const std::string image_name = "hello_reshape_ssd_output.bmp";
if (writeOutputBmp(image_name, image_data.get(), image_height, image_width)) {
std::cout << "The resulting image was saved in the file: " + image_name << std::endl;
} else {
throw std::logic_error(std::string("Can't create a file: ") + image_name);
}
} catch (const std::exception& ex) {
std::cerr << ex.what() << std::endl;
return EXIT_FAILURE;
}
std::cout << std::endl
<< "This sample is an API example, for any performance measurements "
"please use the dedicated benchmark_app tool"
<< std::endl;
return EXIT_SUCCESS;
}