Skip to content

Commit

Permalink
support cpu only in psroi_pooling_layer.cpp
Browse files Browse the repository at this point in the history
1.add cpu forward implementation as YuwenXiong/py-R-FCN#28 (comment)
2.add cpu backward implementation by stealing code from its GPU implement
  • Loading branch information
ZhuLingfeng1993 committed Dec 27, 2018
1 parent 56ac3a2 commit 9d406c4
Showing 1 changed file with 181 additions and 3 deletions.
184 changes: 181 additions & 3 deletions src/caffe/layers/psroi_pooling_layer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,84 @@ using std::floor;
using std::ceil;

namespace caffe {
template <typename Dtype>
void PSROIPoolingForward_cpu(
const int count,
const Dtype* bottom_data,
const Dtype spatial_scale,
const int channels,
const int height, const int width,
const int pooled_height, const int pooled_width,
const Dtype* bottom_rois,
const int output_dim,
const int group_size,
Dtype* top_data,
int* mapping_channel) {
const Dtype* bottom_data_bak = bottom_data;
const Dtype* bottom_rois_bak = bottom_rois;

for(int index = 0; index < count; ++index) {
bottom_data = bottom_data_bak;
bottom_rois = bottom_rois_bak;
// The output is in order (n, ctop, ph, pw)
int pw = index % pooled_width;
int ph = (index / pooled_width) % pooled_height;
int ctop = (index / pooled_width / pooled_height) % output_dim;
int n = index / pooled_width / pooled_height / output_dim;

// [start, end) interval for spatial sampling
bottom_rois += n * 5;
int roi_batch_ind = bottom_rois[0];
Dtype roi_start_w =
static_cast<Dtype>(round(bottom_rois[1])) * spatial_scale;
Dtype roi_start_h =
static_cast<Dtype>(round(bottom_rois[2])) * spatial_scale;
Dtype roi_end_w =
static_cast<Dtype>(round(bottom_rois[3]) + 1.) * spatial_scale;
Dtype roi_end_h =
static_cast<Dtype>(round(bottom_rois[4]) + 1.) * spatial_scale;

// Force too small ROIs to be 1x1
Dtype roi_width = max(roi_end_w - roi_start_w, static_cast<Dtype>(0.1f));// avoid 0
Dtype roi_height = max(roi_end_h - roi_start_h, static_cast<Dtype>(0.1f));

// Compute w and h at bottom
Dtype bin_size_h = roi_height / static_cast<Dtype>(pooled_height);
Dtype bin_size_w = roi_width / static_cast<Dtype>(pooled_width);

int hstart = floor(static_cast<Dtype>(ph) * bin_size_h
+ roi_start_h);
int wstart = floor(static_cast<Dtype>(pw)* bin_size_w
+ roi_start_w);
int hend = ceil(static_cast<Dtype>(ph + 1) * bin_size_h
+ roi_start_h);
int wend = ceil(static_cast<Dtype>(pw + 1) * bin_size_w
+ roi_start_w);
// Add roi offsets and clip to input boundaries
hstart = min(max(hstart, 0), height);
hend = min(max(hend, 0), height);
wstart = min(max(wstart, 0), width);
wend = min(max(wend, 0), width);
bool is_empty = (hend <= hstart) || (wend <= wstart);

int gw = pw;
int gh = ph;
int c = (ctop*group_size + gh)*group_size + gw;

bottom_data += (roi_batch_ind * channels + c) * height * width;
Dtype out_sum = 0;
for (int h = hstart; h < hend; ++h) {
for (int w = wstart; w < wend; ++w) {
int bottom_index = h*width + w;
out_sum += bottom_data[bottom_index];
}
}
Dtype bin_area = (hend - hstart)*(wend - wstart);
top_data[index] = is_empty? 0. : out_sum/bin_area;
mapping_channel[index] = c;
}
}

template <typename Dtype>
void PSROIPoolingLayer<Dtype>::LayerSetUp(const vector<Blob<Dtype>*>& bottom,
const vector<Blob<Dtype>*>& top) {
Expand Down Expand Up @@ -52,14 +130,114 @@ namespace caffe {

template <typename Dtype>
void PSROIPoolingLayer<Dtype>::Forward_cpu(const vector<Blob<Dtype>*>& bottom,
const vector<Blob<Dtype>*>& top) {
NOT_IMPLEMENTED;
const vector<Blob<Dtype>*>& top){
const Dtype* bottom_data = bottom[0]->cpu_data();
const Dtype* bottom_rois = bottom[1]->cpu_data();
Dtype* top_data = top[0]->mutable_cpu_data();
int* mapping_channel_ptr = mapping_channel_.mutable_cpu_data();
int count = top[0]->count();
caffe_set(count, Dtype(0), top_data);
caffe_set(count, -1, mapping_channel_ptr);
PSROIPoolingForward_cpu(count, bottom_data, spatial_scale_,
channels_, height_, width_, pooled_height_,
pooled_width_, bottom_rois, output_dim_, group_size_,
top_data, mapping_channel_ptr);
}

template <typename Dtype>
void PSROIPoolingBackward(
const int count,
const Dtype* top_diff,
const int* mapping_channel,
const int num_rois,
const Dtype spatial_scale,
const int channels,
const int height, const int width,
const int pooled_height, const int pooled_width,
const int output_dim,
Dtype* bottom_diff,
const Dtype* bottom_rois) {
const Dtype* top_diff_bak = top_diff;
const Dtype* bottom_rois_bak = bottom_rois;

for(int index = 0; index < count; ++index) {
top_diff = top_diff_bak;
bottom_rois = bottom_rois_bak;
// The output is in order (n, ctop, ph, pw)
int pw = index % pooled_width;
int ph = (index / pooled_width) % pooled_height;
int n = index / pooled_width / pooled_height / output_dim;

// [start, end) interval for spatial sampling
bottom_rois += n * 5;
int roi_batch_ind = bottom_rois[0];
Dtype roi_start_w =
static_cast<Dtype>(round(bottom_rois[1])) * spatial_scale;
Dtype roi_start_h =
static_cast<Dtype>(round(bottom_rois[2])) * spatial_scale;
Dtype roi_end_w =
static_cast<Dtype>(round(bottom_rois[3]) + 1.) * spatial_scale;
Dtype roi_end_h =
static_cast<Dtype>(round(bottom_rois[4]) + 1.) * spatial_scale;

// Force too small ROIs to be 1x1
Dtype roi_width = max(roi_end_w - roi_start_w, static_cast<Dtype>(0.1f)); // avoid 0
Dtype roi_height = max(roi_end_h - roi_start_h, static_cast<Dtype>(0.1f));

// Compute w and h at bottom
Dtype bin_size_h = roi_height / static_cast<Dtype>(pooled_height);
Dtype bin_size_w = roi_width / static_cast<Dtype>(pooled_width);

int hstart = floor(static_cast<Dtype>(ph)* bin_size_h
+ roi_start_h);
int wstart = floor(static_cast<Dtype>(pw)* bin_size_w
+ roi_start_w);
int hend = ceil(static_cast<Dtype>(ph + 1) * bin_size_h
+ roi_start_h);
int wend = ceil(static_cast<Dtype>(pw + 1) * bin_size_w
+ roi_start_w);
// Add roi offsets and clip to input boundaries
hstart = min(max(hstart, 0), height);
hend = min(max(hend, 0), height);
wstart = min(max(wstart, 0), width);
wend = min(max(wend, 0), width);
bool is_empty = (hend <= hstart) || (wend <= wstart);

// Compute c at bottom
int c = mapping_channel[index];
Dtype* offset_bottom_diff = bottom_diff +
(roi_batch_ind * channels + c) * height * width;
Dtype bin_area = (hend - hstart)*(wend - wstart);
Dtype diff_val = is_empty ? 0. : top_diff[index] / bin_area;
for (int h = hstart; h < hend; ++h) {
for (int w = wstart; w < wend; ++w) {
int bottom_index = h*width + w;
//caffe_gpu_atomic_add(diff_val, offset_bottom_diff + bottom_index);
offset_bottom_diff[bottom_index] += diff_val;
}
}
}
}

template <typename Dtype>
void PSROIPoolingLayer<Dtype>::Backward_cpu(const vector<Blob<Dtype>*>& top,
const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom) {
NOT_IMPLEMENTED;
if (!propagate_down[0]) {
return;
}

const Dtype* bottom_rois = bottom[1]->cpu_data();
const Dtype* top_diff = top[0]->cpu_diff();
Dtype* bottom_diff = bottom[0]->mutable_cpu_diff();
const int bottom_count = bottom[0]->count();
const int* mapping_channel_ptr = mapping_channel_.cpu_data();
caffe_set(bottom[1]->count(), Dtype(0), bottom[1]->mutable_cpu_diff());
caffe_set(bottom_count, Dtype(0), bottom_diff);
const int count = top[0]->count();
PSROIPoolingBackward(count, top_diff, mapping_channel_ptr,
top[0]->num(), spatial_scale_, channels_, height_, width_,
pooled_height_, pooled_width_, output_dim_, bottom_diff,
bottom_rois);
}
#ifdef CPU_ONLY
STUB_GPU(PSROIPoolingLayer);
Expand Down

0 comments on commit 9d406c4

Please sign in to comment.