1 // Copyright (C) 2018-2019 Intel Corporation
2 // SPDX-License-Identifier: Apache-2.0
9 #include <inference_engine.hpp>
10 #include <ext_list.hpp>
11 #include <samples/ocv_common.hpp>
13 #include "shape_infer_extension.hpp"
15 using namespace InferenceEngine;
17 int main(int argc, char* argv[]) {
19 // ------------------------------ Parsing and validation of input args ---------------------------------
21 std::cout << "Usage : ./hello_shape_infer_ssd <path_to_model> <path_to_image> <device> <batch>"
25 const std::string input_model{argv[1]};
26 const std::string input_image_path{argv[2]};
27 const std::string device_name{argv[3]};
28 const size_t batch_size{std::stoul(argv[4])};
29 // -----------------------------------------------------------------------------------------------------
31 // --------------------------- 1. Load Plugin for inference engine -------------------------------------
32 InferencePlugin plugin = PluginDispatcher().getPluginByDevice(device_name);
33 IExtensionPtr cpuExtension, inPlaceExtension;
34 if (device_name == "CPU") {
35 cpuExtension = std::make_shared<Extensions::Cpu::CpuExtensions>();
36 inPlaceExtension = std::make_shared<InPlaceExtension>();
37 plugin.AddExtension(cpuExtension);
38 // register sample's custom kernel (CustomReLU)
39 plugin.AddExtension(inPlaceExtension);
41 // -----------------------------------------------------------------------------------------------------
43 // --------------------------- 2. Read IR Generated by ModelOptimizer (.xml and .bin files) ------------
44 CNNNetReader network_reader;
45 network_reader.ReadNetwork(input_model);
46 network_reader.ReadWeights(input_model.substr(0, input_model.size() - 4) + ".bin");
47 CNNNetwork network = network_reader.getNetwork();
49 OutputsDataMap outputs_info(network.getOutputsInfo());
50 InputsDataMap inputs_info(network.getInputsInfo());
51 if (inputs_info.size() != 1 && outputs_info.size() != 1)
52 throw std::logic_error("Sample supports clean SSD network with one input and one output");
54 // --------------------------- Resize network to match image sizes and given batch----------------------
55 if (device_name == "CPU") {
56 network.AddExtension(cpuExtension);
57 // register sample's custom shape inference (CustomReLU)
58 network.AddExtension(inPlaceExtension);
60 auto input_shapes = network.getInputShapes();
61 std::string input_name;
62 SizeVector input_shape;
63 std::tie(input_name, input_shape) = *input_shapes.begin();
64 cv::Mat image = cv::imread(input_image_path);
65 input_shape[0] = batch_size;
66 input_shape[2] = image.rows;
67 input_shape[3] = image.cols;
68 input_shapes[input_name] = input_shape;
69 std::cout << "Resizing network to the image size = [" << image.rows << "x" << image.cols << "] "
70 << "with batch = " << batch_size << std::endl;
71 network.reshape(input_shapes);
72 // -----------------------------------------------------------------------------------------------------
74 // --------------------------- 3. Configure input & output ---------------------------------------------
75 // --------------------------- Prepare input blobs -----------------------------------------------------
76 InputInfo::Ptr input_info;
77 std::tie(input_name, input_info) = *inputs_info.begin();
78 input_info->setLayout(Layout::NCHW);
79 input_info->setPrecision(Precision::U8);
80 // --------------------------- Prepare output blobs ----------------------------------------------------
82 std::string output_name;
83 std::tie(output_name, output_info) = *outputs_info.begin();
84 if (output_info->creatorLayer.lock()->type != "DetectionOutput")
85 throw std::logic_error("Can't find a DetectionOutput layer in the topology");
86 const SizeVector output_shape = output_info->getTensorDesc().getDims();
87 const int max_proposal_count = output_shape[2];
88 const int object_size = output_shape[3];
89 if (object_size != 7) {
90 throw std::logic_error("Output item should have 7 as a last dimension");
92 if (output_shape.size() != 4) {
93 throw std::logic_error("Incorrect output dimensions for SSD model");
95 if (output_info == nullptr) {
96 THROW_IE_EXCEPTION << "[SAMPLES] internal error - output information is empty";
99 output_info->setPrecision(Precision::FP32);
101 auto dumpVec = [](const SizeVector& vec) -> std::string {
102 if (vec.empty()) return "[]";
103 std::stringstream oss;
104 oss << "[" << vec[0];
105 for (size_t i = 1; i < vec.size(); i++) oss << "," << vec[i];
109 std::cout << "Resulting input shape = " << dumpVec(input_shape) << std::endl;
110 std::cout << "Resulting output shape = " << dumpVec(output_shape) << std::endl;
111 // -----------------------------------------------------------------------------------------------------
113 // --------------------------- 4. Loading model to the plugin ------------------------------------------
114 ExecutableNetwork executable_network = plugin.LoadNetwork(network, {});
115 // -----------------------------------------------------------------------------------------------------
117 // --------------------------- 5. Create infer request -------------------------------------------------
118 InferRequest infer_request = executable_network.CreateInferRequest();
119 // -----------------------------------------------------------------------------------------------------
121 // --------------------------- 6. Prepare input --------------------------------------------------------
122 Blob::Ptr input = infer_request.GetBlob(input_name);
123 for (size_t b = 0; b < batch_size; b++) {
124 matU8ToBlob<uint8_t>(image, input, b);
126 // -----------------------------------------------------------------------------------------------------
128 // --------------------------- 7. Do inference --------------------------------------------------------
129 infer_request.Infer();
130 // -----------------------------------------------------------------------------------------------------
132 // --------------------------- 8. Process output ------------------------------------------------------
133 Blob::Ptr output = infer_request.GetBlob(output_name);
134 const float* detection = output->buffer().as<PrecisionTrait<Precision::FP32>::value_type*>();
136 /* Each detection has image_id that denotes processed image */
137 for (int cur_proposal = 0; cur_proposal < max_proposal_count; cur_proposal++) {
138 float image_id = detection[cur_proposal * object_size + 0];
139 float label = detection[cur_proposal * object_size + 1];
140 float confidence = detection[cur_proposal * object_size + 2];
141 /* CPU and GPU plugins have difference in DetectionOutput layer, so we need both checks */
142 if (image_id < 0 || confidence == 0) {
146 float xmin = detection[cur_proposal * object_size + 3] * image.cols;
147 float ymin = detection[cur_proposal * object_size + 4] * image.rows;
148 float xmax = detection[cur_proposal * object_size + 5] * image.cols;
149 float ymax = detection[cur_proposal * object_size + 6] * image.rows;
151 if (confidence > 0.5) {
152 /** Drawing only objects with >50% probability **/
153 std::ostringstream conf;
154 conf << ":" << std::fixed << std::setprecision(3) << confidence;
155 cv::rectangle(image, cv::Point2f(xmin, ymin), cv::Point2f(xmax, ymax), cv::Scalar(0, 0, 255));
156 std::cout << "[" << cur_proposal << "," << label << "] element, prob = " << confidence <<
157 ", bbox = (" << xmin << "," << ymin << ")-(" << xmax << "," << ymax << ")" << ", batch id = "
158 << image_id << std::endl;
162 cv::imwrite("hello_shape_infer_ssd_output.jpg", image);
163 std::cout << "The resulting image was saved in the file: hello_shape_infer_ssd_output.jpg" << std::endl;
164 // -----------------------------------------------------------------------------------------------------
165 } catch (const std::exception& ex) {
166 std::cerr << ex.what() << std::endl;