1 #include "caffe2/operators/pad_op.h" 7 PadMode StringToPadMode(
const string& mode) {
8 if (mode ==
"constant") {
9 return PadMode::CONSTANT;
10 }
else if (mode ==
"reflect") {
11 return PadMode::REFLECT;
12 }
else if (mode ==
"edge") {
15 CAFFE_THROW(
"Unknown padding mode: " + mode);
23 bool PadImageOp<float, CPUContext>::RunOnDeviceWithOrderNCHW() {
26 int channels = X.dim32(1);
27 int height = X.dim32(2);
28 int width = X.dim32(3);
29 ConvPoolOpBase::SetOutputSize(X, Y, channels);
31 const float* Xdata = X.data<
float>();
32 float* Ydata = Y->template mutable_data<float>();
34 int padded_height = Y->dim32(2);
35 int padded_width = Y->dim32(3);
38 case PadMode::CONSTANT:
39 for (
int n = 0; n < X.dim32(0); ++n) {
40 for (
int c = 0; c < channels; ++c) {
41 for (
int ph = 0; ph < padded_height; ++ph) {
42 for (
int pw = 0; pw < padded_width; ++pw) {
45 Ydata[ph * padded_width + pw] =
46 (h < 0 || w < 0 || h >= height || w >= width)
48 : Xdata[h * width + w];
52 Xdata += height * width;
53 Ydata += padded_height * padded_width;
57 case PadMode::REFLECT:
58 if (pad_r() >= 0 && pad_t() >= 0 && pad_l() >= 0 && pad_b() >= 0) {
59 for (
int n = 0; n < X.dim32(0); ++n) {
60 for (
int c = 0; c < channels; ++c) {
63 auto* Ystart = Ydata + pad_t() * padded_width + pad_l();
64 math::CopyMatrix<CPUContext>(
76 int h = ph - pad_t(); \ 77 int w = pw - pad_l(); \ 79 h = min(h, 2 * height - h - 2); \ 81 w = min(w, 2 * width - w - 2); \ 82 Ydata[ph * padded_width + pw] = Xdata[h * width + w] 85 for (
int ph = 0; ph < pad_t(); ++ph) {
86 for (
int pw = 0; pw < padded_width; ++pw) {
92 for (
int ph = padded_height - pad_b(); ph < padded_height; ++ph) {
93 for (
int pw = 0; pw < padded_width; ++pw) {
99 for (
int ph = pad_t(); ph < padded_height - pad_b(); ++ph) {
101 for (
int pw = 0; pw < pad_l(); ++pw) {
105 for (
int pw = padded_width - pad_r(); pw < padded_width; ++pw) {
112 Xdata += height * width;
113 Ydata += padded_height * padded_width;
117 for (
int n = 0; n < X.dim32(0); ++n) {
118 for (
int c = 0; c < channels; ++c) {
119 for (
int ph = 0; ph < padded_height; ++ph) {
120 for (
int pw = 0; pw < padded_width; ++pw) {
121 int h = ph - pad_t();
122 int w = pw - pad_l();
126 h = min(h, 2 * height - h - 2);
128 w = min(w, 2 * width - w - 2);
129 Ydata[ph * padded_width + pw] = Xdata[h * width + w];
133 Xdata += height * width;
134 Ydata += padded_height * padded_width;
140 for (
int n = 0; n < X.dim32(0); ++n) {
141 for (
int c = 0; c < channels; ++c) {
142 for (
int ph = 0; ph < padded_height; ++ph) {
143 for (
int pw = 0; pw < padded_width; ++pw) {
145 int h = min(height - 1, max(ph - pad_t(), 0));
146 int w = min(width - 1, max(pw - pad_l(), 0));
147 Ydata[ph * padded_width + pw] = Xdata[h * width + w];
151 Xdata += height * width;
152 Ydata += padded_height * padded_width;
161 bool PadImageOp<float, CPUContext>::RunOnDeviceWithOrderNHWC() {
164 int height = X.dim32(1);
165 int width = X.dim32(2);
166 int channels = X.dim32(3);
167 ConvPoolOpBase::SetOutputSize(X, Y, channels);
168 const float* Xdata = X.data<
float>();
169 float* Ydata = Y->template mutable_data<float>();
172 int padded_height = Y->dim32(1);
173 int padded_width = Y->dim32(2);
176 case PadMode::CONSTANT:
177 for (
int n = 0; n < X.dim32(0); ++n) {
178 for (
int ph = 0; ph < padded_height; ++ph) {
179 for (
int pw = 0; pw < padded_width; ++pw) {
180 int h = ph - pad_t();
181 int w = pw - pad_l();
182 const int pad_index = (ph * padded_width + pw) * channels;
183 if (h < 0 || w < 0 || h >= height || w >= width) {
184 for (
int c = 0; c < channels; ++c) {
185 Ydata[pad_index + c] = value_;
188 const int input_index = (h * width + w) * channels;
189 for (
int c = 0; c < channels; ++c) {
190 Ydata[pad_index + c] = Xdata[input_index + c];
196 Xdata += X.numel() / X.dim32(0);
197 Ydata += Y->numel() / Y->dim32(0);
200 case PadMode::REFLECT:
201 for (
int n = 0; n < X.dim32(0); ++n) {
202 for (
int ph = 0; ph < padded_height; ++ph) {
203 for (
int pw = 0; pw < padded_width; ++pw) {
204 const int pad_index = (ph * padded_width + pw) * channels;
205 int h = ph - pad_t();
206 int w = pw - pad_l();
210 h = min(h, 2 * height - h - 2);
212 w = min(w, 2 * width - w - 2);
213 const int input_index = (h * width + w) * channels;
214 for (
int c = 0; c < channels; ++c) {
215 Ydata[pad_index + c] = Xdata[input_index + c];
220 Xdata += X.numel() / X.dim32(0);
221 Ydata += Y->numel() / Y->dim32(0);
225 for (
int n = 0; n < X.dim32(0); ++n) {
226 for (
int ph = 0; ph < padded_height; ++ph) {
227 for (
int pw = 0; pw < padded_width; ++pw) {
228 const int pad_index = (ph * padded_width + pw) * channels;
229 int h = min(height - 1, max(ph - pad_t(), 0));
230 int w = min(width - 1, max(pw - pad_l(), 0));
231 const int input_index = (h * width + w) * channels;
232 for (
int c = 0; c < channels; ++c) {
233 Ydata[pad_index + c] = Xdata[input_index + c];
238 Xdata += X.numel() / X.dim32(0);
239 Ydata += Y->numel() / Y->dim32(0);
247 bool PadImageGradientOp<float, CPUContext>::RunOnDeviceWithOrderNCHW() {
254 dY.dim32(2) - pad_t() - pad_b(),
255 dY.dim32(3) - pad_l() - pad_r()},
257 int padded_height = dY.dim32(2);
258 int padded_width = dY.dim32(3);
259 int channels = dX->dim32(1);
260 int height = dX->dim32(2);
261 int width = dX->dim32(3);
263 const float* dYdata = dY.data<
float>();
264 float* dXdata = dX->template mutable_data<float>();
265 math::Set<float, CPUContext>(dX->numel(), 0, dXdata, &context_);
268 case PadMode::CONSTANT:
269 for (
int n = 0; n < dY.dim32(0); ++n) {
270 for (
int c = 0; c < channels; ++c) {
271 for (
int ph = 0; ph < padded_height; ++ph) {
272 for (
int pw = 0; pw < padded_width; ++pw) {
273 int h = ph - pad_t();
274 int w = pw - pad_l();
275 if (!(h < 0 || w < 0 || h >= height || w >= width)) {
276 dXdata[h * width + w] += dYdata[ph * padded_width + pw];
281 dXdata += height * width;
282 dYdata += padded_height * padded_width;
286 case PadMode::REFLECT:
287 for (
int n = 0; n < dY.dim32(0); ++n) {
288 for (
int c = 0; c < channels; ++c) {
289 for (
int ph = 0; ph < padded_height; ++ph) {
290 for (
int pw = 0; pw < padded_width; ++pw) {
291 int h = ph - pad_t();
292 int w = pw - pad_l();
296 h = min(h, 2 * height - h - 2);
298 w = min(w, 2 * width - w - 2);
299 dXdata[h * width + w] += dYdata[ph * padded_width + pw];
303 dXdata += height * width;
304 dYdata += padded_height * padded_width;
309 for (
int n = 0; n < dY.dim32(0); ++n) {
310 for (
int c = 0; c < channels; ++c) {
311 for (
int ph = 0; ph < padded_height; ++ph) {
312 for (
int pw = 0; pw < padded_width; ++pw) {
313 int h = min(height - 1, max(ph - pad_t(), 0));
314 int w = min(width - 1, max(pw - pad_l(), 0));
315 dXdata[h * width + w] += dYdata[ph * padded_width + pw];
319 dXdata += height * width;
320 dYdata += padded_height * padded_width;
329 bool PadImageGradientOp<float, CPUContext>::RunOnDeviceWithOrderNHWC() {
335 dY.dim32(1) - pad_t() - pad_b(),
336 dY.dim32(2) - pad_l() - pad_r(),
339 int padded_height = dY.dim32(1);
340 int padded_width = dY.dim32(2);
341 int channels = dY.dim32(3);
342 int height = dX->dim32(1);
343 int width = dX->dim32(2);
345 const float* dYdata = dY.data<
float>();
346 float* dXdata = dX->template mutable_data<float>();
347 math::Set<float, CPUContext>(dX->numel(), 0, dXdata, &context_);
350 case PadMode::CONSTANT:
351 for (
int n = 0; n < dY.dim32(0); ++n) {
352 for (
int ph = 0; ph < padded_height; ++ph) {
353 for (
int pw = 0; pw < padded_width; ++pw) {
354 int h = ph - pad_t();
355 int w = pw - pad_l();
356 const int pad_index = (ph * padded_width + pw) * channels;
357 if (!(h < 0 || w < 0 || h >= height || w >= width)) {
358 const int input_index = (h * width + w) * channels;
359 for (
int c = 0; c < channels; ++c) {
360 dXdata[input_index + c] += dYdata[pad_index + c];
366 dXdata += dX->numel() / dX->dim32(0);
367 dYdata += dY.numel() / dY.dim32(0);
370 case PadMode::REFLECT:
371 for (
int n = 0; n < dY.dim32(0); ++n) {
372 for (
int ph = 0; ph < padded_height; ++ph) {
373 for (
int pw = 0; pw < padded_width; ++pw) {
374 const int pad_index = (ph * padded_width + pw) * channels;
375 int h = ph - pad_t();
376 int w = pw - pad_l();
380 h = min(h, 2 * height - h - 2);
382 w = min(w, 2 * width - w - 2);
383 const int input_index = (h * width + w) * channels;
384 for (
int c = 0; c < channels; ++c) {
385 dXdata[input_index + c] += dYdata[pad_index + c];
390 dXdata += dX->numel() / dX->dim32(0);
391 dYdata += dY.numel() / dY.dim32(0);
395 for (
int n = 0; n < dY.dim32(0); ++n) {
396 for (
int ph = 0; ph < padded_height; ++ph) {
397 for (
int pw = 0; pw < padded_width; ++pw) {
398 const int pad_index = (ph * padded_width + pw) * channels;
400 int h = min(height - 1, max(ph - pad_t(), 0));
401 int w = min(width - 1, max(pw - pad_l(), 0));
402 const int input_index = (h * width + w) * channels;
403 for (
int c = 0; c < channels; ++c) {
404 dXdata[input_index + c] += dYdata[pad_index + c];
409 dXdata += dX->numel() / dX->dim32(0);
410 dYdata += dY.numel() / dY.dim32(0);
418 std::vector<TensorShape> PadImageOp<float, CPUContext>::PadTensorInference(
419 const OperatorDef& def,
420 const vector<TensorShape>& in) {
421 return ConvPoolOpBase::TensorInferenceForPool(def, in);
424 REGISTER_CPU_OPERATOR(PadImage, PadImageOp<float, CPUContext>);
425 REGISTER_CPU_GRADIENT_OPERATOR(
427 PadImageGradientOp<float, CPUContext>);
429 OPERATOR_SCHEMA(PadImage)
432 .TensorInferenceFunction(PadImageOp<float, CPUContext>::PadTensorInference)
434 PadImage pads values around the boundary of an image according to the pad 435 values and stride sizes defined by the ConvPoolOpBase operator. 440 "Input data tensor from the previous operator; dimensions " 441 "depend on whether the NCHW or NHWC operators are being used. For example, " 442 "in the former, the input has size (N x C x H x W), where N is the batch " 443 "size, C is the number of channels, and H and W are the height and the width " 444 "of the data. The corresponding permutation of dimensions is used in the " 449 "Output data tensor from padding the H and W dimensions on " 450 "the tensor. Dimensions will vary based on various pad and stride " 453 GRADIENT_OPERATOR_SCHEMA(PadImageGradient).NumInputs(1).NumOutputs(1);
456 using GradientMakerBase::GradientMakerBase;
457 vector<OperatorDef> GetGradientDefs()
override {
459 "PadImageGradient",
"", vector<string>{GO(0)}, vector<string>{GI(0)});
A global dictionary that holds information about what Caffe2 modules have been loaded in the current ...
static vector< OperatorDef > SingleGradientDef(const Args &...args)
a helper function to allow one to create one single operator def, which is usually the case for many ...