From 188708170a51887868a7170c9ee963372bfb9ced Mon Sep 17 00:00:00 2001 From: giuros01 Date: Thu, 13 Sep 2018 09:31:40 +0100 Subject: [COMPMID-1331] Add support for RoIAlign operator in CL Change-Id: Ie215daacd10477309dbf8af1bb2b05b7a0a8f203 Reviewed-on: https://eu-gerrit-1.euhpc.arm.com/150773 Tested-by: bsgcomp Reviewed-by: Isabella Gottardi Reviewed-by: Pablo Tello --- tests/validation/reference/ROIAlignLayer.cpp | 186 +++++++++++++++++++++++++++ tests/validation/reference/ROIAlignLayer.h | 45 +++++++ 2 files changed, 231 insertions(+) create mode 100644 tests/validation/reference/ROIAlignLayer.cpp create mode 100644 tests/validation/reference/ROIAlignLayer.h (limited to 'tests/validation/reference') diff --git a/tests/validation/reference/ROIAlignLayer.cpp b/tests/validation/reference/ROIAlignLayer.cpp new file mode 100644 index 0000000000..68a465d18f --- /dev/null +++ b/tests/validation/reference/ROIAlignLayer.cpp @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2018 ARM Limited. + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#include "ROIAlignLayer.h" + +#include "arm_compute/core/Types.h" +#include "arm_compute/core/utils/misc/ShapeCalculator.h" +#include "tests/validation/Helpers.h" + +#include + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace reference +{ +namespace +{ +/** Average pooling over an aligned window */ +template +inline T roi_align_1x1(const T *input, TensorShape input_shape, + float region_start_x, + float bin_size_x, + int grid_size_x, + float region_end_x, + float region_start_y, + float bin_size_y, + int grid_size_y, + float region_end_y, + int pz) +{ + if((region_end_x <= region_start_x) || (region_end_y <= region_start_y)) + { + return T(0); + } + else + { + float avg = 0; + // Iterate through the aligned pooling region + for(int iy = 0; iy < grid_size_y; ++iy) + { + for(int ix = 0; ix < grid_size_x; ++ix) + { + // Align the window in the middle of every bin + float y = region_start_y + (iy + 0.5) * bin_size_y / float(grid_size_y); + float x = region_start_x + (ix + 0.5) * bin_size_x / float(grid_size_x); + + // Interpolation in the [0,0] [0,1] [1,0] [1,1] square + const int y_low = y; + const int x_low = x; + const int y_high = y_low + 1; + const int x_high = x_low + 1; + + const float ly = y - y_low; + const float lx = x - x_low; + const float hy = 1. - ly; + const float hx = 1. - lx; + + const float w1 = hy * hx; + const float w2 = hy * lx; + const float w3 = ly * hx; + const float w4 = ly * lx; + + const size_t idx1 = coord2index(input_shape, Coordinates(x_low, y_low, pz)); + T data1 = input[idx1]; + + const size_t idx2 = coord2index(input_shape, Coordinates(x_high, y_low, pz)); + T data2 = input[idx2]; + + const size_t idx3 = coord2index(input_shape, Coordinates(x_low, y_high, pz)); + T data3 = input[idx3]; + + const size_t idx4 = coord2index(input_shape, Coordinates(x_high, y_high, pz)); + T data4 = input[idx4]; + + avg += w1 * data1 + w2 * data2 + w3 * data3 + w4 * data4; + } + } + + avg /= grid_size_x * grid_size_y; + + return T(avg); + } +} + +/** Clamp the value between lower and upper */ +template +T clamp(T value, T lower, T upper) +{ + return std::max(lower, std::min(value, upper)); +} +} // namespace +template +SimpleTensor roi_align_layer(const SimpleTensor &src, const std::vector &rois, const ROIPoolingLayerInfo &pool_info) +{ + const size_t num_rois = rois.size(); + DataType dst_data_type = src.data_type(); + + TensorShape input_shape = src.shape(); + TensorShape output_shape(pool_info.pooled_width(), pool_info.pooled_height(), src.shape()[2], num_rois); + SimpleTensor dst(output_shape, dst_data_type); + + // Iterate over every pixel of the input image + for(size_t px = 0; px < pool_info.pooled_width(); px++) + { + for(size_t py = 0; py < pool_info.pooled_height(); py++) + { + for(size_t pw = 0; pw < num_rois; pw++) + { + ROI roi = rois[pw]; + const int roi_batch = roi.batch_idx; + + const float roi_anchor_x = roi.rect.x * pool_info.spatial_scale(); + const float roi_anchor_y = roi.rect.y * pool_info.spatial_scale(); + const float roi_dims_x = std::max(roi.rect.width * pool_info.spatial_scale(), 1.0f); + const float roi_dims_y = std::max(roi.rect.height * pool_info.spatial_scale(), 1.0f); + ; + + float bin_size_x = roi_dims_x / pool_info.pooled_width(); + float bin_size_y = roi_dims_y / pool_info.pooled_height(); + float region_start_x = px * bin_size_x + roi_anchor_x; + float region_start_y = py * bin_size_y + roi_anchor_y; + float region_end_x = (px + 1) * bin_size_x + roi_anchor_x; + float region_end_y = (py + 1) * bin_size_y + roi_anchor_y; + + region_start_x = clamp(region_start_x, 0.0f, float(input_shape[0])); + region_start_y = clamp(region_start_y, 0.0f, float(input_shape[1])); + region_end_x = clamp(region_end_x, 0.0f, float(input_shape[0])); + region_end_y = clamp(region_end_y, 0.0f, float(input_shape[1])); + + const int roi_bin_grid_x = (pool_info.sampling_ratio() > 0) ? pool_info.sampling_ratio() : int(ceil(bin_size_x)); + const int roi_bin_grid_y = (pool_info.sampling_ratio() > 0) ? pool_info.sampling_ratio() : int(ceil(bin_size_y)); + + // Move input and output pointer across the fourth dimension + const size_t input_stride_w = input_shape[0] * input_shape[1] * input_shape[2]; + const size_t output_stride_w = output_shape[0] * output_shape[1] * output_shape[2]; + const T *input_ptr = src.data() + roi_batch * input_stride_w; + T *output_ptr = dst.data() + px + py * output_shape[0] + pw * output_stride_w; + + for(int pz = 0; pz < int(input_shape[2]); ++pz) + { + // For every pixel pool over an aligned region + *(output_ptr + pz * output_shape[0] * output_shape[1]) = roi_align_1x1(input_ptr, input_shape, + region_start_x, + bin_size_x, + roi_bin_grid_x, + region_end_x, + region_start_y, + bin_size_y, + roi_bin_grid_y, + region_end_y, pz); + } + } + } + } + return dst; +} +template SimpleTensor roi_align_layer(const SimpleTensor &src, const std::vector &rois, const ROIPoolingLayerInfo &pool_info); +template SimpleTensor roi_align_layer(const SimpleTensor &src, const std::vector &rois, const ROIPoolingLayerInfo &pool_info); +} // namespace reference +} // namespace validation +} // namespace test +} // namespace arm_compute diff --git a/tests/validation/reference/ROIAlignLayer.h b/tests/validation/reference/ROIAlignLayer.h new file mode 100644 index 0000000000..818f9b147c --- /dev/null +++ b/tests/validation/reference/ROIAlignLayer.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2018 ARM Limited. + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef __ARM_COMPUTE_TEST_ROIALIGNLAYER_H__ +#define __ARM_COMPUTE_TEST_ROIALIGNLAYER_H__ + +#include "arm_compute/core/Types.h" +#include "tests/SimpleTensor.h" +#include "tests/validation/Helpers.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace reference +{ +template +SimpleTensor roi_align_layer(const SimpleTensor &src, const std::vector &rois, const ROIPoolingLayerInfo &pool_info); +} // namespace reference +} // namespace validation +} // namespace test +} // namespace arm_compute +#endif /* __ARM_COMPUTE_TEST_ROIALIGNLAYER_H__ */ -- cgit v1.2.1