Skip to content

Commit 1dcddfa

Browse files
committed
Merge branch 'development' of https://github.com/foss-for-synopsys-dwc-arc-processors/synopsys-caffe into development
add transform_mode: pytorch_half_pixel to ResizeBilinear layer
2 parents 60524b7 + f652a27 commit 1dcddfa

File tree

3 files changed

+209
-0
lines changed

3 files changed

+209
-0
lines changed

FEATURES.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ gru_layer
2727
hard_sigmoid_layer
2828
hard_swish_layer
2929
hard_tanh_layer
30+
icnet_subgraph_layer
3031
log_softmax_layer
3132
lp_normalization_layer
3233
luong_attention_layer
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
#ifndef CAFFE_ICNET_SUBGRAPH_LAYER_HPP_
2+
#define CAFFE_ICNET_SUBGRAPH_LAYER_HPP_
3+
4+
#include <vector>
5+
6+
#include "caffe/blob.hpp"
7+
#include "caffe/layer.hpp"
8+
#include "caffe/proto/caffe.pb.h"
9+
10+
namespace caffe {
11+
12+
/**
13+
* @brief Merge the AVE Pooling, Interp and Eltwise sum for host_fixed usage in ICNet model.
14+
*
15+
* NOTE: does not implement Backwards operation.
16+
*/
17+
template <typename Dtype>
18+
class ICNetSubgraphLayer : public Layer<Dtype> {
19+
public:
20+
explicit ICNetSubgraphLayer(const LayerParameter& param)
21+
: Layer<Dtype>(param) {}
22+
virtual void LayerSetUp(const vector<Blob<Dtype>*>& bottom,
23+
const vector<Blob<Dtype>*>& top);
24+
virtual void Reshape(const vector<Blob<Dtype>*>& bottom,
25+
const vector<Blob<Dtype>*>& top);
26+
27+
virtual inline const char* type() const { return "ICNetSubgraph"; }
28+
virtual inline int ExactNumBottomBlobs() const { return 1; }
29+
virtual inline int ExactNumTopBlobs() const { return 1; }
30+
31+
32+
protected:
33+
virtual void Forward_cpu(const vector<Blob<Dtype>*>& bottom,
34+
const vector<Blob<Dtype>*>& top);
35+
virtual void Backward_cpu(const vector<Blob<Dtype>*>& top,
36+
const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom){
37+
NOT_IMPLEMENTED;
38+
}
39+
40+
int pad_h_ = 0;
41+
int pad_w_ = 0;
42+
int num_;
43+
int channels_;
44+
int height_, width_;
45+
46+
vector<int> kernel_h_;
47+
vector<int> kernel_w_;
48+
vector<int> stride_h_;
49+
vector<int> stride_w_;
50+
vector<int> pooled_height_;
51+
vector<int> pooled_width_;
52+
int pool_branches_ = 4;
53+
54+
Blob<Dtype> pooling_;
55+
Blob<Dtype> interp_;
56+
};
57+
58+
} // namespace caffe
59+
60+
#endif // CAFFE_ICNET_SUBGRAPH_LAYER_HPP_
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
#include <algorithm>
2+
#include <cfloat>
3+
#include <vector>
4+
5+
#include "caffe/layers/icnet_subgraph_layer.hpp"
6+
#include "caffe/util/math_functions.hpp"
7+
#include "caffe/util/interp.hpp"
8+
9+
namespace caffe {
10+
11+
using std::min;
12+
using std::max;
13+
14+
template <typename Dtype>
15+
void ICNetSubgraphLayer<Dtype>::LayerSetUp(const vector<Blob<Dtype>*>& bottom,
16+
const vector<Blob<Dtype>*>& top) {
17+
// the parameter is taken from icnet_cityscapes.prototxt layer conv5_3 to conv5_3_sum subgraph
18+
kernel_h_.push_back(33);
19+
kernel_h_.push_back(17);
20+
kernel_h_.push_back(13);
21+
kernel_h_.push_back(8);
22+
23+
kernel_w_.push_back(65);
24+
kernel_w_.push_back(33);
25+
kernel_w_.push_back(25);
26+
kernel_w_.push_back(15);
27+
28+
stride_h_.push_back(33);
29+
stride_h_.push_back(16);
30+
stride_h_.push_back(10);
31+
stride_h_.push_back(5);
32+
33+
stride_w_.push_back(65);
34+
stride_w_.push_back(32);
35+
stride_w_.push_back(20);
36+
stride_w_.push_back(10);
37+
}
38+
39+
template <typename Dtype>
40+
void ICNetSubgraphLayer<Dtype>::Reshape(const vector<Blob<Dtype>*>& bottom,
41+
const vector<Blob<Dtype>*>& top) {
42+
CHECK_EQ(4, bottom[0]->num_axes()) << "Input must have 4 axes, "
43+
<< "corresponding to (num, channels, height, width)";
44+
num_ = bottom[0]->num();
45+
channels_ = bottom[0]->channels();
46+
height_ = bottom[0]->height();
47+
width_ = bottom[0]->width();
48+
49+
for (int i = 0; i < pool_branches_; i++)
50+
{
51+
pooled_height_.push_back(static_cast<int>(ceil(static_cast<float>(
52+
height_ + 2 * pad_h_ - kernel_h_[i]) / stride_h_[i])) + 1);
53+
pooled_width_.push_back(static_cast<int>(ceil(static_cast<float>(
54+
width_ + 2 * pad_w_ - kernel_w_[i]) / stride_w_[i])) + 1);
55+
}
56+
57+
top[0]->ReshapeLike(*bottom[0]);
58+
59+
// allocate for the largest size needed
60+
pooling_.Reshape(num_, channels_, pooled_height_[pool_branches_-1],
61+
pooled_width_[pool_branches_-1]);
62+
63+
interp_.ReshapeLike(*bottom[0]);
64+
65+
}
66+
67+
template <typename Dtype>
68+
void ICNetSubgraphLayer<Dtype>::Forward_cpu(const vector<Blob<Dtype>*>& bottom,
69+
const vector<Blob<Dtype>*>& top) {
70+
const Dtype* bottom_data = bottom[0]->cpu_data();
71+
Dtype* top_data = top[0]->mutable_cpu_data();
72+
const int top_count = top[0]->count();
73+
74+
// 1 branch data directly copied to final accumulator
75+
for (int i = 0; i < top_count; ++i) {
76+
top_data[i] = bottom_data[i];
77+
}
78+
79+
int pad_top = 0, pad_bottom = 0, pad_left = 0, pad_right = 0;
80+
81+
// The main loop
82+
for (int i = 0; i < pool_branches_; i++)
83+
{
84+
bottom_data = bottom[0]->cpu_data(); // reset the pointer
85+
// do the ave pooling
86+
Dtype* pool_data = pooling_.mutable_cpu_data();
87+
int pool_count = pooling_.count();
88+
for (int j = 0; j < pool_count; ++j) {
89+
pool_data[j] = 0; // clear the field
90+
}
91+
92+
for (int n = 0; n < num_; ++n) {
93+
for (int c = 0; c < channels_; ++c) {
94+
for (int ph = 0; ph < pooled_height_[i]; ++ph) {
95+
for (int pw = 0; pw < pooled_width_[i]; ++pw) {
96+
int hstart = ph * stride_h_[i] - pad_top;
97+
int wstart = pw * stride_w_[i] - pad_left;
98+
int hend = min(hstart + kernel_h_[i], height_ + pad_bottom);
99+
int wend = min(wstart + kernel_w_[i], width_ + pad_right);
100+
int pool_size = (hend - hstart) * (wend - wstart);
101+
hstart = max(hstart, 0);
102+
wstart = max(wstart, 0);
103+
hend = min(hend, height_);
104+
wend = min(wend, width_);
105+
for (int h = hstart; h < hend; ++h) {
106+
for (int w = wstart; w < wend; ++w) {
107+
pool_data[ph * pooled_width_[i] + pw] +=
108+
bottom_data[h * width_ + w];
109+
}
110+
}
111+
pool_data[ph * pooled_width_[i] + pw] /= pool_size;
112+
}
113+
}
114+
// compute offset
115+
bottom_data += bottom[0]->offset(0, 1);
116+
pool_data += pooled_height_[i] * pooled_width_[i];
117+
}
118+
}
119+
120+
// do the interp computation
121+
int pad_beg_ = 0;
122+
int pad_end_ = 0;
123+
int height_in_ = pooled_height_[i];
124+
int width_in_ = pooled_width_[i];
125+
int height_in_eff_ = height_in_ + pad_beg_ + pad_end_;
126+
int width_in_eff_ = width_in_ + pad_beg_ + pad_end_;
127+
128+
Dtype* interp_data = interp_.mutable_cpu_data();
129+
int interp_count = interp_.count();
130+
for (int j = 0; j < interp_count; ++j) {
131+
interp_data[j] = 0; // clear the field
132+
}
133+
134+
caffe_cpu_interp2<Dtype,false>(num_ * channels_,
135+
pooling_.cpu_data(), - pad_beg_, - pad_beg_, height_in_eff_, width_in_eff_, height_in_, width_in_,
136+
interp_.mutable_cpu_data(), 0, 0, height_, width_, height_, width_);
137+
138+
// accumulate
139+
for (int j = 0; j < top_count; ++j) {
140+
top_data[j] += interp_data[j];
141+
}
142+
}
143+
}
144+
145+
INSTANTIATE_CLASS(ICNetSubgraphLayer);
146+
REGISTER_LAYER_CLASS(ICNetSubgraph);
147+
148+
} // namespace caffe

0 commit comments

Comments
 (0)