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 "Remap.h"
25 
26 #include "Utils.h"
27 #include "tests/validation/Helpers.h"
28 
29 #include <algorithm>
30 #include <array>
31 
32 namespace arm_compute
33 {
34 namespace test
35 {
36 namespace validation
37 {
38 namespace reference
39 {
40 template <typename T>
remap(const SimpleTensor<T> & in,SimpleTensor<float> & map_x,SimpleTensor<float> & map_y,SimpleTensor<T> & valid_mask,InterpolationPolicy policy,BorderMode border_mode,T constant_border_value)41 SimpleTensor<T> remap(const SimpleTensor<T> &in, SimpleTensor<float> &map_x, SimpleTensor<float> &map_y, SimpleTensor<T> &valid_mask, InterpolationPolicy policy, BorderMode border_mode,
42                       T constant_border_value)
43 {
44     ARM_COMPUTE_ERROR_ON_MSG(border_mode == BorderMode::REPLICATE, "BorderMode not supported");
45     SimpleTensor<T> out(in.shape(), in.data_type());
46     ARM_COMPUTE_ERROR_ON(out.num_elements() != map_x.num_elements());
47     const int      width        = in.shape().x();
48     const int      height       = in.shape().y();
49     const uint32_t num_elements = out.num_elements();
50     for(uint32_t idx = 0; idx < num_elements; idx++)
51     {
52         const Coordinates id_out = index2coord(out.shape(), idx);
53         valid_mask[idx]          = 1;
54         Coordinates src_idx      = id_out; // need to setup all coordinates and not just xy
55         src_idx.set(0, static_cast<int>(std::floor(map_x[idx])));
56         src_idx.set(1, static_cast<int>(std::floor(map_y[idx])));
57         if((0 <= map_y[idx]) && (map_y[idx] < height) && (0 <= map_x[idx]) && (map_x[idx] < width))
58         {
59             switch(policy)
60             {
61                 case InterpolationPolicy::NEAREST_NEIGHBOR:
62                 {
63                     out[idx] = tensor_elem_at(in, src_idx, border_mode, constant_border_value);
64                     break;
65                 }
66                 case InterpolationPolicy::BILINEAR:
67                 {
68                     (valid_bilinear_policy(map_x[idx], map_y[idx], width, height, border_mode)) ?
69                     out[idx]        = bilinear_policy(in, src_idx, map_x[idx], map_y[idx], border_mode, constant_border_value) :
70                                       valid_mask[idx] = 0;
71                     break;
72                 }
73                 case InterpolationPolicy::AREA:
74                 default:
75                     ARM_COMPUTE_ERROR("Interpolation not supported");
76                     break;
77             }
78         }
79         else
80         {
81             if(border_mode == BorderMode::UNDEFINED)
82             {
83                 valid_mask[idx] = 0;
84             }
85             else
86             {
87                 switch(policy)
88                 {
89                     case InterpolationPolicy::NEAREST_NEIGHBOR:
90                         out[idx] = constant_border_value;
91                         break;
92                     case InterpolationPolicy::BILINEAR:
93                         out[idx] = bilinear_policy(in, src_idx, map_x[idx], map_y[idx], border_mode, constant_border_value);
94                         break;
95                     case InterpolationPolicy::AREA:
96                     default:
97                         break;
98                 }
99             }
100         }
101     }
102 
103     return out;
104 }
105 
106 template SimpleTensor<uint8_t> remap(const SimpleTensor<uint8_t> &src, SimpleTensor<float> &map_x, SimpleTensor<float> &map_y, SimpleTensor<uint8_t> &valid_mask, InterpolationPolicy policy,
107                                      BorderMode border_mode,
108                                      uint8_t    constant_border_value);
109 } // namespace reference
110 } // namespace validation
111 } // namespace test
112 } // namespace arm_compute
113