Compute Library
 21.02
WarpAffine.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017-2019 Arm Limited.
3  *
4  * SPDX-License-Identifier: MIT
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to
8  * deal in the Software without restriction, including without limitation the
9  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10  * sell copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in all
14  * copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  */
24 #include "WarpAffine.h"
25 
26 #include "Utils.h"
27 
28 namespace arm_compute
29 {
30 namespace test
31 {
32 namespace validation
33 {
34 namespace reference
35 {
36 bool valid_bilinear_policy(float xn, float yn, int width, int height, BorderMode border_mode)
37 {
38  if(border_mode != BorderMode::UNDEFINED)
39  {
40  return true;
41  }
42  if((0 <= yn + 1) && (yn + 1 < height) && (0 <= xn + 1) && (xn + 1 < width))
43  {
44  return true;
45  }
46  return false;
47 }
48 
49 template <typename T>
50 SimpleTensor<T> warp_affine(const SimpleTensor<T> &src, SimpleTensor<T> &valid_mask, const float *matrix, InterpolationPolicy policy, BorderMode border_mode, uint8_t constant_border_value)
51 {
52  SimpleTensor<T> dst(src.shape(), src.data_type());
53 
54  // x0 = M00 * x + M01 * y + M02
55  // y0 = M10 * x + M11 * y + M12
56  const float M00 = matrix[0];
57  const float M10 = matrix[1];
58  const float M01 = matrix[0 + 1 * 2];
59  const float M11 = matrix[1 + 1 * 2];
60  const float M02 = matrix[0 + 2 * 2];
61  const float M12 = matrix[1 + 2 * 2];
62 
63  const int width = src.shape().x();
64  const int height = src.shape().y();
65 
66  const uint32_t num_elements = src.num_elements();
67  for(uint32_t element_idx = 0; element_idx < num_elements; ++element_idx)
68  {
69  valid_mask[element_idx] = 1;
70  Coordinates id = index2coord(src.shape(), element_idx);
71  int idx = id.x();
72  int idy = id.y();
73 
74  float x0 = M00 * idx + M01 * idy + M02;
75  float y0 = M10 * idx + M11 * idy + M12;
76 
77  id.set(0, static_cast<int>(std::floor(x0)));
78  id.set(1, static_cast<int>(std::floor(y0)));
79  if((0 <= y0) && (y0 < height) && (0 <= x0) && (x0 < width))
80  {
81  switch(policy)
82  {
84  dst[element_idx] = tensor_elem_at(src, id, border_mode, constant_border_value);
85  break;
87  (valid_bilinear_policy(x0, y0, width, height, border_mode)) ? dst[element_idx] = bilinear_policy(src, id, x0, y0, border_mode, constant_border_value) :
88  valid_mask[element_idx] = 0;
89  break;
91  default:
92  ARM_COMPUTE_ERROR("Interpolation not supported");
93  }
94  }
95  else
96  {
97  if(border_mode == BorderMode::UNDEFINED)
98  {
99  valid_mask[element_idx] = 0;
100  }
101  else
102  {
103  switch(policy)
104  {
106  if(border_mode == BorderMode::CONSTANT)
107  {
108  dst[element_idx] = constant_border_value;
109  }
110  else if(border_mode == BorderMode::REPLICATE)
111  {
112  id.set(0, std::max(0, std::min(static_cast<int>(x0), width - 1)));
113  id.set(1, std::max(0, std::min(static_cast<int>(y0), height - 1)));
114  dst[element_idx] = src[coord2index(src.shape(), id)];
115  }
116  break;
118  dst[element_idx] = bilinear_policy(src, id, x0, y0, border_mode, constant_border_value);
119  break;
121  default:
122  ARM_COMPUTE_ERROR("Interpolation not supported");
123  }
124  }
125  }
126  }
127 
128  return dst;
129 }
130 
131 template SimpleTensor<uint8_t> warp_affine(const SimpleTensor<uint8_t> &src, SimpleTensor<uint8_t> &valid_mask, const float *matrix, InterpolationPolicy policy, BorderMode border_mode,
132  uint8_t constant_border_value);
133 } // namespace reference
134 } // namespace validation
135 } // namespace test
136 } // namespace arm_compute
BorderMode
Methods available to handle borders.
Definition: Types.h:265
InterpolationPolicy
Interpolation method.
Definition: Types.h:392
T tensor_elem_at(const SimpleTensor< T > &src, Coordinates coord, BorderMode border_mode, T constant_border_value)
Definition: Utils.h:64
#define ARM_COMPUTE_ERROR(msg)
Print the given message then throw an std::runtime_error.
Definition: Error.h:352
DataType data_type() const override
Data type of the tensor.
Definition: SimpleTensor.h:357
Output values are defined by bilinear interpolation between the pixels.
TensorShape shape() const override
Shape of the tensor.
Definition: SimpleTensor.h:320
Output values are defined to match the source pixel whose center is nearest to the sample position...
SimpleTensor< float > src
Definition: DFT.cpp:155
Copyright (c) 2017-2021 Arm Limited.
int coord2index(const TensorShape &shape, const Coordinates &coord)
Linearise the given coordinate.
Definition: Utils.h:489
T x() const
Alias to access the size of the first dimension.
Definition: Dimensions.h:87
SimpleTensor< T > warp_affine(const SimpleTensor< T > &src, SimpleTensor< T > &valid_mask, const float *matrix, InterpolationPolicy policy, BorderMode border_mode, uint8_t constant_border_value)
Definition: WarpAffine.cpp:50
Coordinates of an item.
Definition: Coordinates.h:37
T bilinear_policy(const SimpleTensor< T > &in, Coordinates id, float xn, float yn, BorderMode border_mode, T constant_border_value)
Definition: Utils.cpp:36
Coordinates index2coord(const TensorShape &shape, int index)
Convert a linear index into n-dimensional coordinates.
Definition: Utils.h:460
Output values are determined by averaging the source pixels whose areas fall under the area of the de...
Simple tensor object that stores elements in a consecutive chunk of memory.
Definition: SimpleTensor.h:58
Borders are left undefined.
Pixels outside the image are assumed to have the same value as the closest image pixel.
int num_elements() const override
Number of elements of the tensor.
Definition: SimpleTensor.h:406
bool valid_bilinear_policy(float xn, float yn, int width, int height, BorderMode border_mode)
Definition: WarpAffine.cpp:36