mlpack
bilinear_interpolation_impl.hpp
Go to the documentation of this file.
1 
13 #ifndef MLPACK_METHODS_ANN_LAYER_BILINEAR_INTERPOLATION_IMPL_HPP
14 #define MLPACK_METHODS_ANN_LAYER_BILINEAR_INTERPOLATION_IMPL_HPP
15 
16 // In case it hasn't yet been included.
18 
19 namespace mlpack {
20 namespace ann {
21 
22 
23 template<typename InputDataType, typename OutputDataType>
26  inRowSize(0),
27  inColSize(0),
28  outRowSize(0),
29  outColSize(0),
30  depth(0),
31  batchSize(0)
32 {
33  // Nothing to do here.
34 }
35 
36 template<typename InputDataType, typename OutputDataType>
39  const size_t inRowSize,
40  const size_t inColSize,
41  const size_t outRowSize,
42  const size_t outColSize,
43  const size_t depth):
44  inRowSize(inRowSize),
45  inColSize(inColSize),
46  outRowSize(outRowSize),
47  outColSize(outColSize),
48  depth(depth),
49  batchSize(0)
50 {
51  // Nothing to do here.
52 }
53 
54 template<typename InputDataType, typename OutputDataType>
55 template<typename eT>
57  const arma::Mat<eT>& input, arma::Mat<eT>& output)
58 {
59  batchSize = input.n_cols;
60  if (output.is_empty())
61  output.set_size(outRowSize * outColSize * depth, batchSize);
62  else
63  {
64  assert(output.n_rows == outRowSize * outColSize * depth);
65  assert(output.n_cols == batchSize);
66  }
67 
68  assert(inRowSize >= 2);
69  assert(inColSize >= 2);
70 
71  arma::cube inputAsCube(const_cast<arma::Mat<eT>&>(input).memptr(),
72  inRowSize, inColSize, depth * batchSize, false, false);
73  arma::cube outputAsCube(output.memptr(), outRowSize, outColSize,
74  depth * batchSize, false, true);
75 
76  double scaleRow = (double) inRowSize / (double) outRowSize;
77  double scaleCol = (double) inColSize / (double) outColSize;
78 
79  arma::mat22 coeffs;
80  for (size_t i = 0; i < outRowSize; ++i)
81  {
82  size_t rOrigin = (size_t) std::floor(i * scaleRow);
83  if (rOrigin > inRowSize - 2)
84  rOrigin = inRowSize - 2;
85 
86  // Scaled distance of the interpolated point from the topmost row.
87  double deltaR = i * scaleRow - rOrigin;
88  if (deltaR > 1)
89  deltaR = 1.0;
90  for (size_t j = 0; j < outColSize; ++j)
91  {
92  // Scaled distance of the interpolated point from the leftmost column.
93  size_t cOrigin = (size_t) std::floor(j * scaleCol);
94  if (cOrigin > inColSize - 2)
95  cOrigin = inColSize - 2;
96 
97  double deltaC = j * scaleCol - cOrigin;
98  if (deltaC > 1)
99  deltaC = 1.0;
100  coeffs[0] = (1 - deltaR) * (1 - deltaC);
101  coeffs[1] = deltaR * (1 - deltaC);
102  coeffs[2] = (1 - deltaR) * deltaC;
103  coeffs[3] = deltaR * deltaC;
104 
105  for (size_t k = 0; k < depth * batchSize; ++k)
106  {
107  outputAsCube(i, j, k) = arma::accu(inputAsCube.slice(k).submat(
108  rOrigin, cOrigin, rOrigin + 1, cOrigin + 1) % coeffs);
109  }
110  }
111  }
112 }
113 
114 template<typename InputDataType, typename OutputDataType>
115 template<typename eT>
117  const arma::Mat<eT>& /*input*/,
118  const arma::Mat<eT>& gradient,
119  arma::Mat<eT>& output)
120 {
121  if (output.is_empty())
122  output.set_size(inRowSize * inColSize * depth, batchSize);
123  else
124  {
125  assert(output.n_rows == inRowSize * inColSize * depth);
126  assert(output.n_cols == batchSize);
127  }
128 
129  assert(outRowSize >= 2);
130  assert(outColSize >= 2);
131 
132  arma::cube gradientAsCube(((arma::Mat<eT>&) gradient).memptr(), outRowSize,
133  outColSize, depth * batchSize, false, false);
134  arma::cube outputAsCube(output.memptr(), inRowSize, inColSize,
135  depth * batchSize, false, true);
136 
137  if (gradient.n_elem == output.n_elem)
138  {
139  outputAsCube = gradientAsCube;
140  }
141  else
142  {
143  double scaleRow = (double)(outRowSize) / inRowSize;
144  double scaleCol = (double)(outColSize) / inColSize;
145 
146  arma::mat22 coeffs;
147  for (size_t i = 0; i < inRowSize; ++i)
148  {
149  size_t rOrigin = (size_t) std::floor(i * scaleRow);
150  if (rOrigin > outRowSize - 2)
151  rOrigin = outRowSize - 2;
152  double deltaR = i * scaleRow - rOrigin;
153  for (size_t j = 0; j < inColSize; ++j)
154  {
155  size_t cOrigin = (size_t) std::floor(j * scaleCol);
156 
157  if (cOrigin > outColSize - 2)
158  cOrigin = outColSize - 2;
159 
160  double deltaC = j * scaleCol - cOrigin;
161  coeffs[0] = (1 - deltaR) * (1 - deltaC);
162  coeffs[1] = deltaR * (1 - deltaC);
163  coeffs[2] = (1 - deltaR) * deltaC;
164  coeffs[3] = deltaR * deltaC;
165 
166  for (size_t k = 0; k < depth * batchSize; ++k)
167  {
168  outputAsCube(i, j, k) = arma::accu(gradientAsCube.slice(k).submat(
169  rOrigin, cOrigin, rOrigin + 1, cOrigin + 1) % coeffs);
170  }
171  }
172  }
173  }
174 }
175 
176 template<typename InputDataType, typename OutputDataType>
177 template<typename Archive>
179  Archive& ar, const uint32_t /* version */)
180 {
181  ar(CEREAL_NVP(inRowSize));
182  ar(CEREAL_NVP(inColSize));
183  ar(CEREAL_NVP(outRowSize));
184  ar(CEREAL_NVP(outColSize));
185  ar(CEREAL_NVP(depth));
186 }
187 
188 } // namespace ann
189 } // namespace mlpack
190 
191 #endif
void serialize(Archive &ar, const uint32_t)
Serialize the layer.
Definition: bilinear_interpolation_impl.hpp:178
Linear algebra utility functions, generally performed on matrices or vectors.
Definition: cv.hpp:1
void Forward(const arma::Mat< eT > &input, arma::Mat< eT > &output)
Forward pass through the layer.
Definition: bilinear_interpolation_impl.hpp:56
BilinearInterpolation()
Create the Bilinear Interpolation object.
Definition: bilinear_interpolation_impl.hpp:25
void Backward(const arma::Mat< eT > &, const arma::Mat< eT > &gradient, arma::Mat< eT > &output)
Ordinary feed backward pass of a neural network, calculating the function f(x) by propagating x backw...
Definition: bilinear_interpolation_impl.hpp:116