Created
September 20, 2019 19:10
-
-
Save wolterlw/6f1ebc49230506f8e9ce5facc5251d4f to your computer and use it in GitHub Desktop.
c++ program to get anchors needed for hand detection
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
parameter JSON | |
{ | |
"num_layers": 5, | |
"min_scale": 0.1171875, | |
"max_scale": 0.75, | |
"input_size_height": 256, | |
"input_size_width": 256, | |
"anchor_offset_x": 0.5, | |
"anchor_offset_y": 0.5, | |
"strides": [8,16,32,32,32], | |
"aspect_ratios": [1.0], | |
"fixed_anchor_size": true, | |
"interpolated_scale_aspect_ratio": 1.0, | |
"reduce_boxes_in_lowest_layer": false | |
} | |
*/ | |
#include <vector> | |
#include <cmath> | |
#include <iostream> | |
#include <json.hpp> | |
#include <fstream> | |
//see github.com/nlohmann/json | |
using json=nlohmann::json; | |
class Anchor{ | |
public: | |
float x_center = 1; | |
float y_center = 2; | |
float h = 3; | |
float w = 4; | |
void set_x_center(float val){ | |
x_center = val; | |
} | |
void set_y_center(float val){ | |
y_center = val; | |
} | |
void set_w(float val){ | |
w = val; | |
} | |
void set_h(float val){ | |
h = val; | |
} | |
void print(){ | |
std::cout << x_center << "," << y_center << "," <<w << "," << h << std::endl; | |
} | |
}; | |
float CalculateScale(float min_scale, float max_scale, int stride_index, | |
int num_strides) { | |
return min_scale + | |
(max_scale - min_scale) * 1.0 * stride_index / (num_strides - 1.0f); | |
} | |
std::vector<Anchor> GenerateAnchors(json options){ | |
std::vector<Anchor> anchors; | |
anchors.reserve(2000); | |
int layer_id = 0; | |
while (layer_id < options["strides"].size()) { | |
std::vector<float> anchor_height; | |
std::vector<float> anchor_width; | |
std::vector<float> aspect_ratios; | |
std::vector<float> scales; | |
// For same strides, we merge the anchors in the same order. | |
int last_same_stride_layer = layer_id; | |
while (last_same_stride_layer < (int) options["strides"].size() && | |
(int) options["strides"][last_same_stride_layer] == | |
(int) options["strides"][layer_id]) { | |
const float scale = | |
CalculateScale((float) options["min_scale"], (float) options["max_scale"], | |
last_same_stride_layer, (int) options["strides"].size()); | |
if (last_same_stride_layer == 0 && | |
options["reduce_boxes_in_lowest_layer"]) { | |
// For first layer, it can be specified to use predefined anchors. | |
aspect_ratios.push_back(1.0); | |
aspect_ratios.push_back(2.0); | |
aspect_ratios.push_back(0.5); | |
scales.push_back(0.1); | |
scales.push_back(scale); | |
scales.push_back(scale); | |
} else { | |
for (int aspect_ratio_id = 0; | |
aspect_ratio_id < options["aspect_ratios"].size(); | |
++aspect_ratio_id) { | |
aspect_ratios.push_back(options["aspect_ratios"][aspect_ratio_id]); | |
scales.push_back(scale); | |
} | |
if (options["interpolated_scale_aspect_ratio"] > 0.0) { | |
const float scale_next = | |
last_same_stride_layer == options["strides"].size() - 1 | |
? 1.0f | |
: CalculateScale(options["min_scale"], options["max_scale"], | |
last_same_stride_layer + 1, | |
options["strides"].size()); | |
scales.push_back(std::sqrt(scale * scale_next)); | |
aspect_ratios.push_back(options["interpolated_scale_aspect_ratio"]); | |
} | |
} | |
last_same_stride_layer++; | |
} | |
for (int i = 0; i < aspect_ratios.size(); ++i) { | |
const float ratio_sqrts = std::sqrt(aspect_ratios[i]); | |
anchor_height.push_back(scales[i] / ratio_sqrts); | |
anchor_width.push_back(scales[i] * ratio_sqrts); | |
} | |
int feature_map_height = 0; | |
int feature_map_width = 0; | |
if (false) { //(options["feature_map_height"].size()) { | |
feature_map_height = (float)options["feature_map_height"][layer_id]; | |
feature_map_width = (float)options["feature_map_width"][layer_id]; | |
} else { | |
const int stride = (int)options["strides"][layer_id]; | |
feature_map_height = | |
std::ceil(1.0f * (float)options["input_size_height"] / stride); | |
feature_map_width = std::ceil(1.0f * (float)options["input_size_width"] / stride); | |
} | |
for (int y = 0; y < feature_map_height; ++y) { | |
for (int x = 0; x < feature_map_width; ++x) { | |
for (int anchor_id = 0; anchor_id < anchor_height.size(); ++anchor_id) { | |
// TODO: Support specifying anchor_offset_x, anchor_offset_y. | |
const float x_center = | |
(x + (float)options["anchor_offset_x"]) * 1.0f / feature_map_width; | |
const float y_center = | |
(y + (float)options["anchor_offset_y"]) * 1.0f / feature_map_height; | |
Anchor new_anchor; | |
new_anchor.set_x_center(x_center); | |
new_anchor.set_y_center(y_center); | |
if ((bool)options["fixed_anchor_size"]) { | |
new_anchor.set_w(1.0f); | |
new_anchor.set_h(1.0f); | |
} else { | |
new_anchor.set_w(anchor_width[anchor_id]); | |
new_anchor.set_h(anchor_height[anchor_id]); | |
} | |
anchors.push_back(new_anchor); | |
} | |
} | |
} | |
layer_id = last_same_stride_layer; | |
} | |
return anchors; | |
} | |
int main(int argc, char const *argv[]) | |
{ | |
std::ifstream inp_file("./options.json"); | |
json options; | |
inp_file >> options; | |
std::vector<Anchor> res = GenerateAnchors(options); | |
for (auto value: res) | |
value.print(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment