Caffe2 - C++ API
A deep learning, cross platform ML framework
space_batch_op.h
1 #ifndef CAFFE2_OPERATORS_SPACE_BATCH_OP_H_
2 #define CAFFE2_OPERATORS_SPACE_BATCH_OP_H_
3 
4 #include "caffe2/core/context.h"
5 #include "caffe2/core/logging.h"
6 #include "caffe2/core/operator.h"
7 #include "caffe2/utils/math.h"
8 
9 namespace caffe2 {
10 
11 template <typename Context>
12 void spaceToBatch(
13  const Tensor<Context>& input,
14  int pad_t,
15  int pad_l,
16  int block_size,
17  Tensor<Context>* output,
18  Context* /*context*/) {
19  CAFFE_ENFORCE(input.ndim() == 4);
20  CAFFE_ENFORCE(output->ndim() == 4);
21 
22  const int output_batch = output->dim32(0);
23  const int output_depth = output->dim32(1);
24  const int output_height = output->dim32(2);
25  const int output_width = output->dim32(3);
26 
27  const int input_batch = input.dim32(0);
28  const int input_depth = input.dim32(1);
29  const int input_height = input.dim32(2);
30  const int input_width = input.dim32(3);
31 
32  for (int out_b = 0; out_b < output_batch; ++out_b) {
33  const int in_b = out_b % input_batch;
34  const int offset_w = (out_b / input_batch) % block_size;
35  const int offset_h = (out_b / input_batch) / block_size;
36  for (int d = 0; d < input_depth; ++d) {
37  for (int out_h = 0; out_h < output_height; ++out_h) {
38  const int in_h = out_h * block_size + offset_h - pad_t;
39  for (int out_w = 0; out_w < output_width; ++out_w) {
40  const int in_w = out_w * block_size + offset_w - pad_l;
41  const auto output_offset =
42  ((out_b * output_depth + d) * output_height + out_h) *
43  output_width +
44  out_w;
45  const auto input_offset =
46  ((in_b * input_depth + d) * input_height + in_h) * input_width +
47  in_w;
48  if (in_h >= 0 && in_w >= 0 && in_h < input_height &&
49  in_w < input_width) {
50  output->template mutable_data<float>()[output_offset] =
51  input.template data<float>()[input_offset];
52  } else {
53  output->template mutable_data<float>()[output_offset] = 0.0;
54  }
55  }
56  }
57  }
58  }
59 }
60 
61 template <typename Context>
62 void batchToSpace(
63  const Tensor<Context>& input,
64  int pad_t,
65  int pad_l,
66  int block_size,
67  Tensor<Context>* output,
68  Context* /*context*/) {
69  CAFFE_ENFORCE(input.ndim() == 4);
70  CAFFE_ENFORCE(output->ndim() == 4);
71 
72  const int output_batch = output->dim32(0);
73  const int output_depth = output->dim32(1);
74  const int output_height = output->dim32(2);
75  const int output_width = output->dim32(3);
76 
77  const int input_batch = input.dim32(0);
78  const int input_depth = input.dim32(1);
79  const int input_height = input.dim32(2);
80  const int input_width = input.dim32(3);
81 
82  CAFFE_ENFORCE(input_depth == output_depth);
83  for (int in_b = 0; in_b < input_batch; ++in_b) {
84  const int out_b = in_b % output_batch;
85  const int offset_w = (in_b / output_batch) % block_size;
86  const int offset_h = (in_b / output_batch) / block_size;
87  for (int d = 0; d < input_depth; ++d) {
88  for (int in_h = 0; in_h < input_height; ++in_h) {
89  const int out_h = in_h * block_size + offset_h - pad_t;
90  for (int in_w = 0; in_w < input_width; ++in_w) {
91  const int out_w = in_w * block_size + offset_w - pad_l;
92  if (out_h >= 0 && out_w >= 0 && out_h < output_height &&
93  out_w < output_width) {
94  const auto output_offset =
95  ((out_b * output_depth + d) * output_height + out_h) *
96  output_width +
97  out_w;
98  const auto input_offset =
99  ((in_b * input_depth + d) * input_height + in_h) * input_width +
100  in_w;
101  output->template mutable_data<float>()[output_offset] =
102  input.template data<float>()[input_offset];
103  }
104  }
105  }
106  }
107  }
108 }
109 
110 template <typename Context>
111 class SpaceBatchOpBase : public Operator<Context> {
112  public:
113  USE_OPERATOR_CONTEXT_FUNCTIONS;
114  SpaceBatchOpBase(const OperatorDef& operator_def, Workspace* ws)
115  : Operator<Context>(operator_def, ws),
116  pad_(OperatorBase::GetSingleArgument<int>("pad", 0)),
117  pad_t_(OperatorBase::GetSingleArgument<int>("pad_t", pad_)),
118  pad_l_(OperatorBase::GetSingleArgument<int>("pad", pad_)),
119  pad_b_(OperatorBase::GetSingleArgument<int>("pad", pad_)),
120  pad_r_(OperatorBase::GetSingleArgument<int>("pad", pad_)),
121  block_size_(OperatorBase::GetSingleArgument<int>("block_size", 2)),
122  order_(StringToStorageOrder(
123  OperatorBase::GetSingleArgument<string>("order", "NCHW"))) {
124  CAFFE_ENFORCE(order_ == StorageOrder::NCHW);
125  }
126 
127  protected:
128  int pad_;
129  int pad_t_;
130  int pad_l_;
131  int pad_b_;
132  int pad_r_;
133  int block_size_;
134  StorageOrder order_;
135 };
136 
137 template <typename Context>
138 class SpaceToBatchOp final : public SpaceBatchOpBase<Context> {
139  public:
140  USE_OPERATOR_CONTEXT_FUNCTIONS;
142 
143  bool RunOnDevice() override {
144  const auto& input = Input(0);
145  auto* output = Output(0);
146  const int batch = input.dim32(0);
147  const int depth = input.dim32(1);
148  const int height = this->pad_b_ + this->pad_t_ + input.dim32(2);
149  const int width = this->pad_l_ + this->pad_r_ + input.dim32(3);
150  CAFFE_ENFORCE(
151  height % this->block_size_ == 0,
152  "Height: ",
153  height,
154  ", block size: ",
155  this->block_size_);
156  CAFFE_ENFORCE(width % this->block_size_ == 0);
157 
158  const int output_batch = batch * this->block_size_ * this->block_size_;
159  const int output_height = height / this->block_size_;
160  const int output_width = width / this->block_size_;
161  Output(0)->Resize(output_batch, depth, output_height, output_width);
162 
163  spaceToBatch<Context>(
164  input,
165  this->pad_t_,
166  this->pad_l_,
167  this->block_size_,
168  output,
169  &context_);
170 
171  return true;
172  }
173 };
174 
175 template <typename Context>
176 class BatchToSpaceOp final : public SpaceBatchOpBase<Context> {
177  public:
178  USE_OPERATOR_CONTEXT_FUNCTIONS;
180 
181  bool RunOnDevice() override {
182  const auto& input = Input(0);
183  auto* output = Output(0);
184  const int batch = input.dim32(0);
185  const int depth = input.dim32(1);
186  const int height = input.dim32(2);
187  const int width = input.dim32(3);
188 
189  const int output_batch = batch / this->block_size_ / this->block_size_;
190  const int output_height =
191  height * this->block_size_ - this->pad_b_ - this->pad_t_;
192  const int output_width =
193  width * this->block_size_ - this->pad_l_ - this->pad_r_;
194  Output(0)->Resize(output_batch, depth, output_height, output_width);
195  batchToSpace<Context>(
196  input,
197  this->pad_t_,
198  this->pad_l_,
199  this->block_size_,
200  output,
201  &context_);
202  return true;
203  }
204 };
205 
206 } // namespace caffe2
207 
208 #endif // CAFFE2_OPERATORS_SPACE_BATCH_OP_H_
Workspace is a class that holds all the related objects created during runtime: (1) all blobs...
Definition: workspace.h:47
A global dictionary that holds information about what Caffe2 modules have been loaded in the current ...