1 // Copyright (C) 2018-2019 Intel Corporation
2 // SPDX-License-Identifier: Apache-2.0
5 #include "ext_list.hpp"
6 #include "ext_base.hpp"
13 namespace InferenceEngine {
14 namespace Extensions {
17 class PriorBoxImpl: public ExtLayerBase {
19 explicit PriorBoxImpl(const CNNLayer *layer) {
21 if (layer->insData.size() != 2 || layer->outData.empty())
22 THROW_IE_EXCEPTION << "Incorrect number of input/output edges!";
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!";
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);
38 _aspect_ratios.push_back(1.0f);
40 const std::vector<float> aspect_ratios = layer->GetParamAsFloats("aspect_ratio", {});
42 for (float aspect_ratio : aspect_ratios) {
45 if (std::fabs(aspect_ratio) < std::numeric_limits<float>::epsilon()) {
46 THROW_IE_EXCEPTION << "aspect_ratio param can't be equal to zero";
49 for (float _aspect_ratio : _aspect_ratios) {
50 if (fabs(aspect_ratio - _aspect_ratio) < 1e-6) {
60 _aspect_ratios.push_back(aspect_ratio);
63 _aspect_ratios.push_back(1.0f / aspect_ratio);
67 if (_scale_all_sizes) {
68 _num_priors = static_cast<int>(_aspect_ratios.size() * _min_sizes.size());
70 _num_priors = static_cast<int>(_aspect_ratios.size() + _min_sizes.size() - 1);
73 for (auto it = _max_sizes.begin(); it != _max_sizes.end(); it++) {
77 const std::vector<float> variance = layer->GetParamAsFloats("variance", {});
79 if (variance.size() == 1 || variance.size() == 4) {
80 for (float i : variance) {
82 THROW_IE_EXCEPTION << "Variance must be > 0.";
85 _variance.push_back(i);
87 } else if (variance.empty()) {
88 _variance.push_back(0.1f);
90 THROW_IE_EXCEPTION << "Wrong number of variance values. Not less than 1 and more than 4 variance values.";
93 addConfig(layer, {{ConfLayout::ANY, true}, {ConfLayout::ANY, true}}, {{ConfLayout::PLN, true}});
94 } catch (InferenceEngine::details::InferenceEngineException &ex) {
99 StatusCode init(LayerConfig& config, ResponseDesc *resp) noexcept override {
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()) {
107 std::string errorMsg = "Incorrect number of input or output edges!";
108 errorMsg.copy(resp->msg, sizeof(resp->msg) - 1);
110 return GENERAL_ERROR;
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];
122 const int OH = dstMemPtr->getTensorDesc().getDims()[2];
123 const int OW = (dstMemPtr->getTensorDesc().getDims().size() == 3) ? 1 : dstMemPtr->getTensorDesc().getDims()[3];
129 step_x = static_cast<float>(IW) / W;
130 step_y = static_cast<float>(IH) / H;
136 float* dst_data = dstMemPtr->buffer();
138 int dim = H * W * _num_priors * 4;
140 float center_x = 0.0f;
141 float center_y = 0.0f;
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++) {
150 center_x = (w + 0.5f) * step_x;
151 center_y = (h + 0.5f) * step_y;
153 center_x = (_offset + w) * _step;
154 center_y = (_offset + h) * _step;
157 box_width = _min_sizes[msIdx];
158 box_height = _min_sizes[msIdx];
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;
165 if (_max_sizes.size() > msIdx) {
166 box_width = box_height = sqrt(_min_sizes[msIdx] * _max_sizes[msIdx]);
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;
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) {
181 box_width = _min_sizes[sIdx] * sqrt(ar);
182 box_height = _min_sizes[sIdx] / sqrt(ar);
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;
195 for (int d = 0; d < dim; ++d) {
196 dst_data[d] = (std::min)((std::max)(dst_data[d], 0.0f), 1.0f);
200 int channel_size = OH * OW;
202 dst_data += channel_size;
205 if (_variance.size() == 1) {
206 for (int i = 0; i < channel_size; i++) {
207 dst_data[i] = _variance[0];
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];
227 std::vector<float> _min_sizes;
228 std::vector<float> _max_sizes;
231 bool _scale_all_sizes = true;
233 std::vector<float> _aspect_ratios;
234 std::vector<float> _variance;
239 REG_FACTORY_FOR(ImplFactory<PriorBoxImpl>, PriorBox);
242 } // namespace Extensions
243 } // namespace InferenceEngine