Publishing 2019 R1 content
[platform/upstream/dldt.git] / inference-engine / src / extension / ext_priorbox.cpp
1 // Copyright (C) 2018-2019 Intel Corporation
2 // SPDX-License-Identifier: Apache-2.0
3 //
4
5 #include "ext_list.hpp"
6 #include "ext_base.hpp"
7
8 #include <vector>
9 #include <string>
10 #include <cmath>
11 #include <limits>
12
13 namespace InferenceEngine {
14 namespace Extensions {
15 namespace Cpu {
16
17 class PriorBoxImpl: public ExtLayerBase {
18 public:
19     explicit PriorBoxImpl(const CNNLayer *layer) {
20         try {
21             if (layer->insData.size() != 2 || layer->outData.empty())
22                 THROW_IE_EXCEPTION << "Incorrect number of input/output edges!";
23
24             if (layer->insData[0].lock()->dims.size() != 4 ||
25                     layer->insData[1].lock()->dims.size() != 4)
26                 THROW_IE_EXCEPTION << "PriorBox supports only 4D blobs!";
27
28             _offset = layer->GetParamAsFloat("offset");
29             _step = layer->GetParamAsFloat("step", 0);
30             _min_sizes = layer->GetParamAsFloats("min_size", {});
31             _max_sizes = layer->GetParamAsFloats("max_size", {});
32             _flip = layer->GetParamAsBool("flip", false);
33             _clip = layer->GetParamAsBool("clip", false);
34             _scale_all_sizes = layer->GetParamAsBool("scale_all_sizes", true);
35
36             bool exist;
37
38             _aspect_ratios.push_back(1.0f);
39
40             const std::vector<float> aspect_ratios = layer->GetParamAsFloats("aspect_ratio", {});
41
42             for (float aspect_ratio : aspect_ratios) {
43                 exist = false;
44
45                 if (std::fabs(aspect_ratio) < std::numeric_limits<float>::epsilon()) {
46                     THROW_IE_EXCEPTION << "aspect_ratio param can't be equal to zero";
47                 }
48
49                 for (float _aspect_ratio : _aspect_ratios) {
50                     if (fabs(aspect_ratio - _aspect_ratio) < 1e-6) {
51                         exist = true;
52                         break;
53                     }
54                 }
55
56                 if (exist) {
57                     continue;
58                 }
59
60                 _aspect_ratios.push_back(aspect_ratio);
61
62                 if (_flip) {
63                     _aspect_ratios.push_back(1.0f / aspect_ratio);
64                 }
65             }
66
67             if (_scale_all_sizes) {
68                 _num_priors = static_cast<int>(_aspect_ratios.size() * _min_sizes.size());
69             } else {
70                 _num_priors = static_cast<int>(_aspect_ratios.size() + _min_sizes.size() - 1);
71             }
72
73             for (auto it = _max_sizes.begin(); it != _max_sizes.end(); it++) {
74                 _num_priors += 1;
75             }
76
77             const std::vector<float> variance = layer->GetParamAsFloats("variance", {});
78
79             if (variance.size() == 1 || variance.size() == 4) {
80                 for (float i : variance) {
81                     if (i < 0) {
82                         THROW_IE_EXCEPTION << "Variance must be > 0.";
83                     }
84
85                     _variance.push_back(i);
86                 }
87             } else if (variance.empty()) {
88                 _variance.push_back(0.1f);
89             } else {
90                 THROW_IE_EXCEPTION << "Wrong number of variance values. Not less than 1 and more than 4 variance values.";
91             }
92
93             addConfig(layer, {{ConfLayout::ANY, true}, {ConfLayout::ANY, true}}, {{ConfLayout::PLN, true}});
94         } catch (InferenceEngine::details::InferenceEngineException &ex) {
95             errorMsg = ex.what();
96         }
97     }
98
99     StatusCode init(LayerConfig& config, ResponseDesc *resp) noexcept override {
100         return OK;
101     }
102
103     StatusCode execute(std::vector<Blob::Ptr>& inputs, std::vector<Blob::Ptr>& outputs,
104                        ResponseDesc *resp) noexcept override {
105         if (inputs.size() != 2 || outputs.empty()) {
106             if (resp) {
107                 std::string errorMsg = "Incorrect number of input or output edges!";
108                 errorMsg.copy(resp->msg, sizeof(resp->msg) - 1);
109             }
110             return GENERAL_ERROR;
111         }
112         auto& dataMemPtr = inputs[0];
113         auto& imageMemPtr = inputs[1];
114         auto& dstMemPtr = outputs[0];
115         SizeVector _data_dims = dataMemPtr->getTensorDesc().getDims();
116         SizeVector _image_dims = imageMemPtr->getTensorDesc().getDims();
117         const int W = _data_dims[3];
118         const int H = _data_dims[2];
119         const int IW = _image_dims[3];
120         const int IH = _image_dims[2];
121
122         const int OH = dstMemPtr->getTensorDesc().getDims()[2];
123         const int OW = (dstMemPtr->getTensorDesc().getDims().size() == 3) ? 1 : dstMemPtr->getTensorDesc().getDims()[3];
124
125         float step_x = 0.0f;
126         float step_y = 0.0f;
127
128         if (_step == 0) {
129             step_x = static_cast<float>(IW) / W;
130             step_y = static_cast<float>(IH) / H;
131         } else {
132             step_x = _step;
133             step_y = _step;
134         }
135
136         float* dst_data = dstMemPtr->buffer();
137
138         int dim = H * W * _num_priors * 4;
139         int idx = 0;
140         float center_x = 0.0f;
141         float center_y = 0.0f;
142
143         float box_width;
144         float box_height;
145
146         for (int h = 0; h < H; ++h) {
147             for (int w = 0; w < W; ++w) {
148                 for (size_t msIdx = 0; msIdx < _min_sizes.size(); msIdx++) {
149                     if (_step == 0) {
150                         center_x = (w + 0.5f) * step_x;
151                         center_y = (h + 0.5f) * step_y;
152                     } else {
153                         center_x = (_offset + w) * _step;
154                         center_y = (_offset + h) * _step;
155                     }
156
157                     box_width = _min_sizes[msIdx];
158                     box_height = _min_sizes[msIdx];
159
160                     dst_data[idx++] = (center_x - box_width / 2.0f) / IW;
161                     dst_data[idx++] = (center_y - box_height / 2.0f) / IH;
162                     dst_data[idx++] = (center_x + box_width / 2.0f) / IW;
163                     dst_data[idx++] = (center_y + box_height / 2.0f) / IH;
164
165                     if (_max_sizes.size() > msIdx) {
166                         box_width = box_height = sqrt(_min_sizes[msIdx] * _max_sizes[msIdx]);
167
168                         dst_data[idx++] = (center_x - box_width / 2.0f) / IW;
169                         dst_data[idx++] = (center_y - box_height / 2.0f) / IH;
170                         dst_data[idx++] = (center_x + box_width / 2.0f) / IW;
171                         dst_data[idx++] = (center_y + box_height / 2.0f) / IH;
172                     }
173
174                     if (_scale_all_sizes || (!_scale_all_sizes && (msIdx == _min_sizes.size() - 1))) {
175                         size_t sIdx = _scale_all_sizes ? msIdx : 0;
176                         for (float ar : _aspect_ratios) {
177                             if (fabs(ar - 1.0f) < 1e-6) {
178                                 continue;
179                             }
180
181                             box_width = _min_sizes[sIdx] * sqrt(ar);
182                             box_height = _min_sizes[sIdx] / sqrt(ar);
183
184                             dst_data[idx++] = (center_x - box_width / 2.0f) / IW;
185                             dst_data[idx++] = (center_y - box_height / 2.0f) / IH;
186                             dst_data[idx++] = (center_x + box_width / 2.0f) / IW;
187                             dst_data[idx++] = (center_y + box_height / 2.0f) / IH;
188                         }
189                     }
190                 }
191             }
192         }
193
194         if (_clip) {
195             for (int d = 0; d < dim; ++d) {
196                 dst_data[d] = (std::min)((std::max)(dst_data[d], 0.0f), 1.0f);
197             }
198         }
199
200         int channel_size = OH * OW;
201
202         dst_data += channel_size;
203
204         int count = 0;
205         if (_variance.size() == 1) {
206             for (int i = 0; i < channel_size; i++) {
207                 dst_data[i] = _variance[0];
208             }
209         } else {
210             for (int h = 0; h < H; ++h) {
211                 for (int w = 0; w < W; ++w) {
212                     for (int i = 0; i < _num_priors; ++i) {
213                         for (int j = 0; j < 4; ++j) {
214                             dst_data[count] = _variance[j];
215                             ++count;
216                         }
217                     }
218                 }
219             }
220         }
221         return OK;
222     }
223
224 private:
225     float _offset = 0;
226     float _step = 0;
227     std::vector<float> _min_sizes;
228     std::vector<float> _max_sizes;
229     bool _flip = false;
230     bool _clip = false;
231     bool _scale_all_sizes = true;
232
233     std::vector<float> _aspect_ratios;
234     std::vector<float> _variance;
235
236     int _num_priors = 0;
237 };
238
239 REG_FACTORY_FOR(ImplFactory<PriorBoxImpl>, PriorBox);
240
241 }  // namespace Cpu
242 }  // namespace Extensions
243 }  // namespace InferenceEngine