d7cd57a65821f8e22d441e71f099327707a1a85c
[platform/upstream/dldt.git] / inference-engine / thirdparty / clDNN / src / proposal.cpp
1 /*
2 // Copyright (c) 2017-2019 Intel Corporation
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 */
16
17 #include "proposal_inst.h"
18 #include "primitive_type_base.h"
19 #include "json_object.h"
20
21 #include <cmath>
22 #include <string>
23 #include <vector>
24
25 namespace cldnn {
26
27 static void generate_anchors(unsigned base_size,
28                              const std::vector<float>& ratios,
29                              const std::vector<float>& scales,
30                              std::vector<proposal_inst::anchor>& anchors,
31                              float coordinates_offset,
32                              bool shift_anchors,
33                              bool round_ratios);
34
35 primitive_type_id proposal_type_id() {
36     static primitive_type_base<proposal> instance;
37     return &instance;
38 }
39
40 layout proposal_inst::calc_output_layout(proposal_node const& node) {
41     assert(static_cast<bool>(node.get_primitive()->output_data_type) == false &&
42            "Output data type forcing is not supported for proposal_node!");
43     auto desc = node.get_primitive();
44     layout input_layout = node.get_dependency(cls_scores_index).get_output_layout();
45
46     return layout(input_layout.data_type,
47                   format::bfyx,
48                   {input_layout.size.batch[0] * desc->post_nms_topn, CLDNN_ROI_VECTOR_SIZE, 1, 1});
49 }
50
51 static inline std::string stringify_vector(std::vector<float> v) {
52     std::stringstream s;
53
54     s << "{ ";
55
56     for (size_t i = 0; i < v.size(); ++i) {
57         s << v.at(i);
58         if (i + 1 < v.size())
59             s << ", ";
60     }
61
62     s << " }";
63
64     return s.str();
65 }
66
67 // TODO: rename to?
68 static std::string stringify_port(const program_node& p) {
69     std::stringstream res;
70     auto node_info = p.desc_to_json();
71     node_info->dump(res);
72
73     return res.str();
74 }
75
76 std::string proposal_inst::to_string(proposal_node const& node) {
77     auto desc = node.get_primitive();
78     auto node_info = node.desc_to_json();
79     auto scales_parm = desc->scales;
80
81     std::stringstream primitive_description;
82
83     auto swap_xy = desc->swap_xy ? "true" : "false";
84     auto initial_clip = desc->initial_clip ? "true" : "false";
85     auto round_ratios = desc->round_ratios ? "true" : "false";
86     auto shift_anchors = desc->shift_anchors ? "true" : "false";
87     auto clip_before_nms = desc->clip_before_nms ? "true" : "false";
88     auto clip_after_nms = desc->clip_after_nms ? "true" : "false";
89     auto for_deformable = desc->clip_after_nms ? "true" : "false";
90
91     json_composite proposal_info;
92     proposal_info.add("cls score", stringify_port(node.cls_score()));
93     proposal_info.add("box pred", stringify_port(node.bbox_pred()));
94     proposal_info.add("image info", stringify_port(node.image_info()));
95
96     json_composite params;
97     params.add("max proposals", desc->max_proposals);
98     params.add("iou threshold", desc->iou_threshold);
99     params.add("base bbox size", desc->base_bbox_size);
100     params.add("min bbox size", desc->min_bbox_size);
101     params.add("pre nms topn", desc->pre_nms_topn);
102     params.add("post nms topn", desc->post_nms_topn);
103     params.add("ratios", stringify_vector(desc->ratios));
104     params.add("ratios", stringify_vector(desc->ratios));
105     params.add("coordinates offset", desc->coordinates_offset);
106     params.add("box coordinate scale", desc->box_coordinate_scale);
107     params.add("box size scale", desc->box_size_scale);
108     params.add("swap xy", swap_xy);
109     params.add("initial clip", initial_clip);
110     params.add("round ratios", round_ratios);
111     params.add("shift anchors", shift_anchors);
112     params.add("clip_before_nms", clip_before_nms);
113     params.add("clip_after_nms", clip_after_nms);
114     params.add("for_deformable", for_deformable);
115     proposal_info.add("params", params);
116
117     node_info->add("proposal info", proposal_info);
118     node_info->dump(primitive_description);
119
120     return primitive_description.str();
121 }
122
123 proposal_inst::typed_primitive_inst(network_impl& network, proposal_node const& node) : parent(network, node) {
124     generate_anchors(argument.base_bbox_size,
125                      argument.ratios,
126                      argument.scales,
127                      _anchors,
128                      argument.coordinates_offset,
129                      argument.shift_anchors,
130                      argument.round_ratios);
131 }
132
133 static void generate_anchors(unsigned int base_size,
134                              const std::vector<float>& ratios,
135                              const std::vector<float>& scales,             // input
136                              std::vector<proposal_inst::anchor>& anchors,  // output
137                              float coordinates_offset,
138                              bool shift_anchors,
139                              bool round_ratios) {
140     const float base_area = static_cast<float>(base_size * base_size);
141     const float half_base_size = base_size * 0.5f;
142     const float center = 0.5f * (base_size - coordinates_offset);
143
144     anchors.clear();
145     // enumerate all transformed boxes
146     for (size_t ratio = 0; ratio < ratios.size(); ++ratio) {
147         // transformed width & height for given ratio factors
148         float ratio_w;
149         float ratio_h;
150         if (round_ratios) {
151             ratio_w = std::roundf(std::sqrt(base_area / ratios[ratio]));
152             ratio_h = std::roundf(ratio_w * ratios[ratio]);
153         } else {
154             ratio_w = std::sqrt(base_area / ratios[ratio]);
155             ratio_h = ratio_w * ratios[ratio];
156         }
157
158         for (size_t scale = 0; scale < scales.size(); ++scale) {
159             proposal_inst::anchor anchor;
160             // transformed width & height for given scale factors
161             const float scale_w = 0.5f * (ratio_w * scales[scale] - coordinates_offset);
162             const float scale_h = 0.5f * (ratio_h * scales[scale] - coordinates_offset);
163
164             // (x1, y1, x2, y2) for transformed box
165             anchor.start_x = center - scale_w;
166             anchor.start_y = center - scale_h;
167             anchor.end_x = center + scale_w;
168             anchor.end_y = center + scale_h;
169
170             if (shift_anchors) {
171                 anchor.start_x -= half_base_size;
172                 anchor.start_y -= half_base_size;
173                 anchor.end_x -= half_base_size;
174                 anchor.end_y -= half_base_size;
175             }
176
177             anchors.push_back(anchor);
178         }
179     }
180 }
181 }  // namespace cldnn