From 7655a67384895868c0afa72bfda9a9b2fcfdf323 Mon Sep 17 00:00:00 2001 From: Moritz Pflanzer Date: Sat, 23 Sep 2017 11:57:33 +0100 Subject: COMPMID-507: Move Sobel to new validation Change-Id: Ic0a9dbd8e646abbf8d9ea52e497a5fe60e499cc7 Reviewed-on: http://mpd-gerrit.cambridge.arm.com/88883 Tested-by: Kaizen Reviewed-by: Anthony Barbier --- arm_compute/core/Types.h | 2 +- tests/validation/CL/Sobel.cpp | 283 ++++++++++++++++++++++++++++++ tests/validation/CPP/Sobel.cpp | 136 +++++++++++++++ tests/validation/CPP/Sobel.h | 44 +++++ tests/validation/CPP/Utils.cpp | 37 ---- tests/validation/CPP/Utils.h | 31 +++- tests/validation/NEON/Sobel.cpp | 284 +++++++++++++++++++++++++++++++ tests/validation/Validation.h | 2 +- tests/validation/fixtures/SobelFixture.h | 178 +++++++++++++++++++ tests/validation_old/CL/Sobel3x3.cpp | 205 ---------------------- tests/validation_old/CL/Sobel5x5.cpp | 204 ---------------------- tests/validation_old/NEON/Sobel3x3.cpp | 203 ---------------------- tests/validation_old/NEON/Sobel5x5.cpp | 204 ---------------------- tests/validation_old/Reference.cpp | 32 ---- tests/validation_old/Reference.h | 18 -- tests/validation_old/ReferenceCPP.cpp | 20 --- tests/validation_old/ReferenceCPP.h | 20 --- utils/TypePrinter.h | 7 + 18 files changed, 962 insertions(+), 948 deletions(-) create mode 100644 tests/validation/CL/Sobel.cpp create mode 100644 tests/validation/CPP/Sobel.cpp create mode 100644 tests/validation/CPP/Sobel.h create mode 100644 tests/validation/NEON/Sobel.cpp create mode 100644 tests/validation/fixtures/SobelFixture.h delete mode 100644 tests/validation_old/CL/Sobel3x3.cpp delete mode 100644 tests/validation_old/CL/Sobel5x5.cpp delete mode 100644 tests/validation_old/NEON/Sobel3x3.cpp delete mode 100644 tests/validation_old/NEON/Sobel5x5.cpp diff --git a/arm_compute/core/Types.h b/arm_compute/core/Types.h index 8750a9cf1f..f9766b39be 100644 --- a/arm_compute/core/Types.h +++ b/arm_compute/core/Types.h @@ -142,7 +142,7 @@ struct BorderSize } /** Border with equal size around the 2D plane */ - constexpr BorderSize(unsigned int size) + explicit constexpr BorderSize(unsigned int size) : top{ size }, right{ size }, bottom{ size }, left{ size } { } diff --git a/tests/validation/CL/Sobel.cpp b/tests/validation/CL/Sobel.cpp new file mode 100644 index 0000000000..cde93e77a9 --- /dev/null +++ b/tests/validation/CL/Sobel.cpp @@ -0,0 +1,283 @@ +/* + * Copyright (c) 2017 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 "arm_compute/core/Types.h" +#include "arm_compute/runtime/CL/CLTensor.h" +#include "arm_compute/runtime/CL/CLTensorAllocator.h" +#include "arm_compute/runtime/CL/functions/CLSobel3x3.h" +#include "arm_compute/runtime/CL/functions/CLSobel5x5.h" +#include "arm_compute/runtime/CL/functions/CLSobel7x7.h" +#include "tests/CL/CLAccessor.h" +#include "tests/PaddingCalculator.h" +#include "tests/datasets/BorderModeDataset.h" +#include "tests/datasets/ShapeDatasets.h" +#include "tests/framework/Asserts.h" +#include "tests/framework/Macros.h" +#include "tests/framework/datasets/Datasets.h" +#include "tests/validation/Validation.h" +#include "tests/validation/fixtures/SobelFixture.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +TEST_SUITE(CL) +TEST_SUITE(Sobel) + +TEST_SUITE(W3x3) +using CLSobel3x3Fixture = SobelValidationFixture; + +DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(combine(concat(datasets::Small2DShapes(), datasets::Large2DShapes()), datasets::BorderModes()), framework::dataset::make("Format", + Format::U8)), + shape, border_mode, format) +{ + // Generate a random constant value + std::mt19937 gen(library->seed()); + std::uniform_int_distribution int_dist(0, 255); + const uint8_t constant_border_value = int_dist(gen); + + // Create tensors + CLTensor src = create_tensor(shape, data_type_from_format(format)); + CLTensor dst_x = create_tensor(shape, DataType::S16); + CLTensor dst_y = create_tensor(shape, DataType::S16); + + src.info()->set_format(format); + dst_x.info()->set_format(Format::S16); + dst_y.info()->set_format(Format::S16); + + ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(dst_x.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(dst_y.info()->is_resizable(), framework::LogLevel::ERRORS); + + // Create sobel 3x3 configure function + CLSobel3x3 sobel; + sobel.configure(&src, &dst_x, &dst_y, border_mode, constant_border_value); + + // Validate valid region + constexpr BorderSize border_size{ 1 }; + const ValidRegion dst_valid_region = shape_to_valid_region(shape, border_mode == BorderMode::UNDEFINED, border_size); + + validate(dst_x.info()->valid_region(), dst_valid_region); + validate(dst_y.info()->valid_region(), dst_valid_region); + + // Validate padding + PaddingCalculator calculator(shape.x(), 8); + + calculator.set_border_mode(border_mode); + calculator.set_border_size(1); + + const PaddingSize dst_padding = calculator.required_padding(); + + calculator.set_accessed_elements(16); + calculator.set_access_offset(-1); + + const PaddingSize src_padding = calculator.required_padding(); + + validate(src.info()->padding(), src_padding); + validate(dst_x.info()->padding(), dst_padding); + validate(dst_y.info()->padding(), dst_padding); +} + +FIXTURE_DATA_TEST_CASE(RunSmall, CLSobel3x3Fixture, framework::DatasetMode::PRECOMMIT, combine(combine(datasets::Small2DShapes(), datasets::BorderModes()), framework::dataset::make("Format", + Format::U8))) +{ + // Validate output + ValidRegion valid_region_x = shape_to_valid_region(_reference.first.shape(), (_border_mode == BorderMode::UNDEFINED), BorderSize(1)); + validate(CLAccessor(_target.first), _reference.first, valid_region_x); + + ValidRegion valid_region_y = shape_to_valid_region(_reference.second.shape(), (_border_mode == BorderMode::UNDEFINED), BorderSize(1)); + validate(CLAccessor(_target.second), _reference.second, valid_region_y); +} + +FIXTURE_DATA_TEST_CASE(RunLarge, CLSobel3x3Fixture, framework::DatasetMode::NIGHTLY, combine(combine(datasets::Large2DShapes(), datasets::BorderModes()), framework::dataset::make("Format", + Format::U8))) +{ + // Validate output + ValidRegion valid_region_x = shape_to_valid_region(_reference.first.shape(), (_border_mode == BorderMode::UNDEFINED), BorderSize(1)); + validate(CLAccessor(_target.first), _reference.first, valid_region_x); + + ValidRegion valid_region_y = shape_to_valid_region(_reference.second.shape(), (_border_mode == BorderMode::UNDEFINED), BorderSize(1)); + validate(CLAccessor(_target.second), _reference.second, valid_region_y); +} +TEST_SUITE_END() + +TEST_SUITE(W5x5) +using CLSobel5x5Fixture = SobelValidationFixture; + +DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(combine(concat(datasets::Small2DShapes(), datasets::Large2DShapes()), datasets::BorderModes()), framework::dataset::make("Format", + Format::U8)), + shape, border_mode, format) +{ + // Generate a random constant value + std::mt19937 gen(library->seed()); + std::uniform_int_distribution int_dist(0, 255); + const uint8_t constant_border_value = int_dist(gen); + + // Create tensors + CLTensor src = create_tensor(shape, data_type_from_format(format)); + CLTensor dst_x = create_tensor(shape, DataType::S16); + CLTensor dst_y = create_tensor(shape, DataType::S16); + + src.info()->set_format(format); + dst_x.info()->set_format(Format::S16); + dst_y.info()->set_format(Format::S16); + + ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(dst_x.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(dst_y.info()->is_resizable(), framework::LogLevel::ERRORS); + + // Create sobel 5x5 configure function + CLSobel5x5 sobel; + sobel.configure(&src, &dst_x, &dst_y, border_mode, constant_border_value); + + // Validate valid region + constexpr BorderSize border_size{ 2 }; + const ValidRegion dst_valid_region = shape_to_valid_region(shape, border_mode == BorderMode::UNDEFINED, border_size); + + validate(dst_x.info()->valid_region(), dst_valid_region); + validate(dst_y.info()->valid_region(), dst_valid_region); + + // Validate padding + PaddingCalculator calculator(shape.x(), 8); + calculator.set_border_mode(border_mode); + calculator.set_border_size(2); + + const PaddingSize dst_padding = calculator.required_padding(); + + calculator.set_accessed_elements(16); + calculator.set_access_offset(-2); + + const PaddingSize src_padding = calculator.required_padding(); + + validate(src.info()->padding(), src_padding); + validate(dst_x.info()->padding(), dst_padding); + validate(dst_y.info()->padding(), dst_padding); +} + +FIXTURE_DATA_TEST_CASE(RunSmall, CLSobel5x5Fixture, framework::DatasetMode::PRECOMMIT, combine(combine(datasets::Small2DShapes(), datasets::BorderModes()), framework::dataset::make("Format", + Format::U8))) +{ + // Validate output + ValidRegion valid_region_x = shape_to_valid_region(_reference.first.shape(), (_border_mode == BorderMode::UNDEFINED), BorderSize(2)); + validate(CLAccessor(_target.first), _reference.first, valid_region_x); + + ValidRegion valid_region_y = shape_to_valid_region(_reference.second.shape(), (_border_mode == BorderMode::UNDEFINED), BorderSize(2)); + validate(CLAccessor(_target.second), _reference.second, valid_region_y); +} + +FIXTURE_DATA_TEST_CASE(RunLarge, CLSobel5x5Fixture, framework::DatasetMode::NIGHTLY, combine(combine(datasets::Large2DShapes(), datasets::BorderModes()), framework::dataset::make("Format", + Format::U8))) +{ + // Validate output + ValidRegion valid_region_x = shape_to_valid_region(_reference.first.shape(), (_border_mode == BorderMode::UNDEFINED), BorderSize(2)); + validate(CLAccessor(_target.first), _reference.first, valid_region_x); + + ValidRegion valid_region_y = shape_to_valid_region(_reference.second.shape(), (_border_mode == BorderMode::UNDEFINED), BorderSize(2)); + validate(CLAccessor(_target.second), _reference.second, valid_region_y); +} +TEST_SUITE_END() + +TEST_SUITE(W7x7) +using CLSobel7x7Fixture = SobelValidationFixture; + +DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(combine(concat(datasets::Small2DShapes(), datasets::Large2DShapes()), datasets::BorderModes()), framework::dataset::make("Format", + Format::U8)), + shape, border_mode, format) +{ + // Generate a random constant value + std::mt19937 gen(library->seed()); + std::uniform_int_distribution int_dist(0, 255); + const uint8_t constant_border_value = int_dist(gen); + + // Create tensors + CLTensor src = create_tensor(shape, data_type_from_format(format)); + CLTensor dst_x = create_tensor(shape, DataType::S32); + CLTensor dst_y = create_tensor(shape, DataType::S32); + + src.info()->set_format(format); + dst_x.info()->set_format(Format::S32); + dst_y.info()->set_format(Format::S32); + + ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(dst_x.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(dst_y.info()->is_resizable(), framework::LogLevel::ERRORS); + + // Create sobel 7x7 configure function + CLSobel7x7 sobel; + sobel.configure(&src, &dst_x, &dst_y, border_mode, constant_border_value); + + // Validate valid region + constexpr BorderSize border_size{ 3 }; + const ValidRegion dst_valid_region = shape_to_valid_region(shape, border_mode == BorderMode::UNDEFINED, border_size); + + validate(dst_x.info()->valid_region(), dst_valid_region); + validate(dst_y.info()->valid_region(), dst_valid_region); + + // Validate padding + PaddingCalculator calculator(shape.x(), 8); + + calculator.set_border_mode(border_mode); + calculator.set_border_size(3); + + const PaddingSize dst_padding = calculator.required_padding(); + + calculator.set_accessed_elements(16); + calculator.set_access_offset(-3); + + const PaddingSize src_padding = calculator.required_padding(); + + validate(src.info()->padding(), src_padding); + validate(dst_x.info()->padding(), dst_padding); + validate(dst_y.info()->padding(), dst_padding); +} + +FIXTURE_DATA_TEST_CASE(RunSmall, CLSobel7x7Fixture, framework::DatasetMode::PRECOMMIT, combine(combine(datasets::Small2DShapes(), datasets::BorderModes()), framework::dataset::make("Format", + Format::U8))) +{ + // Validate output + ValidRegion valid_region_x = shape_to_valid_region(_reference.first.shape(), (_border_mode == BorderMode::UNDEFINED), BorderSize(3)); + validate(CLAccessor(_target.first), _reference.first, valid_region_x); + + ValidRegion valid_region_y = shape_to_valid_region(_reference.second.shape(), (_border_mode == BorderMode::UNDEFINED), BorderSize(3)); + validate(CLAccessor(_target.second), _reference.second, valid_region_y); +} + +FIXTURE_DATA_TEST_CASE(RunLarge, CLSobel7x7Fixture, framework::DatasetMode::NIGHTLY, combine(combine(datasets::Large2DShapes(), datasets::BorderModes()), framework::dataset::make("Format", + Format::U8))) +{ + // Validate output + ValidRegion valid_region_x = shape_to_valid_region(_reference.first.shape(), (_border_mode == BorderMode::UNDEFINED), BorderSize(3)); + validate(CLAccessor(_target.first), _reference.first, valid_region_x); + + ValidRegion valid_region_y = shape_to_valid_region(_reference.second.shape(), (_border_mode == BorderMode::UNDEFINED), BorderSize(3)); + validate(CLAccessor(_target.second), _reference.second, valid_region_y); +} +TEST_SUITE_END() + +TEST_SUITE_END() +TEST_SUITE_END() +} // namespace validation +} // namespace test +} // namespace arm_compute diff --git a/tests/validation/CPP/Sobel.cpp b/tests/validation/CPP/Sobel.cpp new file mode 100644 index 0000000000..314fbd4f8a --- /dev/null +++ b/tests/validation/CPP/Sobel.cpp @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2017 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 "Sobel.h" + +#include "Utils.h" +#include "tests/validation/Helpers.h" + +#include +#include +#include + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace reference +{ +namespace +{ +const std::array sobel_3_x{ { -1, 0, 1, -2, 0, 2, -1, 0, 1 } }; +const std::array sobel_3_y{ { -1, -2, -1, 0, 0, 0, 1, 2, 1 } }; + +const std::array sobel_5_x{ { + -1, -2, 0, 2, 1, + -4, -8, 0, 8, 4, + -6, -12, 0, 12, 6, + -4, -8, 0, 8, 4, + -1, -2, 0, 2, 1 + } }; + +const std::array sobel_5_y{ { + -1, -4, -6, -4, -1, + -2, -8, -12, -8, -2, + 0, 0, 0, 0, 0, + 2, 8, 12, 8, 2, + 1, 4, 6, 4, 1 + } }; + +const std::array sobel_7_x{ { + -1, -4, -5, 0, 5, 4, 1, + -6, -24, -30, 0, 30, 24, 6, + -15, -60, -75, 0, 75, 60, 15, + -20, -80, -100, 0, 100, 80, 20, + -15, -60, -75, 0, 75, 60, 15, + -6, -24, -30, 0, 30, 24, 6, + -1, -4, -5, 0, 5, 4, 1 + } }; + +const std::array sobel_7_y{ { + -1, -6, -15, -20, -15, -6, -1, + -4, -24, -60, -80, -60, -24, -4, + -5, -30, -75, -100, -75, -30, -5, + 0, 0, 0, 0, 0, 0, 0, + 5, 30, 75, 100, 75, 30, 5, + 4, 24, 60, 80, 60, 24, 4, + 1, 6, 15, 20, 15, 6, 1 + } }; + +const std::map> masks +{ + { 3, { sobel_3_x.data(), sobel_3_y.data() } }, + { 5, { sobel_5_x.data(), sobel_5_y.data() } }, + { 7, { sobel_7_x.data(), sobel_7_y.data() } }, +}; + +template +struct data_type; + +template <> +struct data_type +{ + const static DataType value = DataType::S16; +}; + +template <> +struct data_type +{ + const static DataType value = DataType::S32; +}; +} // namespace + +template +std::pair, SimpleTensor> sobel(const SimpleTensor &src, int filter_size, BorderMode border_mode, uint8_t constant_border_value) +{ + SimpleTensor dst_x(src.shape(), data_type::value, src.num_channels()); + SimpleTensor dst_y(src.shape(), data_type::value, src.num_channels()); + + ValidRegion valid_region = shape_to_valid_region(src.shape(), border_mode == BorderMode::UNDEFINED, BorderSize(filter_size / 2)); + + for(int i = 0; i < src.num_elements(); ++i) + { + Coordinates coord = index2coord(src.shape(), i); + + if(!is_in_valid_region(valid_region, coord)) + { + continue; + } + + apply_2d_spatial_filter(coord, src, dst_x, TensorShape{ static_cast(filter_size), static_cast(filter_size) }, masks.at(filter_size).first, 1.f, border_mode, + constant_border_value); + apply_2d_spatial_filter(coord, src, dst_y, TensorShape{ static_cast(filter_size), static_cast(filter_size) }, masks.at(filter_size).second, 1.f, border_mode, + constant_border_value); + } + + return std::make_pair(dst_x, dst_y); +} + +template std::pair, SimpleTensor> sobel(const SimpleTensor &src, int filter_size, BorderMode border_mode, uint8_t constant_border_value); +template std::pair, SimpleTensor> sobel(const SimpleTensor &src, int filter_size, BorderMode border_mode, uint8_t constant_border_value); +} // namespace reference +} // namespace validation +} // namespace test +} // namespace arm_compute diff --git a/tests/validation/CPP/Sobel.h b/tests/validation/CPP/Sobel.h new file mode 100644 index 0000000000..ab046639dc --- /dev/null +++ b/tests/validation/CPP/Sobel.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2017 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_SOBEL_H__ +#define __ARM_COMPUTE_TEST_SOBEL_H__ + +#include "arm_compute/core/Types.h" +#include "tests/SimpleTensor.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace reference +{ +template +std::pair, SimpleTensor> sobel(const SimpleTensor &src, int filter_size, BorderMode border_mode, uint8_t constant_border_value = 0); +} // namespace reference +} // namespace validation +} // namespace test +} // namespace arm_compute +#endif /* __ARM_COMPUTE_TEST_SOBEL_H__ */ diff --git a/tests/validation/CPP/Utils.cpp b/tests/validation/CPP/Utils.cpp index 2f54879818..e27688889d 100644 --- a/tests/validation/CPP/Utils.cpp +++ b/tests/validation/CPP/Utils.cpp @@ -96,43 +96,6 @@ template int16_t bilinear_policy(const SimpleTensor &in, Coordinates id template half bilinear_policy(const SimpleTensor &in, Coordinates id, float xn, float yn, BorderMode border_mode, half constant_border_value); template float bilinear_policy(const SimpleTensor &in, Coordinates id, float xn, float yn, BorderMode border_mode, float constant_border_value); -/* Apply 2D spatial filter on a single element of @p in at coordinates @p coord - * - * - filter sizes have to be odd number - * - Row major order of filter assumed - * - TO_ZERO rounding policy assumed - * - SATURATE convert policy assumed - * - */ -template -void apply_2d_spatial_filter(Coordinates coord, const SimpleTensor &in, SimpleTensor &out, const TensorShape &filter_shape, const T2 *filter_itr, float scale, BorderMode border_mode, - T1 constant_border_value) -{ - double val = 0; - const int x = coord.x(); - const int y = coord.y(); - for(int j = y - static_cast(filter_shape[1] / 2); j <= y + static_cast(filter_shape[1] / 2); ++j) - { - for(int i = x - static_cast(filter_shape[0] / 2); i <= x + static_cast(filter_shape[0] / 2); ++i) - { - coord.set(0, i); - coord.set(1, j); - val += static_cast(*filter_itr) * tensor_elem_at(in, coord, border_mode, constant_border_value); - ++filter_itr; - } - } - coord.set(0, x); - coord.set(1, y); - const double rounded_val = support::cpp11::trunc(val * static_cast(scale)); - out[coord2index(in.shape(), coord)] = saturate_cast(rounded_val); -} -template void apply_2d_spatial_filter(Coordinates coord, const SimpleTensor &in, SimpleTensor &out, const TensorShape &filter_shape, const float *filter_itr, float scale, - BorderMode border_mode, - float constant_border_value); -template void apply_2d_spatial_filter(Coordinates coord, const SimpleTensor &in, SimpleTensor &out, const TensorShape &filter_shape, const uint8_t *filter_itr, float scale, - BorderMode border_mode, - uint8_t constant_border_value); - RawTensor transpose(const RawTensor &src, int chunk_width) { // Create reference diff --git a/tests/validation/CPP/Utils.h b/tests/validation/CPP/Utils.h index 557d85f204..2d879c129b 100644 --- a/tests/validation/CPP/Utils.h +++ b/tests/validation/CPP/Utils.h @@ -47,9 +47,34 @@ T tensor_elem_at(const SimpleTensor &in, Coordinates coord, BorderMode border template T bilinear_policy(const SimpleTensor &in, Coordinates id, float xn, float yn, BorderMode border_mode, T constant_border_value); -template -void apply_2d_spatial_filter(Coordinates coord, const SimpleTensor &in, SimpleTensor &out, const TensorShape &filter_shape, const T2 *filter_itr, float scale, BorderMode border_mode, - T1 constant_border_value = 0); +/* Apply 2D spatial filter on a single element of @p in at coordinates @p coord + * + * - filter sizes have to be odd number + * - Row major order of filter assumed + * - TO_ZERO rounding policy assumed + * - SATURATE convert policy assumed + */ +template +void apply_2d_spatial_filter(Coordinates coord, const SimpleTensor &src, SimpleTensor &dst, const TensorShape &filter_shape, const V *filter_itr, double scale, BorderMode border_mode, + T constant_border_value = T(0)) +{ + double val = 0.; + const int x = coord.x(); + const int y = coord.y(); + for(int j = y - static_cast(filter_shape[1] / 2); j <= y + static_cast(filter_shape[1] / 2); ++j) + { + for(int i = x - static_cast(filter_shape[0] / 2); i <= x + static_cast(filter_shape[0] / 2); ++i) + { + coord.set(0, i); + coord.set(1, j); + val += static_cast(*filter_itr) * tensor_elem_at(src, coord, border_mode, constant_border_value); + ++filter_itr; + } + } + coord.set(0, x); + coord.set(1, y); + dst[coord2index(src.shape(), coord)] = saturate_cast(support::cpp11::trunc(val * scale)); +} RawTensor transpose(const RawTensor &src, int chunk_width = 1); } // namespace validation diff --git a/tests/validation/NEON/Sobel.cpp b/tests/validation/NEON/Sobel.cpp new file mode 100644 index 0000000000..99f9e1ff5d --- /dev/null +++ b/tests/validation/NEON/Sobel.cpp @@ -0,0 +1,284 @@ +/* + * Copyright (c) 2017 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 "arm_compute/core/Types.h" +#include "arm_compute/runtime/NEON/functions/NESobel3x3.h" +#include "arm_compute/runtime/NEON/functions/NESobel5x5.h" +#include "arm_compute/runtime/NEON/functions/NESobel7x7.h" +#include "arm_compute/runtime/Tensor.h" +#include "arm_compute/runtime/TensorAllocator.h" +#include "tests/NEON/Accessor.h" +#include "tests/PaddingCalculator.h" +#include "tests/datasets/BorderModeDataset.h" +#include "tests/datasets/ShapeDatasets.h" +#include "tests/framework/Asserts.h" +#include "tests/framework/Macros.h" +#include "tests/framework/datasets/Datasets.h" +#include "tests/validation/Validation.h" +#include "tests/validation/fixtures/SobelFixture.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +TEST_SUITE(NEON) +TEST_SUITE(Sobel) + +TEST_SUITE(W3x3) +using NESobel3x3Fixture = SobelValidationFixture; + +DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(combine(concat(datasets::Small2DShapes(), datasets::Large2DShapes()), datasets::BorderModes()), framework::dataset::make("Format", + Format::U8)), + shape, border_mode, format) +{ + // Generate a random constant value + std::mt19937 gen(library->seed()); + std::uniform_int_distribution int_dist(0, 255); + const uint8_t constant_border_value = int_dist(gen); + + // Create tensors + Tensor src = create_tensor(shape, data_type_from_format(format)); + Tensor dst_x = create_tensor(shape, DataType::S16); + Tensor dst_y = create_tensor(shape, DataType::S16); + + src.info()->set_format(format); + dst_x.info()->set_format(Format::S16); + dst_y.info()->set_format(Format::S16); + + ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(dst_x.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(dst_y.info()->is_resizable(), framework::LogLevel::ERRORS); + + // Create sobel 3x3 configure function + NESobel3x3 sobel; + sobel.configure(&src, &dst_x, &dst_y, border_mode, constant_border_value); + + // Validate valid region + constexpr BorderSize border_size{ 1 }; + const ValidRegion dst_valid_region = shape_to_valid_region(shape, border_mode == BorderMode::UNDEFINED, border_size); + + validate(dst_x.info()->valid_region(), dst_valid_region); + validate(dst_y.info()->valid_region(), dst_valid_region); + + // Validate padding + PaddingCalculator calculator(shape.x(), 8); + + calculator.set_border_mode(border_mode); + calculator.set_border_size(1); + + const PaddingSize dst_padding = calculator.required_padding(); + + calculator.set_accessed_elements(16); + calculator.set_access_offset(-1); + + const PaddingSize src_padding = calculator.required_padding(); + + validate(src.info()->padding(), src_padding); + validate(dst_x.info()->padding(), dst_padding); + validate(dst_y.info()->padding(), dst_padding); +} + +FIXTURE_DATA_TEST_CASE(RunSmall, NESobel3x3Fixture, framework::DatasetMode::PRECOMMIT, combine(combine(datasets::Small2DShapes(), datasets::BorderModes()), framework::dataset::make("Format", + Format::U8))) +{ + // Validate output + ValidRegion valid_region_x = shape_to_valid_region(_reference.first.shape(), (_border_mode == BorderMode::UNDEFINED), BorderSize(1)); + validate(Accessor(_target.first), _reference.first, valid_region_x); + + ValidRegion valid_region_y = shape_to_valid_region(_reference.second.shape(), (_border_mode == BorderMode::UNDEFINED), BorderSize(1)); + validate(Accessor(_target.second), _reference.second, valid_region_y); +} + +FIXTURE_DATA_TEST_CASE(RunLarge, NESobel3x3Fixture, framework::DatasetMode::NIGHTLY, combine(combine(datasets::Large2DShapes(), datasets::BorderModes()), framework::dataset::make("Format", + Format::U8))) +{ + // Validate output + ValidRegion valid_region_x = shape_to_valid_region(_reference.first.shape(), (_border_mode == BorderMode::UNDEFINED), BorderSize(1)); + validate(Accessor(_target.first), _reference.first, valid_region_x); + + ValidRegion valid_region_y = shape_to_valid_region(_reference.second.shape(), (_border_mode == BorderMode::UNDEFINED), BorderSize(1)); + validate(Accessor(_target.second), _reference.second, valid_region_y); +} +TEST_SUITE_END() + +TEST_SUITE(W5x5) +using NESobel5x5Fixture = SobelValidationFixture; + +DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(combine(concat(datasets::Small2DShapes(), datasets::Large2DShapes()), datasets::BorderModes()), framework::dataset::make("Format", + Format::U8)), + shape, border_mode, format) +{ + // Generate a random constant value + std::mt19937 gen(library->seed()); + std::uniform_int_distribution int_dist(0, 255); + const uint8_t constant_border_value = int_dist(gen); + + // Create tensors + Tensor src = create_tensor(shape, data_type_from_format(format)); + Tensor dst_x = create_tensor(shape, DataType::S16); + Tensor dst_y = create_tensor(shape, DataType::S16); + + src.info()->set_format(format); + dst_x.info()->set_format(Format::S16); + dst_y.info()->set_format(Format::S16); + + ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(dst_x.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(dst_y.info()->is_resizable(), framework::LogLevel::ERRORS); + + // Create sobel 5x5 configure function + NESobel5x5 sobel; + sobel.configure(&src, &dst_x, &dst_y, border_mode, constant_border_value); + + // Validate valid region + constexpr BorderSize border_size{ 2 }; + const ValidRegion dst_valid_region = shape_to_valid_region(shape, border_mode == BorderMode::UNDEFINED, border_size); + + validate(dst_x.info()->valid_region(), dst_valid_region); + validate(dst_y.info()->valid_region(), dst_valid_region); + + // Validate padding + PaddingCalculator calculator(shape.x(), 16); + + calculator.set_border_mode(border_mode); + calculator.set_border_size(2); + + const PaddingSize dst_padding = calculator.required_padding(); + + calculator.set_processed_elements(8); + calculator.set_access_offset(-2); + + const PaddingSize src_padding = calculator.required_padding(); + + validate(src.info()->padding(), src_padding); + validate(dst_x.info()->padding(), dst_padding); + validate(dst_y.info()->padding(), dst_padding); +} + +FIXTURE_DATA_TEST_CASE(RunSmall, NESobel5x5Fixture, framework::DatasetMode::PRECOMMIT, combine(combine(datasets::Small2DShapes(), datasets::BorderModes()), framework::dataset::make("Format", + Format::U8))) +{ + // Validate output + ValidRegion valid_region_x = shape_to_valid_region(_reference.first.shape(), (_border_mode == BorderMode::UNDEFINED), BorderSize(2)); + validate(Accessor(_target.first), _reference.first, valid_region_x); + + ValidRegion valid_region_y = shape_to_valid_region(_reference.second.shape(), (_border_mode == BorderMode::UNDEFINED), BorderSize(2)); + validate(Accessor(_target.second), _reference.second, valid_region_y); +} + +FIXTURE_DATA_TEST_CASE(RunLarge, NESobel5x5Fixture, framework::DatasetMode::NIGHTLY, combine(combine(datasets::Large2DShapes(), datasets::BorderModes()), framework::dataset::make("Format", + Format::U8))) +{ + // Validate output + ValidRegion valid_region_x = shape_to_valid_region(_reference.first.shape(), (_border_mode == BorderMode::UNDEFINED), BorderSize(2)); + validate(Accessor(_target.first), _reference.first, valid_region_x); + + ValidRegion valid_region_y = shape_to_valid_region(_reference.second.shape(), (_border_mode == BorderMode::UNDEFINED), BorderSize(2)); + validate(Accessor(_target.second), _reference.second, valid_region_y); +} +TEST_SUITE_END() + +TEST_SUITE(W7x7) +using NESobel7x7Fixture = SobelValidationFixture; + +DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(combine(concat(datasets::Small2DShapes(), datasets::Large2DShapes()), datasets::BorderModes()), framework::dataset::make("Format", + Format::U8)), + shape, border_mode, format) +{ + // Generate a random constant value + std::mt19937 gen(library->seed()); + std::uniform_int_distribution int_dist(0, 255); + const uint8_t constant_border_value = int_dist(gen); + + // Create tensors + Tensor src = create_tensor(shape, data_type_from_format(format)); + Tensor dst_x = create_tensor(shape, DataType::S32); + Tensor dst_y = create_tensor(shape, DataType::S32); + + src.info()->set_format(format); + dst_x.info()->set_format(Format::S32); + dst_y.info()->set_format(Format::S32); + + ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(dst_x.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(dst_y.info()->is_resizable(), framework::LogLevel::ERRORS); + + // Create sobel 7x7 configure function + NESobel7x7 sobel; + sobel.configure(&src, &dst_x, &dst_y, border_mode, constant_border_value); + + // Validate valid region + constexpr BorderSize border_size{ 3 }; + const ValidRegion dst_valid_region = shape_to_valid_region(shape, border_mode == BorderMode::UNDEFINED, border_size); + + validate(dst_x.info()->valid_region(), dst_valid_region); + validate(dst_y.info()->valid_region(), dst_valid_region); + + // Validate padding + PaddingCalculator calculator(shape.x(), 8); + + calculator.set_border_mode(border_mode); + calculator.set_border_size(3); + + const PaddingSize dst_padding = calculator.required_padding(); + + calculator.set_accessed_elements(16); + calculator.set_access_offset(-3); + + const PaddingSize src_padding = calculator.required_padding(); + + validate(src.info()->padding(), src_padding); + validate(dst_x.info()->padding(), dst_padding); + validate(dst_y.info()->padding(), dst_padding); +} + +FIXTURE_DATA_TEST_CASE(RunSmall, NESobel7x7Fixture, framework::DatasetMode::PRECOMMIT, combine(combine(datasets::Small2DShapes(), datasets::BorderModes()), framework::dataset::make("Format", + Format::U8))) +{ + // Validate output + ValidRegion valid_region_x = shape_to_valid_region(_reference.first.shape(), (_border_mode == BorderMode::UNDEFINED), BorderSize(3)); + validate(Accessor(_target.first), _reference.first, valid_region_x); + + ValidRegion valid_region_y = shape_to_valid_region(_reference.second.shape(), (_border_mode == BorderMode::UNDEFINED), BorderSize(3)); + validate(Accessor(_target.second), _reference.second, valid_region_y); +} + +FIXTURE_DATA_TEST_CASE(RunLarge, NESobel7x7Fixture, framework::DatasetMode::NIGHTLY, combine(combine(datasets::Large2DShapes(), datasets::BorderModes()), framework::dataset::make("Format", + Format::U8))) +{ + // Validate output + ValidRegion valid_region_x = shape_to_valid_region(_reference.first.shape(), (_border_mode == BorderMode::UNDEFINED), BorderSize(3)); + validate(Accessor(_target.first), _reference.first, valid_region_x); + + ValidRegion valid_region_y = shape_to_valid_region(_reference.second.shape(), (_border_mode == BorderMode::UNDEFINED), BorderSize(3)); + validate(Accessor(_target.second), _reference.second, valid_region_y); +} +TEST_SUITE_END() + +TEST_SUITE_END() +TEST_SUITE_END() +} // namespace validation +} // namespace test +} // namespace arm_compute diff --git a/tests/validation/Validation.h b/tests/validation/Validation.h index 85238617d8..b6e7b8e82b 100644 --- a/tests/validation/Validation.h +++ b/tests/validation/Validation.h @@ -211,7 +211,7 @@ void validate(std::vector classified_labels, std::vector +template > void validate(T target, T reference, U tolerance = AbsoluteTolerance()); template diff --git a/tests/validation/fixtures/SobelFixture.h b/tests/validation/fixtures/SobelFixture.h new file mode 100644 index 0000000000..2a592b87f7 --- /dev/null +++ b/tests/validation/fixtures/SobelFixture.h @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2017 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_SOBEL_FIXTURE +#define ARM_COMPUTE_TEST_SOBEL_FIXTURE + +#include "arm_compute/core/TensorShape.h" +#include "arm_compute/core/Types.h" +#include "support/ToolchainSupport.h" +#include "tests/AssetsLibrary.h" +#include "tests/Globals.h" +#include "tests/IAccessor.h" +#include "tests/framework/Asserts.h" +#include "tests/framework/Fixture.h" +#include "tests/validation/CPP/Sobel.h" + +#include + +namespace arm_compute +{ +class CLSobel3x3; +class CLSobel5x5; +class CLSobel7x7; +class NESobel3x3; +class NESobel5x5; +class NESobel7x7; + +namespace test +{ +namespace validation +{ +namespace +{ +template +struct info; + +template <> +struct info +{ + static const Format dst_format = Format::S16; + static const int filter_size = 3; +}; + +template <> +struct info +{ + static const Format dst_format = Format::S16; + static const int filter_size = 3; +}; + +template <> +struct info +{ + static const Format dst_format = Format::S16; + static const int filter_size = 5; +}; + +template <> +struct info +{ + static const Format dst_format = Format::S16; + static const int filter_size = 5; +}; + +template <> +struct info +{ + static const Format dst_format = Format::S32; + static const int filter_size = 7; +}; + +template <> +struct info +{ + static const Format dst_format = Format::S32; + static const int filter_size = 7; +}; +} // namespace + +template +class SobelValidationFixture : public framework::Fixture +{ +public: + template + void setup(TensorShape shape, BorderMode border_mode, Format format) + { + // Generate a random constant value + std::mt19937 gen(library->seed()); + std::uniform_int_distribution int_dist(0, 255); + const uint8_t constant_border_value = int_dist(gen); + + _border_mode = border_mode; + _target = compute_target(shape, border_mode, format, constant_border_value); + _reference = compute_reference(shape, info::filter_size, border_mode, format, constant_border_value); + } + +protected: + template + void fill(V &&tensor) + { + library->fill_tensor_uniform(tensor, 0); + } + + std::pair compute_target(const TensorShape &shape, BorderMode border_mode, Format format, uint8_t constant_border_value) + { + // Create tensors + TensorType src = create_tensor(shape, data_type_from_format(format)); + TensorType dst_x = create_tensor(shape, data_type_from_format(info::dst_format)); + TensorType dst_y = create_tensor(shape, data_type_from_format(info::dst_format)); + + src.info()->set_format(format); + dst_x.info()->set_format(info::dst_format); + dst_y.info()->set_format(info::dst_format); + + FunctionType sobel; + sobel.configure(&src, &dst_x, &dst_y, border_mode, constant_border_value); + + ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(dst_x.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(dst_y.info()->is_resizable(), framework::LogLevel::ERRORS); + + // Allocate tensors + src.allocator()->allocate(); + dst_x.allocator()->allocate(); + dst_y.allocator()->allocate(); + + ARM_COMPUTE_EXPECT(!src.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(!dst_x.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(!dst_y.info()->is_resizable(), framework::LogLevel::ERRORS); + + // Fill tensors + fill(AccessorType(src)); + + // Compute function + sobel.run(); + + return std::make_pair(std::move(dst_x), std::move(dst_y)); + } + + std::pair, SimpleTensor> compute_reference(const TensorShape &shape, int filter_size, BorderMode border_mode, Format format, uint8_t constant_border_value) + { + // Create reference + SimpleTensor src{ shape, format }; + + // Fill reference + fill(src); + + return reference::sobel(src, filter_size, border_mode, constant_border_value); + } + + BorderMode _border_mode{ BorderMode::UNDEFINED }; + std::pair _target{}; + std::pair, SimpleTensor> _reference{}; +}; +} // namespace validation +} // namespace test +} // namespace arm_compute +#endif /* ARM_COMPUTE_TEST_SOBEL_FIXTURE */ diff --git a/tests/validation_old/CL/Sobel3x3.cpp b/tests/validation_old/CL/Sobel3x3.cpp deleted file mode 100644 index cb4e318736..0000000000 --- a/tests/validation_old/CL/Sobel3x3.cpp +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Copyright (c) 2017 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 "CL/CLAccessor.h" -#include "PaddingCalculator.h" -#include "Utils.h" -#include "tests/AssetsLibrary.h" -#include "tests/Globals.h" -#include "tests/validation_old/Datasets.h" -#include "tests/validation_old/Reference.h" -#include "tests/validation_old/Validation.h" -#include "tests/validation_old/ValidationUserConfiguration.h" -#include "utils/TypePrinter.h" - -#include "arm_compute/core/Helpers.h" -#include "arm_compute/core/Types.h" -#include "arm_compute/runtime/CL/CLSubTensor.h" -#include "arm_compute/runtime/CL/CLTensor.h" -#include "arm_compute/runtime/CL/CLTensorAllocator.h" -#include "arm_compute/runtime/CL/functions/CLSobel3x3.h" - -#include "tests/validation_old/boost_wrapper.h" - -#include -#include - -using namespace arm_compute; -using namespace arm_compute::test; -using namespace arm_compute::test::validation; - -namespace -{ -constexpr unsigned int filter_size = 3; /** Size of the kernel/filter in number of elements. */ -constexpr BorderSize border_size(filter_size / 2); /** Border size of the kernel/filter around its central element. */ - -/** Compute CL Sobel 3x3 function. - * - * @param[in] shape Shape of the input and output tensors. - * @param[in] border_mode BorderMode used by the input tensor - * @param[in] constant_border_value Constant to use if @p border_mode == CONSTANT - * - * @return Computed output tensor. - */ -std::pair compute_sobel_3x3(const TensorShape &shape, BorderMode border_mode, uint8_t constant_border_value) -{ - // Create tensors - CLTensor src = create_tensor(shape, DataType::U8); - CLTensor dst_x = create_tensor(shape, DataType::S16); - CLTensor dst_y = create_tensor(shape, DataType::S16); - - src.info()->set_format(Format::U8); - dst_x.info()->set_format(Format::S16); - dst_y.info()->set_format(Format::S16); - - // Create sobel image configure function - CLSobel3x3 sobel_3x3; - sobel_3x3.configure(&src, &dst_x, &dst_y, border_mode, constant_border_value); - - // Allocate tensors - src.allocator()->allocate(); - dst_x.allocator()->allocate(); - dst_y.allocator()->allocate(); - - BOOST_TEST(!src.info()->is_resizable()); - BOOST_TEST(!dst_x.info()->is_resizable()); - BOOST_TEST(!dst_y.info()->is_resizable()); - - // Fill tensors - library->fill_tensor_uniform(CLAccessor(src), 0); - - // Compute function - sobel_3x3.run(); - - return std::make_pair(std::move(dst_x), std::move(dst_y)); -} -} // namespace - -#ifndef DOXYGEN_SKIP_THIS -BOOST_AUTO_TEST_SUITE(CL) -BOOST_AUTO_TEST_SUITE(Sobel3x3) - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, (SmallShapes() + LargeShapes()) * BorderModes(), shape, border_mode) -{ - // Create tensors - CLTensor src = create_tensor(shape, DataType::U8); - CLTensor dst_x = create_tensor(shape, DataType::S16); - CLTensor dst_y = create_tensor(shape, DataType::S16); - - src.info()->set_format(Format::U8); - dst_x.info()->set_format(Format::S16); - dst_y.info()->set_format(Format::S16); - - BOOST_TEST(src.info()->is_resizable()); - BOOST_TEST(dst_x.info()->is_resizable()); - BOOST_TEST(dst_y.info()->is_resizable()); - - // Create sobel 3x3 configure function - CLSobel3x3 sobel_3x3; - sobel_3x3.configure(&src, &dst_x, &dst_y, border_mode); - - // Validate valid region - const ValidRegion src_valid_region = shape_to_valid_region(shape); - const ValidRegion dst_valid_region = shape_to_valid_region(shape, border_mode == BorderMode::UNDEFINED, border_size); - - validate(src.info()->valid_region(), src_valid_region); - validate(dst_x.info()->valid_region(), dst_valid_region); - validate(dst_y.info()->valid_region(), dst_valid_region); - - // Validate padding - PaddingCalculator calculator(shape.x(), 8); - - calculator.set_border_mode(border_mode); - calculator.set_border_size(1); - - const PaddingSize dst_padding = calculator.required_padding(); - - calculator.set_accessed_elements(16); - calculator.set_access_offset(-1); - - const PaddingSize src_padding = calculator.required_padding(); - - validate(src.info()->padding(), src_padding); - validate(dst_x.info()->padding(), dst_padding); - validate(dst_y.info()->padding(), dst_padding); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * BorderModes(), shape, border_mode) -{ - uint8_t constant_border_value = 0; - - // Generate a random constant value if border_mode is constant - if(border_mode == BorderMode::CONSTANT) - { - std::mt19937 gen(user_config.seed.get()); - std::uniform_int_distribution distribution(0, 255); - constant_border_value = distribution(gen); - } - - // Compute function - std::pair dst = compute_sobel_3x3(shape, border_mode, constant_border_value); - - // Compute reference - std::pair ref_dst = Reference::compute_reference_sobel_3x3(shape, border_mode, constant_border_value); - - // Calculate valid region - const ValidRegion valid_region = shape_to_valid_region(shape, border_mode == BorderMode::UNDEFINED, border_size); - - // Validate output - validate(CLAccessor(dst.first), ref_dst.first, valid_region); - validate(CLAccessor(dst.second), ref_dst.second, valid_region); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, LargeShapes() * BorderModes(), shape, border_mode) -{ - uint8_t constant_border_value = 0; - - // Generate a random constant value if border_mode is constant - if(border_mode == BorderMode::CONSTANT) - { - std::mt19937 gen(user_config.seed.get()); - std::uniform_int_distribution distribution(0, 255); - constant_border_value = distribution(gen); - } - - // Compute function - std::pair dst = compute_sobel_3x3(shape, border_mode, constant_border_value); - - // Compute reference - std::pair ref_dst = Reference::compute_reference_sobel_3x3(shape, border_mode, constant_border_value); - - // Calculate valid region - const ValidRegion valid_region = shape_to_valid_region(shape, border_mode == BorderMode::UNDEFINED, border_size); - - // Validate output - validate(CLAccessor(dst.first), ref_dst.first, valid_region); - validate(CLAccessor(dst.second), ref_dst.second, valid_region); -} - -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -#endif /* DOXYGEN_SKIP_THIS */ diff --git a/tests/validation_old/CL/Sobel5x5.cpp b/tests/validation_old/CL/Sobel5x5.cpp deleted file mode 100644 index d035027218..0000000000 --- a/tests/validation_old/CL/Sobel5x5.cpp +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Copyright (c) 2017 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 "CL/CLAccessor.h" -#include "PaddingCalculator.h" -#include "Utils.h" -#include "tests/AssetsLibrary.h" -#include "tests/Globals.h" -#include "tests/validation_old/Datasets.h" -#include "tests/validation_old/Reference.h" -#include "tests/validation_old/Validation.h" -#include "tests/validation_old/ValidationUserConfiguration.h" -#include "utils/TypePrinter.h" - -#include "arm_compute/core/Helpers.h" -#include "arm_compute/core/Types.h" -#include "arm_compute/runtime/CL/CLSubTensor.h" -#include "arm_compute/runtime/CL/CLTensor.h" -#include "arm_compute/runtime/CL/CLTensorAllocator.h" -#include "arm_compute/runtime/CL/functions/CLSobel5x5.h" - -#include "tests/validation_old/boost_wrapper.h" - -#include -#include - -using namespace arm_compute; -using namespace arm_compute::test; -using namespace arm_compute::test::validation; - -namespace -{ -constexpr unsigned int filter_size = 5; /** Size of the kernel/filter in number of elements. */ -constexpr BorderSize border_size(filter_size / 2); /** Border size of the kernel/filter around its central element. */ - -/** Compute CL Sobel 5x5 function. - * - * @param[in] shape Shape of the input and output tensors. - * @param[in] border_mode BorderMode used by the input tensor - * @param[in] constant_border_value Constant to use if @p border_mode == CONSTANT - * - * @return Computed output tensor. - */ -std::pair compute_sobel_5x5(const TensorShape &shape, BorderMode border_mode, uint8_t constant_border_value) -{ - // Create tensors - CLTensor src = create_tensor(shape, DataType::U8); - CLTensor dst_x = create_tensor(shape, DataType::S16); - CLTensor dst_y = create_tensor(shape, DataType::S16); - - src.info()->set_format(Format::U8); - dst_x.info()->set_format(Format::S16); - dst_y.info()->set_format(Format::S16); - - // Create sobel image configure function - CLSobel5x5 sobel_5x5; - sobel_5x5.configure(&src, &dst_x, &dst_y, border_mode, constant_border_value); - - // Allocate tensors - src.allocator()->allocate(); - dst_x.allocator()->allocate(); - dst_y.allocator()->allocate(); - - BOOST_TEST(!src.info()->is_resizable()); - BOOST_TEST(!dst_x.info()->is_resizable()); - BOOST_TEST(!dst_y.info()->is_resizable()); - - // Fill tensors - library->fill_tensor_uniform(CLAccessor(src), 0); - - // Compute function - sobel_5x5.run(); - - return std::make_pair(std::move(dst_x), std::move(dst_y)); -} -} // namespace - -#ifndef DOXYGEN_SKIP_THIS -BOOST_AUTO_TEST_SUITE(CL) -BOOST_AUTO_TEST_SUITE(Sobel5x5) - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, (SmallShapes() + LargeShapes()) * BorderModes(), shape, border_mode) -{ - // Create tensors - CLTensor src = create_tensor(shape, DataType::U8); - CLTensor dst_x = create_tensor(shape, DataType::S16); - CLTensor dst_y = create_tensor(shape, DataType::S16); - - src.info()->set_format(Format::U8); - dst_x.info()->set_format(Format::S16); - dst_y.info()->set_format(Format::S16); - - BOOST_TEST(src.info()->is_resizable()); - BOOST_TEST(dst_x.info()->is_resizable()); - BOOST_TEST(dst_y.info()->is_resizable()); - - // Create sobel 5x5 configure function - CLSobel5x5 sobel_5x5; - sobel_5x5.configure(&src, &dst_x, &dst_y, border_mode); - - // Validate valid region - const ValidRegion src_valid_region = shape_to_valid_region(shape); - const ValidRegion dst_valid_region = shape_to_valid_region(shape, border_mode == BorderMode::UNDEFINED, border_size); - - validate(src.info()->valid_region(), src_valid_region); - validate(dst_x.info()->valid_region(), dst_valid_region); - validate(dst_y.info()->valid_region(), dst_valid_region); - - // Validate padding - PaddingCalculator calculator(shape.x(), 8); - calculator.set_border_mode(border_mode); - calculator.set_border_size(2); - - const PaddingSize dst_padding = calculator.required_padding(); - - calculator.set_accessed_elements(16); - calculator.set_access_offset(-2); - - const PaddingSize src_padding = calculator.required_padding(); - - validate(src.info()->padding(), src_padding); - validate(dst_x.info()->padding(), dst_padding); - validate(dst_y.info()->padding(), dst_padding); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * BorderModes(), shape, border_mode) -{ - uint8_t constant_border_value = 0; - - // Generate a random constant value if border_mode is constant - if(border_mode == BorderMode::CONSTANT) - { - std::mt19937 gen(user_config.seed.get()); - std::uniform_int_distribution distribution(0, 255); - constant_border_value = distribution(gen); - } - - // Compute function - std::pair dst = compute_sobel_5x5(shape, border_mode, constant_border_value); - - // Compute reference - std::pair ref_dst = Reference::compute_reference_sobel_5x5(shape, border_mode, constant_border_value); - - // Calculate valid region - const ValidRegion valid_region = shape_to_valid_region(shape, border_mode == BorderMode::UNDEFINED, border_size); - - // Validate output - validate(CLAccessor(dst.first), ref_dst.first, valid_region); - validate(CLAccessor(dst.second), ref_dst.second, valid_region); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, LargeShapes() * BorderModes(), shape, border_mode) -{ - uint8_t constant_border_value = 0; - - // Generate a random constant value if border_mode is constant - if(border_mode == BorderMode::CONSTANT) - { - std::mt19937 gen(user_config.seed.get()); - std::uniform_int_distribution distribution(0, 255); - constant_border_value = distribution(gen); - } - - // Compute function - std::pair dst = compute_sobel_5x5(shape, border_mode, constant_border_value); - - // Compute reference - std::pair ref_dst = Reference::compute_reference_sobel_5x5(shape, border_mode, constant_border_value); - - // Calculate valid region - const ValidRegion valid_region = shape_to_valid_region(shape, border_mode == BorderMode::UNDEFINED, border_size); - - // Validate output - validate(CLAccessor(dst.first), ref_dst.first, valid_region); - validate(CLAccessor(dst.second), ref_dst.second, valid_region); -} - -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -#endif /* DOXYGEN_SKIP_THIS */ diff --git a/tests/validation_old/NEON/Sobel3x3.cpp b/tests/validation_old/NEON/Sobel3x3.cpp deleted file mode 100644 index 302364048a..0000000000 --- a/tests/validation_old/NEON/Sobel3x3.cpp +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Copyright (c) 2017 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 "NEON/Accessor.h" -#include "Utils.h" -#include "tests/AssetsLibrary.h" -#include "tests/Globals.h" -#include "tests/validation_old/Datasets.h" -#include "tests/validation_old/Reference.h" -#include "tests/validation_old/Validation.h" -#include "tests/validation_old/ValidationUserConfiguration.h" -#include "utils/TypePrinter.h" - -#include "arm_compute/core/Helpers.h" -#include "arm_compute/core/Types.h" -#include "arm_compute/runtime/NEON/functions/NESobel3x3.h" -#include "arm_compute/runtime/Tensor.h" -#include "arm_compute/runtime/TensorAllocator.h" - -#include "PaddingCalculator.h" -#include "tests/validation_old/boost_wrapper.h" - -#include -#include - -using namespace arm_compute; -using namespace arm_compute::test; -using namespace arm_compute::test::validation; - -namespace -{ -constexpr unsigned int filter_size = 3; /** Size of the kernel/filter in number of elements. */ -constexpr BorderSize border_size(filter_size / 2); /** Border size of the kernel/filter around its central element. */ - -/** Compute Neon Sobel 3x3 function. - * - * @param[in] shape Shape of the input and output tensors. - * @param[in] border_mode BorderMode used by the input tensor - * @param[in] constant_border_value Constant to use if @p border_mode == CONSTANT - * - * @return Computed output tensor. - */ -std::pair compute_sobel_3x3(const TensorShape &shape, BorderMode border_mode, uint8_t constant_border_value) -{ - // Create tensors - Tensor src = create_tensor(shape, DataType::U8); - Tensor dst_x = create_tensor(shape, DataType::S16); - Tensor dst_y = create_tensor(shape, DataType::S16); - - src.info()->set_format(Format::U8); - dst_x.info()->set_format(Format::S16); - dst_y.info()->set_format(Format::S16); - - // Create sobel image configure function - NESobel3x3 sobel_3x3; - sobel_3x3.configure(&src, &dst_x, &dst_y, border_mode, constant_border_value); - - // Allocate tensors - src.allocator()->allocate(); - dst_x.allocator()->allocate(); - dst_y.allocator()->allocate(); - - BOOST_TEST(!src.info()->is_resizable()); - BOOST_TEST(!dst_x.info()->is_resizable()); - BOOST_TEST(!dst_y.info()->is_resizable()); - - // Fill tensors - library->fill_tensor_uniform(Accessor(src), 0); - - // Compute function - sobel_3x3.run(); - - return std::make_pair(std::move(dst_x), std::move(dst_y)); -} -} // namespace - -#ifndef DOXYGEN_SKIP_THIS -BOOST_AUTO_TEST_SUITE(NEON) -BOOST_AUTO_TEST_SUITE(Sobel3x3) - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, (SmallShapes() + LargeShapes()) * BorderModes(), shape, border_mode) -{ - // Create tensors - Tensor src = create_tensor(shape, DataType::U8); - Tensor dst_x = create_tensor(shape, DataType::S16); - Tensor dst_y = create_tensor(shape, DataType::S16); - - src.info()->set_format(Format::U8); - dst_x.info()->set_format(Format::S16); - dst_y.info()->set_format(Format::S16); - - BOOST_TEST(src.info()->is_resizable()); - BOOST_TEST(dst_x.info()->is_resizable()); - BOOST_TEST(dst_y.info()->is_resizable()); - - // Create sobel 3x3 configure function - NESobel3x3 sobel_3x3; - sobel_3x3.configure(&src, &dst_x, &dst_y, border_mode); - - // Validate valid region - const ValidRegion src_valid_region = shape_to_valid_region(shape); - const ValidRegion dst_valid_region = shape_to_valid_region(shape, border_mode == BorderMode::UNDEFINED, border_size); - - validate(src.info()->valid_region(), src_valid_region); - validate(dst_x.info()->valid_region(), dst_valid_region); - validate(dst_y.info()->valid_region(), dst_valid_region); - - // Validate padding - PaddingCalculator calculator(shape.x(), 8); - - calculator.set_border_mode(border_mode); - calculator.set_border_size(1); - - const PaddingSize dst_padding = calculator.required_padding(); - - calculator.set_accessed_elements(16); - calculator.set_access_offset(-1); - - const PaddingSize src_padding = calculator.required_padding(); - - validate(src.info()->padding(), src_padding); - validate(dst_x.info()->padding(), dst_padding); - validate(dst_y.info()->padding(), dst_padding); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * BorderModes(), shape, border_mode) -{ - uint8_t constant_border_value = 0; - - // Generate a random constant value if border_mode is constant - if(border_mode == BorderMode::CONSTANT) - { - std::mt19937 gen(user_config.seed.get()); - std::uniform_int_distribution distribution(0, 255); - constant_border_value = distribution(gen); - } - - // Compute function - std::pair dst = compute_sobel_3x3(shape, border_mode, constant_border_value); - - // Compute reference - std::pair ref_dst = Reference::compute_reference_sobel_3x3(shape, border_mode, constant_border_value); - - // Calculate valid region - const ValidRegion valid_region = shape_to_valid_region(shape, border_mode == BorderMode::UNDEFINED, border_size); - - // Validate output - validate(Accessor(dst.first), ref_dst.first, valid_region); - validate(Accessor(dst.second), ref_dst.second, valid_region); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, LargeShapes() * BorderModes(), shape, border_mode) -{ - uint8_t constant_border_value = 0; - - // Generate a random constant value if border_mode is constant - if(border_mode == BorderMode::CONSTANT) - { - std::mt19937 gen(user_config.seed.get()); - std::uniform_int_distribution distribution(0, 255); - constant_border_value = distribution(gen); - } - - // Compute function - std::pair dst = compute_sobel_3x3(shape, border_mode, constant_border_value); - - // Compute reference - std::pair ref_dst = Reference::compute_reference_sobel_3x3(shape, border_mode, constant_border_value); - - // Calculate valid region - const ValidRegion valid_region = shape_to_valid_region(shape, border_mode == BorderMode::UNDEFINED, border_size); - - // Validate output - validate(Accessor(dst.first), ref_dst.first, valid_region); - validate(Accessor(dst.second), ref_dst.second, valid_region); -} - -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -#endif /* DOXYGEN_SKIP_THIS */ diff --git a/tests/validation_old/NEON/Sobel5x5.cpp b/tests/validation_old/NEON/Sobel5x5.cpp deleted file mode 100644 index e9835b6095..0000000000 --- a/tests/validation_old/NEON/Sobel5x5.cpp +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Copyright (c) 2017 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 "NEON/Accessor.h" -#include "PaddingCalculator.h" -#include "Utils.h" -#include "tests/AssetsLibrary.h" -#include "tests/Globals.h" -#include "tests/validation_old/Datasets.h" -#include "tests/validation_old/Reference.h" -#include "tests/validation_old/Validation.h" -#include "tests/validation_old/ValidationUserConfiguration.h" -#include "utils/TypePrinter.h" - -#include "arm_compute/core/Helpers.h" -#include "arm_compute/core/Types.h" -#include "arm_compute/runtime/NEON/functions/NESobel5x5.h" -#include "arm_compute/runtime/Tensor.h" -#include "arm_compute/runtime/TensorAllocator.h" - -#include "tests/validation_old/boost_wrapper.h" - -#include -#include - -using namespace arm_compute; -using namespace arm_compute::test; -using namespace arm_compute::test::validation; - -namespace -{ -constexpr unsigned int filter_size = 5; /** Size of the kernel/filter in number of elements. */ -constexpr BorderSize border_size(filter_size / 2); /** Border size of the kernel/filter around its central element. */ - -/** Compute Neon Sobel 5x5 function. - * - * @param[in] shape Shape of the input and output tensors. - * @param[in] border_mode BorderMode used by the input tensor - * @param[in] constant_border_value Constant to use if @p border_mode == CONSTANT - * - * @return Computed output tensor. - */ -std::pair compute_sobel_5x5(const TensorShape &shape, BorderMode border_mode, uint8_t constant_border_value) -{ - // Create tensors - Tensor src = create_tensor(shape, DataType::U8); - Tensor dst_x = create_tensor(shape, DataType::S16); - Tensor dst_y = create_tensor(shape, DataType::S16); - - src.info()->set_format(Format::U8); - dst_x.info()->set_format(Format::S16); - dst_y.info()->set_format(Format::S16); - - // Create sobel image configure function - NESobel5x5 sobel_5x5; - sobel_5x5.configure(&src, &dst_x, &dst_y, border_mode, constant_border_value); - - // Allocate tensors - src.allocator()->allocate(); - dst_x.allocator()->allocate(); - dst_y.allocator()->allocate(); - - BOOST_TEST(!src.info()->is_resizable()); - BOOST_TEST(!dst_x.info()->is_resizable()); - BOOST_TEST(!dst_y.info()->is_resizable()); - - // Fill tensors - library->fill_tensor_uniform(Accessor(src), 0); - - // Compute function - sobel_5x5.run(); - - return std::make_pair(std::move(dst_x), std::move(dst_y)); -} -} // namespace - -#ifndef DOXYGEN_SKIP_THIS -BOOST_AUTO_TEST_SUITE(NEON) -BOOST_AUTO_TEST_SUITE(Sobel5x5) - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, (SmallShapes() + LargeShapes()) * BorderModes(), shape, border_mode) -{ - // Create tensors - Tensor src = create_tensor(shape, DataType::U8); - Tensor dst_x = create_tensor(shape, DataType::S16); - Tensor dst_y = create_tensor(shape, DataType::S16); - - src.info()->set_format(Format::U8); - dst_x.info()->set_format(Format::S16); - dst_y.info()->set_format(Format::S16); - - BOOST_TEST(src.info()->is_resizable()); - BOOST_TEST(dst_x.info()->is_resizable()); - BOOST_TEST(dst_y.info()->is_resizable()); - - // Create sobel 5x5 configure function - NESobel5x5 sobel_5x5; - sobel_5x5.configure(&src, &dst_x, &dst_y, border_mode); - - // Validate valid region - const ValidRegion src_valid_region = shape_to_valid_region(shape); - const ValidRegion dst_valid_region = shape_to_valid_region(shape, border_mode == BorderMode::UNDEFINED, border_size); - - validate(src.info()->valid_region(), src_valid_region); - validate(dst_x.info()->valid_region(), dst_valid_region); - validate(dst_y.info()->valid_region(), dst_valid_region); - - // Validate padding - PaddingCalculator calculator(shape.x(), 16); - - calculator.set_border_mode(border_mode); - calculator.set_border_size(2); - - const PaddingSize dst_padding = calculator.required_padding(); - - calculator.set_processed_elements(8); - calculator.set_access_offset(-2); - - const PaddingSize src_padding = calculator.required_padding(); - - validate(src.info()->padding(), src_padding); - validate(dst_x.info()->padding(), dst_padding); - validate(dst_y.info()->padding(), dst_padding); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * BorderModes(), shape, border_mode) -{ - uint8_t constant_border_value = 0; - - // Generate a random constant value if border_mode is constant - if(border_mode == BorderMode::CONSTANT) - { - std::mt19937 gen(user_config.seed.get()); - std::uniform_int_distribution distribution(0, 255); - constant_border_value = distribution(gen); - } - - // Compute function - std::pair dst = compute_sobel_5x5(shape, border_mode, constant_border_value); - - // Compute reference - std::pair ref_dst = Reference::compute_reference_sobel_5x5(shape, border_mode, constant_border_value); - - // Calculate valid region - const ValidRegion valid_region = shape_to_valid_region(shape, border_mode == BorderMode::UNDEFINED, border_size); - - // Validate output - validate(Accessor(dst.first), ref_dst.first, valid_region); - validate(Accessor(dst.second), ref_dst.second, valid_region); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, LargeShapes() * BorderModes(), shape, border_mode) -{ - uint8_t constant_border_value = 0; - - // Generate a random constant value if border_mode is constant - if(border_mode == BorderMode::CONSTANT) - { - std::mt19937 gen(user_config.seed.get()); - std::uniform_int_distribution distribution(0, 255); - constant_border_value = distribution(gen); - } - - // Compute function - std::pair dst = compute_sobel_5x5(shape, border_mode, constant_border_value); - - // Compute reference - std::pair ref_dst = Reference::compute_reference_sobel_5x5(shape, border_mode, constant_border_value); - - // Calculate valid region - const ValidRegion valid_region = shape_to_valid_region(shape, border_mode == BorderMode::UNDEFINED, border_size); - - // Validate output - validate(Accessor(dst.first), ref_dst.first, valid_region); - validate(Accessor(dst.second), ref_dst.second, valid_region); -} - -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -#endif /* DOXYGEN_SKIP_THIS */ diff --git a/tests/validation_old/Reference.cpp b/tests/validation_old/Reference.cpp index 32e0212596..0331ccefca 100644 --- a/tests/validation_old/Reference.cpp +++ b/tests/validation_old/Reference.cpp @@ -41,38 +41,6 @@ namespace test { namespace validation { -std::pair Reference::compute_reference_sobel_3x3(const TensorShape &shape, BorderMode border_mode, uint8_t constant_border_value) -{ - // Create reference - RawTensor ref_src(shape, Format::U8); - RawTensor ref_dst_x(shape, Format::S16); - RawTensor ref_dst_y(shape, Format::S16); - - // Fill reference - library->fill_tensor_uniform(ref_src, 0); - - // Compute reference - ReferenceCPP::sobel_3x3(ref_src, ref_dst_x, ref_dst_y, border_mode, constant_border_value); - - return std::make_pair(ref_dst_x, ref_dst_y); -} - -std::pair Reference::compute_reference_sobel_5x5(const TensorShape &shape, BorderMode border_mode, uint8_t constant_border_value) -{ - // Create reference - RawTensor ref_src(shape, Format::U8); - RawTensor ref_dst_x(shape, Format::S16); - RawTensor ref_dst_y(shape, Format::S16); - - // Fill reference - library->fill_tensor_uniform(ref_src, 0); - - // Compute reference - ReferenceCPP::sobel_5x5(ref_src, ref_dst_x, ref_dst_y, border_mode, constant_border_value); - - return std::make_pair(ref_dst_x, ref_dst_y); -} - KeyPointArray Reference::compute_reference_harris_corners(const TensorShape &shape, float threshold, float min_dist, float sensitivity, int32_t gradient_size, int32_t block_size, BorderMode border_mode, uint8_t constant_border_value) { diff --git a/tests/validation_old/Reference.h b/tests/validation_old/Reference.h index 306009df05..7b3de11e01 100644 --- a/tests/validation_old/Reference.h +++ b/tests/validation_old/Reference.h @@ -41,24 +41,6 @@ namespace validation class Reference { public: - /** Compute reference sobel 3x3. - * - * @param[in] shape Shape of the input and output tensors. - * @param[in] border_mode Border mode to use for input tensor - * @param[in] constant_border_value Constant value to use if @p border_mode is constant - * - * @return Computed raw tensors along x and y axis. - */ - static std::pair compute_reference_sobel_3x3(const TensorShape &shape, BorderMode border_mode, uint8_t constant_border_value); - /** Compute reference sobel 5x5. - * - * @param[in] shape Shape of the input and output tensors. - * @param[in] border_mode Border mode to use for input tensor - * @param[in] constant_border_value Constant value to use if @p border_mode is constant - * - * @return Computed raw tensors along x and y axis. - */ - static std::pair compute_reference_sobel_5x5(const TensorShape &shape, BorderMode border_mode, uint8_t constant_border_value); /** Compute reference Harris corners. * * @param[in] shape Shape of input tensor diff --git a/tests/validation_old/ReferenceCPP.cpp b/tests/validation_old/ReferenceCPP.cpp index e10f9065a0..0ea3032d81 100644 --- a/tests/validation_old/ReferenceCPP.cpp +++ b/tests/validation_old/ReferenceCPP.cpp @@ -50,26 +50,6 @@ namespace test { namespace validation { -// Sobel 3x3 -void ReferenceCPP::sobel_3x3(RawTensor &src, RawTensor &dst_x, RawTensor &dst_y, BorderMode border_mode, uint8_t constant_border_value) -{ - ARM_COMPUTE_ERROR_ON(src.data_type() != DataType::U8 || dst_x.data_type() != DataType::S16 || dst_y.data_type() != DataType::S16); - Tensor s(src.shape(), src.data_type(), src.fixed_point_position(), reinterpret_cast(src.data())); - Tensor dx(dst_x.shape(), dst_x.data_type(), dst_x.fixed_point_position(), reinterpret_cast(dst_x.data())); - Tensor dy(dst_y.shape(), dst_y.data_type(), dst_y.fixed_point_position(), reinterpret_cast(dst_y.data())); - tensor_operations::sobel_3x3(s, dx, dy, border_mode, constant_border_value); -} - -// Sobel 5x5 -void ReferenceCPP::sobel_5x5(RawTensor &src, RawTensor &dst_x, RawTensor &dst_y, BorderMode border_mode, uint8_t constant_border_value) -{ - ARM_COMPUTE_ERROR_ON(src.data_type() != DataType::U8 || dst_x.data_type() != DataType::S16 || dst_y.data_type() != DataType::S16); - Tensor s(src.shape(), src.data_type(), src.fixed_point_position(), reinterpret_cast(src.data())); - Tensor dx(dst_x.shape(), dst_x.data_type(), dst_x.fixed_point_position(), reinterpret_cast(dst_x.data())); - Tensor dy(dst_y.shape(), dst_y.data_type(), dst_y.fixed_point_position(), reinterpret_cast(dst_y.data())); - tensor_operations::sobel_5x5(s, dx, dy, border_mode, constant_border_value); -} - // Harris corners void ReferenceCPP::harris_corners(RawTensor &src, RawTensor &Gx, RawTensor &Gy, const RawTensor &candidates, const RawTensor &non_maxima, float threshold, float min_dist, float sensitivity, int32_t gradient_size, int32_t block_size, KeyPointArray &corners, BorderMode border_mode, uint8_t constant_border_value) diff --git a/tests/validation_old/ReferenceCPP.h b/tests/validation_old/ReferenceCPP.h index 3203196b5d..039d0b627e 100644 --- a/tests/validation_old/ReferenceCPP.h +++ b/tests/validation_old/ReferenceCPP.h @@ -44,26 +44,6 @@ namespace validation class ReferenceCPP final : public Reference { public: - /** Function to compute reference sobel 3x3. - * - * @param[in] src Input tensor. - * @param[in] dst_x Result tensor along x axis - * @param[in] dst_y Result tensor along y axis - * @param[in] border_mode Border mode to use for input tensor - * @param[in] constant_border_value Constant value to use if @p border_mode is constant - * - */ - static void sobel_3x3(RawTensor &src, RawTensor &dst_x, RawTensor &dst_y, BorderMode border_mode, uint8_t constant_border_value); - /** Function to compute reference sobel 5x5. - * - * @param[in] src Input tensor. - * @param[in] dst_x Result tensor along x axis - * @param[in] dst_y Result tensor along y axis - * @param[in] border_mode Border mode to use for input tensor - * @param[in] constant_border_value Constant value to use if @p border_mode is constant - * - */ - static void sobel_5x5(RawTensor &src, RawTensor &dst_x, RawTensor &dst_y, BorderMode border_mode, uint8_t constant_border_value); /** Function to compute reference Harris corners. * * @param[in] src Input tensor diff --git a/utils/TypePrinter.h b/utils/TypePrinter.h index 30592fff55..6e2d7e24f3 100644 --- a/utils/TypePrinter.h +++ b/utils/TypePrinter.h @@ -389,6 +389,13 @@ inline ::std::ostream &operator<<(::std::ostream &os, const Format &format) return os; } +inline std::string to_string(const Format &format) +{ + std::stringstream str; + str << format; + return str.str(); +} + /** Formatted output of the Channel type. */ inline ::std::ostream &operator<<(::std::ostream &os, const Channel &channel) { -- cgit v1.2.1