From 5e25b4848a9253ae9b0be7927ce67167ccc2479f Mon Sep 17 00:00:00 2001 From: harsh-4 Date: Sat, 3 Apr 2021 10:20:36 +0530 Subject: [PATCH 1/9] Add distance transform functionality --- example/euclidean_distance_transform.cpp | 81 +++ .../image_processing/distance_transform.hpp | 517 ++++++++++++++++++ test/core/image_processing/CMakeLists.txt | 3 +- test/core/image_processing/Jamfile | 1 + .../image_processing/distance_transform.cpp | 480 ++++++++++++++++ 5 files changed, 1081 insertions(+), 1 deletion(-) create mode 100644 example/euclidean_distance_transform.cpp create mode 100644 include/boost/gil/image_processing/distance_transform.hpp create mode 100644 test/core/image_processing/distance_transform.cpp diff --git a/example/euclidean_distance_transform.cpp b/example/euclidean_distance_transform.cpp new file mode 100644 index 0000000000..2869ccbe9e --- /dev/null +++ b/example/euclidean_distance_transform.cpp @@ -0,0 +1,81 @@ +// +// Copyright 2021 Harsit Pant +// +// Use, modification and distribution are subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#include +#include +#include +#include + +#include + +namespace gil = boost::gil; + +/// calculates distance transform based on euclidean distance measurement formulae. + +int main(int argc, char* argv[]) +{ + if (argc != 6) + { + std::cerr << "usage: " << argv[0] << " " + " "; + return -1; + } + + std::string dist_from = argv[3]; + std::string dist_type = argv[4]; + std::string mask_size = argv[5]; + + gil::gray8_image_t input; + gil::read_image(argv[1], input, gil::png_tag{}); + gil::gray8_image_t output(input.dimensions()); + + if (dist_from == "on_pixels" && dist_type == "euclidean_approximation" && mask_size == "three") + { + distance_transform(view(input), view(output), gil::distance_from::on_pixels, + gil::distance_type::euclidean_approximation, gil::mask_size::three); + gil::write_view(argv[2], view(output), gil::png_tag{}); + } + + else if (dist_from == "off_pixels" && dist_type == "euclidean_approximation" && mask_size == "three") + { + distance_transform(view(input), view(output), gil::distance_from::off_pixels, + gil::distance_type::euclidean_approximation, gil::mask_size::three); + gil::write_view(argv[2], view(output), gil::png_tag{}); + } + + else if (dist_from == "on_pixels" && dist_type == "euclidean_approximation" && mask_size == "five") + { + distance_transform(view(input), view(output), gil::distance_from::on_pixels, + gil::distance_type::euclidean_approximation, gil::mask_size::five); + gil::write_view(argv[2], view(output), gil::png_tag{}); + } + + else if (dist_from == "off_pixels" && dist_type == "euclidean_approximation" && mask_size == "five") + { + distance_transform(view(input), view(output), gil::distance_from::off_pixels, + gil::distance_type::euclidean_approximation, gil::mask_size::five); + gil::write_view(argv[2], view(output), gil::png_tag{}); + } + + else if (dist_from == "on_pixels" && dist_type == "precise_euclidean" && mask_size == "not_applicable") + { + distance_transform(view(input), view(output), gil::distance_from::on_pixels, + gil::distance_type::precise_euclidean, gil::mask_size::not_applicable); + gil::write_view(argv[2], view(output), gil::png_tag{}); + } + + else if (dist_from == "off_pixels" && dist_type == "precise_euclidean" && mask_size == "not_applicable") + { + distance_transform(view(input), view(output), gil::distance_from::off_pixels, + gil::distance_type::precise_euclidean, gil::mask_size::not_applicable); + gil::write_view(argv[2], view(output), gil::png_tag{}); + } + else + { + std::cerr << "Incorrect options used."; + } +} diff --git a/include/boost/gil/image_processing/distance_transform.hpp b/include/boost/gil/image_processing/distance_transform.hpp new file mode 100644 index 0000000000..188ead88f1 --- /dev/null +++ b/include/boost/gil/image_processing/distance_transform.hpp @@ -0,0 +1,517 @@ +// +// Copyright 2021 Harsit Pant +// +// Use, modification and distribution are subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#ifndef BOOST_GIL_IMAGE_PROCESSING_DISTANCE_TRANSFORM_HPP +#define BOOST_GIL_IMAGE_PROCESSING_DISTANCE_TRANSFORM_HPP + +#include +#include +#include +#include + +#include + +#include +#include +#include + +namespace boost { namespace gil { + +namespace distance_type{ +struct euclidean_approximation_t {}; +struct manhattan_t {}; +struct chessboard_t {}; +struct precise_euclidean_t {}; + +static euclidean_approximation_t euclidean_approximation; +static manhattan_t manhattan; +static chessboard_t chessboard; +static precise_euclidean_t precise_euclidean; + +/// \breif Checks if distance_type used exists. +template +struct check_distance_type +{ + static const bool value = std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value; +}; +} + +namespace mask_size { +struct three_t {}; +struct five_t {}; +struct not_applicable_t {}; + +static three_t three; +static five_t five; +static not_applicable_t not_applicable; + +/// \breif Checks if mask_size used exists. +template +struct check_mask_size +{ + static const bool value = std::is_same::value || + std::is_same::value || + std::is_same::value; +}; +} + +enum class distance_from +{ + off_pixels, + on_pixels +}; + +namespace detail { + +/// \breif Checks compatiblity of distance_type and mask_size used together. +template +struct dt_parameters_are_compatible +{ + static const bool value = true; +}; + +template +struct dt_parameters_are_compatible +{ + static const bool value = false; +}; + +template +struct dt_parameters_are_compatible +{ + static const bool value = false; +}; + +template <> +struct dt_parameters_are_compatible +{ + static const bool value = true; +}; + +// Value used as infinite distance for distance_transform. +float constexpr dt_infinite = 1000000000; + +/// \breif Calculates distance transfrom with mask size three. +/// Optimal local distances a, b for euclidean approximation from, +/// http://www.cmm.mines-paristech.fr/~marcoteg/cv/publi_pdf/MM_refs/1986_Borgefors_distance.pdf +template +void distance_transform_mask_size_three_impl(SrcView const& src_view, + DstView const& dst_view, + distance_from dist_from, + DistanceType /*Passes type*/) +{ + int const padding = 1; + gray32f_image_t intermediate_image(src_view.width() + 2 * padding, + src_view.height() + 2 * padding); + gray32f_view_t intermediate_image_view = view(intermediate_image); + + for (std::ptrdiff_t x = 0; x < intermediate_image_view.width(); ++x) + { + intermediate_image_view(x, 0)[0] = dt_infinite ; + intermediate_image_view(x, intermediate_image_view.height() - 1)[0] = dt_infinite; + } + for (std::ptrdiff_t y = 0; y < intermediate_image_view.height(); ++y) + { + intermediate_image_view(0, y)[0] = dt_infinite ; + intermediate_image_view(intermediate_image_view.width() - 1, y)[0] = dt_infinite ; + } + + float constexpr src_channel_min = + (std::numeric_limits ::type>::min)(); + + for (std::ptrdiff_t y = 0; y < src_view.height(); ++y) + { + for (std::ptrdiff_t x = 0; x < src_view.width(); ++x) + { + if(dist_from == distance_from::off_pixels) + { + if (src_view(x, y)[0] == src_channel_min) + intermediate_image_view(x + padding, y + padding)[0] = 0; + else + intermediate_image_view(x + padding, y + padding)[0] = dt_infinite; + } + else + { + if (src_view(x, y)[0] != src_channel_min) + intermediate_image_view(x + padding, y + padding)[0] = 0; + else + intermediate_image_view(x + padding, y + padding)[0] = dt_infinite; + } + } + } + + float a, b; + + if(std::is_same::value) + { + a = 0.95509f; + b = 1.36930f; + } + else if(std::is_same::value) + { + a = 1; + b = 2; + } + else + { + a = 1; + b = 1; + } + + for (std::ptrdiff_t y = 0; y < src_view.height(); ++y) + { + for (std::ptrdiff_t x = 0; x < src_view.width(); ++x) + { + if(intermediate_image_view(x + padding, y + padding)[0] > 0) + { + float const d1 = a + intermediate_image_view(x - 1 + padding, y + padding)[0]; + float const d2 = b + intermediate_image_view(x - 1 + padding, y - 1 + padding)[0]; + float const d3 = a + intermediate_image_view(x + padding, y - 1 + padding)[0]; + float const d4 = b + intermediate_image_view(x + 1 + padding, y - 1 + padding)[0]; + + intermediate_image_view(x + padding, y + padding)[0] = std::min({d1, d2, d3, d4}); + } + } + } + + for (std::ptrdiff_t y = src_view.height() - 1; y >= 0; --y) + { + for (std::ptrdiff_t x = src_view.width() - 1; x >= 0; --x) + { + if (intermediate_image_view(x + padding, y + padding)[0] > 0) + { + float const d1 = a + intermediate_image_view(x + 1 + padding, y + padding)[0]; + float const d2 = b + intermediate_image_view(x + 1 + padding, y + 1 + padding)[0]; + float const d3 = a + intermediate_image_view(x + padding, y + 1 + padding)[0]; + float const d4 = b + intermediate_image_view(x - 1 + padding, y + 1 + padding)[0]; + + intermediate_image_view(x + padding, y + padding)[0] = std::min({ d1, d2, d3, d4, + static_cast(intermediate_image_view(x + padding, y + padding)[0]) }); + + float const distance_transform = intermediate_image_view + (x + padding, y + padding)[0]; + + float constexpr dst_channel_max = + (is_same::value) ? dt_infinite : static_cast( + (std::numeric_limits::type>::max)()); + + float constexpr dst_channel_min = + (is_same::value) ? 0.f : static_cast( + (std::numeric_limits::type>::min)()); + + dst_view(x, y)[0] = + static_cast::type>( + (distance_transform > dst_channel_max) ? dst_channel_max : + (distance_transform < dst_channel_min) ? dst_channel_min : + distance_transform); + } + } + } +} + +/// \breif Calculates distance transfrom with mask size five. +/// Optimal local distances a, b, c for euclidean approximation from, +/// http://www.cmm.mines-paristech.fr/~marcoteg/cv/publi_pdf/MM_refs/1986_Borgefors_distance.pdf +template +void distance_transform_mask_size_five_impl(SrcView const& src_view, + DstView const& dst_view, + distance_from dist_from, + DistanceType /*Passes type*/) +{ + int const padding = 2; + gray32f_image_t intermediate_image(src_view.width() + 2 * padding, + src_view.height() + 2 * padding); + gray32f_view_t intermediate_image_view = view(intermediate_image); + + for (std::ptrdiff_t x = 0; x < intermediate_image_view.width(); ++x) + { + intermediate_image_view(x, 0)[0] = dt_infinite; + intermediate_image_view(x, 1)[0] = dt_infinite; + intermediate_image_view(x, intermediate_image_view.height() - 1)[0] = dt_infinite; + intermediate_image_view(x, intermediate_image_view.height() - 2)[0] = dt_infinite; + } + for (std::ptrdiff_t y = 0; y < intermediate_image_view.height(); ++y) + { + intermediate_image_view(0, y)[0] = dt_infinite ; + intermediate_image_view(1, y)[0] = dt_infinite ; + intermediate_image_view(intermediate_image_view.width() - 1, y)[0] = dt_infinite; + intermediate_image_view(intermediate_image_view.width() - 2, y)[0] = dt_infinite; + } + + float constexpr src_channel_min = + (std::numeric_limits::type>::min)(); + + for (std::ptrdiff_t y = 0; y < src_view.height(); ++y) + { + for (std::ptrdiff_t x = 0; x < src_view.width(); ++x) + { + if(dist_from == distance_from::off_pixels) + { + if (src_view(x, y)[0] == src_channel_min) + intermediate_image_view(x + padding, y + padding)[0] = 0; + else + intermediate_image_view(x + padding, y + padding)[0] = dt_infinite; + } + else + { + if (src_view(x, y)[0] != src_channel_min) + intermediate_image_view(x + padding, y + padding)[0] = 0; + else + intermediate_image_view(x + padding, y + padding)[0] = dt_infinite; + } + } + } + + float a, b, c; + + if(std::is_same::value) + { + a = 1; + b = 1.4f; + c = 2.19691f; + } + else if(std::is_same::value) + { + a = 1; + b = 2; + c = 3; + } + else + { + a = 1; + b = 1; + c = 2; + } + + for (std::ptrdiff_t y = 0; y < src_view.height(); ++y) + { + for (std::ptrdiff_t x = 0; x < src_view.width(); ++x) + { + if(intermediate_image_view(x + padding, y + padding)[0] > 0) + { + float const d1 = c + intermediate_image_view(x - 1 + padding, y - 2 + padding)[0]; + float const d2 = c + intermediate_image_view(x + 1 + padding, y - 2 + padding)[0]; + float const d3 = c + intermediate_image_view(x - 2 + padding, y - 1 + padding)[0]; + float const d4 = b + intermediate_image_view(x - 1 + padding, y - 1 + padding)[0]; + float const d5 = a + intermediate_image_view(x + padding, y - 1 + padding)[0]; + float const d6 = b + intermediate_image_view(x + 1 + padding, y - 1 + padding)[0]; + float const d7 = c + intermediate_image_view(x + 2 + padding, y - 1 + padding)[0]; + float const d8 = a + intermediate_image_view(x - 1 + padding, y + padding)[0]; + + intermediate_image_view(x + padding, y + padding)[0] = + std::min({d1, d2, d3, d4, d5, d6, d7, d8}); + } + } + } + + for (std::ptrdiff_t y = src_view.height() - 1; y >= 0; --y) + { + for (std::ptrdiff_t x = src_view.width() - 1; x >= 0; --x) + { + if (intermediate_image_view(x + padding, y + padding)[0] > 0) + { + float const d1 = c + intermediate_image_view(x + 1 + padding, y + 2 + padding)[0]; + float const d2 = c + intermediate_image_view(x - 1 + padding, y + 2 + padding)[0]; + float const d3 = c + intermediate_image_view(x + 2 + padding, y + 1 + padding)[0]; + float const d4 = b + intermediate_image_view(x + 1 + padding, y + 1 + padding)[0]; + float const d5 = a + intermediate_image_view(x + padding, y + 1 + padding)[0]; + float const d6 = b + intermediate_image_view(x - 1 + padding, y + 1 + padding)[0]; + float const d7 = c + intermediate_image_view(x - 2 + padding, y + 1 + padding)[0]; + float const d8 = a + intermediate_image_view(x + 1 + padding, y + padding)[0]; + + intermediate_image_view(x + padding, y + padding)[0] = + std::min({ d1, d2, d3, d4, d5, d6, d7, d8, + static_cast(intermediate_image_view(x + padding, y + padding)[0]) }); + + float const distance_transform = + intermediate_image_view (x + padding, y + padding)[0]; + + float constexpr dst_channel_max = + (is_same::value) ? dt_infinite : static_cast( + (std::numeric_limits::type>::max)()); + + float constexpr dst_channel_min = + (is_same::value) ? 0.f : static_cast( + (std::numeric_limits::type>::min)()); + + dst_view(x, y)[0] = + static_cast::type>( + (distance_transform > dst_channel_max) ? dst_channel_max : + (distance_transform < dst_channel_min) ? dst_channel_min : + distance_transform); + } + } + } +} + +/// \breif Calculates one-dimensional squared euclidean distance. +/// +/// Reference - http://www.theoryofcomputing.org/articles/v008a019/v008a019.pdf +template +std::vector calculate_squared_euclidean_distance(ImageIterator f, std::ptrdiff_t n) +{ + std::ptrdiff_t k = 0; + std::vector d(n); + std::vector v(n); + std::vector z(n + 1); + v[0] = 0; + z[0] = static_cast(-dt_infinite); + z[1] = static_cast(dt_infinite); + for(int q = 1; q < n ; ++q) + { + float s = static_cast(((f[q][0] + std::pow(q, 2)) - + (f[v[k]][0] + std::pow(v[k], 2))) / (2 * q - 2 * v[k])); + while (s <= z[k]) + { + --k; + s = static_cast(((f[q][0] + std::pow(q, 2)) - + (f[v[k]][0] + std::pow(v[k], 2))) / (2 * q - 2 * v[k])); + } + { + k = k + 1; + v[k] = static_cast(q); + z[k] = static_cast(s); + z[k + 1] = static_cast(dt_infinite); + } + } + k = 0; + for (int q = 0; q < n; ++q) + { + while(z[k+1] < q) + { + ++k; + } + d[q] = static_cast(std::pow((q - v[k]), 2) + f[v[k]][0]); + } + return d; +} + +/// \breif Calculates precise euclidean distance transform. +template +void distance_transorm_precise_impl(SrcView const& src_view, + DstView const& dst_view, + distance_from dist_from) +{ + gray32f_image_t intermediate_image(src_view.dimensions()); + gray32f_view_t intermediate_image_view = view(intermediate_image); + float constexpr src_channel_min = + (std::numeric_limits::type>::min)(); + + for (std::ptrdiff_t y = 0; y < src_view.height(); ++y) + { + for (std::ptrdiff_t x = 0; x < src_view.width(); ++x) + { + if (dist_from == distance_from::off_pixels) + { + if (src_view(x, y)[0] == src_channel_min) intermediate_image_view(x, y)[0] = 0; + else intermediate_image_view(x, y)[0] = dt_infinite; + } + else + { + if (src_view(x, y)[0] != src_channel_min) intermediate_image_view(x, y)[0] = 0; + else intermediate_image_view(x, y)[0] = dt_infinite; + } + } + } + + for (std::ptrdiff_t y = 0; y < intermediate_image_view.height(); ++y) + { + typename gray32f_view_t::x_iterator intermediate_row_itr = + intermediate_image_view.row_begin(y); + + std::vector one_dimensional_squared_distance = calculate_squared_euclidean_distance + (intermediate_row_itr, intermediate_image_view.width()); + + for (std::ptrdiff_t x = 0; x < intermediate_image_view.width(); ++x) + { + intermediate_row_itr[x][0] = one_dimensional_squared_distance[x]; + } + } + + for (std::ptrdiff_t x = 0; x < intermediate_image_view.width(); ++x) + { + typename gray32f_view_t::y_iterator intermediate_col_itr = + intermediate_image_view.col_begin(x); + + std::vector one_dimensional_squared_distance = calculate_squared_euclidean_distance + (intermediate_col_itr, intermediate_image_view.height()); + + for (std::ptrdiff_t y = 0; y < intermediate_image_view.height(); ++y) + { + intermediate_col_itr[y][0] = one_dimensional_squared_distance[y]; + + float const distance_transform = std::sqrt(intermediate_col_itr[y][0]); + + float constexpr dst_channel_max = + (is_same::value) ? dt_infinite : static_cast( + (std::numeric_limits::type>::max)()); + + float constexpr dst_channel_min = + (is_same::value) ? 0.f : static_cast( + (std::numeric_limits::type>::min)()); + + dst_view(x, y)[0] = + static_cast::type>( + (distance_transform > dst_channel_max) ? dst_channel_max : + (distance_transform < dst_channel_min) ? dst_channel_min : + distance_transform); + } + } +} + +} //namespace detail + +/// \addtogroup ImageProcessing +/// @{ +/// \breif Calculates distance to the nearest 'on' OR 'off' pixel (as specified), +/// for each pixel of a binary image. +/// +/// \param src_view - Source image view. +/// \param dst_view - Destination image view. +/// \param dist_from - Specifies from where to find distance from, neareast, 'on' OR 'off' pixels. +/// \param dist_type - Specifies formula/method for distance calculation. +/// \tparam SrcView - Source image view type. +/// \tparam DstView - Destination image view type. +/// \tparam DistanceType - Distance type choosen. +/// \tparam MaskSize - Mask size choosen. +template +void distance_transform(SrcView const& src_view, DstView const& dst_view, distance_from dist_from, + DistanceType dist_type, MaskSize /*Passes type*/) +{ + gil_function_requires>(); + gil_function_requires>(); + + static_assert(is_same::type>::value && + is_same::type>::value, + "Source and destination image views must use gray color space."); + + static_assert(distance_type::check_distance_type::value, + "Distance type not recognized."); + static_assert(mask_size::check_mask_size::value, "Mask Size not recognized."); + + // Generates compile time error if invalid combination of distance_type and mask_size is used. + static_assert(detail::dt_parameters_are_compatible::value, + "distance_transform is incompatible with combination of " + "distance_type and mask_size used."); + + BOOST_ASSERT(src_view.dimensions() == dst_view.dimensions()); + + if(std::is_same::value) + distance_transform_mask_size_three_impl(src_view, dst_view, dist_from, dist_type); + + else if (std::is_same::value) + distance_transform_mask_size_five_impl(src_view, dst_view, dist_from, dist_type); + + else + distance_transorm_precise_impl(src_view, dst_view, dist_from); +} +/// @} +}} // namespace boost::gil +#endif // BOOST_GIL_IMAGE_PROCESSING_DISTANCE_TRANSFORM_HPP diff --git a/test/core/image_processing/CMakeLists.txt b/test/core/image_processing/CMakeLists.txt index 1581fd3075..a8d47eacdc 100644 --- a/test/core/image_processing/CMakeLists.txt +++ b/test/core/image_processing/CMakeLists.txt @@ -10,7 +10,8 @@ foreach(_name threshold_binary threshold_truncate threshold_otsu - morphology) + morphology + distance_transform) set(_test t_core_image_processing_${_name}) set(_target test_core_image_processing_${_name}) diff --git a/test/core/image_processing/Jamfile b/test/core/image_processing/Jamfile index acd74d08f2..7210891057 100644 --- a/test/core/image_processing/Jamfile +++ b/test/core/image_processing/Jamfile @@ -23,3 +23,4 @@ run anisotropic_diffusion.cpp ; run hough_line_transform.cpp ; run hough_circle_transform.cpp ; run morphology.cpp ; +distance_transform.cpp ; diff --git a/test/core/image_processing/distance_transform.cpp b/test/core/image_processing/distance_transform.cpp new file mode 100644 index 0000000000..e36a9cb185 --- /dev/null +++ b/test/core/image_processing/distance_transform.cpp @@ -0,0 +1,480 @@ +// +// Copyright 2021 Harsit Pant +// +// Use, modification and distribution are subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#include +#include +#include +#include + +namespace gil = boost::gil; + +template +void fill_image_view(std::vector >& values, ImgView image_view) +{ + for (std::ptrdiff_t y = 0; y < image_view.height(); ++y) + { + for (std::ptrdiff_t x = 0; x < image_view.width(); ++x) + { + image_view(x, y)[0] = values[y][x]; + } + } +} + +template +void check_for_negligible_varition(ImgView1 const& image_view1, ImgView2 const& image_view2) +{ + for (std::ptrdiff_t y = 0; y < image_view1.height(); ++y) + { + for (std::ptrdiff_t x = 0; x < image_view1.width(); ++x) + { + float variation = std::abs(image_view1(x, y)[0] - image_view2(x, y)[0]); + BOOST_TEST_LT(variation, 0.1); + } + } +} + +void test_manhattan_uint8_t_input_uint8_t_output_distance_from_off_pixels() +{ + + gil::gray8_image_t img_in(7, 7); + gil::gray8_image_t img_expected(7, 7); + gil::gray8_image_t img_out(7, 7); + + //test values from wikipedia, in 8 bit binary form + std::vector> val_in + { + {0, 0, 0, 0, 0, 0,0}, + {0,255,255,255,255,255,0}, + {0,255,255,255,255,255,0}, + {0,255,255,255,255,255,0}, + {0,255,255,255,255,255,0}, + {0,255,255,255,255,255,0}, + {0, 0, 0, 0, 0, 0,0} + }; + + std::vector> val_exp + { + {0,0,0,0,0,0,0}, + {0,1,1,1,1,1,0}, + {0,1,2,2,2,1,0}, + {0,1,2,3,2,1,0}, + {0,1,2,2,2,1,0}, + {0,1,1,1,1,1,0}, + {0,0,0,0,0,0,0} + }; + + fill_image_view(val_in, view(img_in)); + fill_image_view(val_exp, view(img_expected)); + + gil::distance_transform(view(img_in), view(img_out), gil::distance_from::off_pixels, + gil::distance_type::manhattan, gil::mask_size::three); + + BOOST_TEST(equal_pixels(const_view(img_out), const_view(img_expected))); +} + + +void test_chessboard_uint16_t_input_uint8_t_output_distance_from_on_pixels() +{ + gil::gray16_image_t img_in(7, 7); + gil::gray8_image_t img_expected(7, 7); + gil::gray8_image_t img_out(7, 7); + + std::vector> val_in + { + {0, 65535, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 65535, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0} + }; + + std::vector> val_exp + { + {1, 0, 1, 2, 3, 4, 4}, + {1, 1, 1, 2, 3, 3, 3}, + {2, 2, 2, 2, 2, 2, 3}, + {3, 2, 1, 1, 1, 2, 3}, + {3, 2, 1, 0, 1, 2, 3}, + {3, 2, 1, 1, 1, 2, 3}, + {3, 2, 2, 2, 2, 2, 3} + }; + + fill_image_view(val_in, view(img_in)); + fill_image_view(val_exp, view(img_expected)); + + gil::distance_transform(view(img_in), view(img_out), gil::distance_from::on_pixels, + gil::distance_type::chessboard, gil::mask_size::three); + + BOOST_TEST(equal_pixels(const_view(img_out), const_view(img_expected))); +} + +void test_euclidean_approx_and_manhattan_uint8_t_input_float32_t_output_distance_from_off_pixels() +{ + gil::gray8_image_t img_in(15, 15); + gil::gray32f_image_t img_expected(15, 15); + gil::gray32f_image_t img_out(15, 15); + + std::vector> val_in + { + {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, + {255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255}, + {255, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 255}, + {255, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 255}, + {255, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 255}, + {255, 0, 255, 255, 255, 0, 0, 0, 0, 0, 255, 255, 255, 0, 255}, + {255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255}, + {255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255}, + {255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255}, + {255, 0, 255, 255, 255, 0, 0, 0, 0, 0, 255, 255, 255, 0, 255}, + {255, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 255}, + {255, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 255}, + {255, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 255}, + {255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255}, + {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255} + }; + + std::vector> val_exp1 + { + {1.4f, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.4f}, + { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, + { 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1}, + { 1, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0, 1}, + { 1, 0, 1, 2, 1.4f, 1, 1, 1, 1, 1, 1.4f, 2, 1, 0, 1}, + { 1, 0, 1, 2, 1, 0, 0, 0, 0, 0, 1, 2, 1, 0, 1}, + { 1, 0, 1, 2, 1, 0, 1, 1, 1, 0, 1, 2, 1, 0, 1}, + { 1, 0, 1, 2, 1, 0, 1, 2, 1, 0, 1, 2, 1, 0, 1}, + { 1, 0, 1, 2, 1, 0, 1, 1, 1, 0, 1, 2, 1, 0, 1}, + { 1, 0, 1, 2, 1, 0, 0, 0, 0, 0, 1, 2, 1, 0, 1}, + { 1, 0, 1, 2, 1.4f, 1, 1, 1, 1, 1, 1.4f, 2, 1, 0, 1}, + { 1, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0, 1}, + { 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1}, + { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, + {1.4f, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.4f} + }; + + std::vector> val_exp2 + { + {2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2}, + {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, + {1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1}, + {1, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0, 1}, + {1, 0, 1, 2, 2, 1, 1, 1, 1, 1, 2, 2, 1, 0, 1}, + {1, 0, 1, 2, 1, 0, 0, 0, 0, 0, 1, 2, 1, 0, 1}, + {1, 0, 1, 2, 1, 0, 1, 1, 1, 0, 1, 2, 1, 0, 1}, + {1, 0, 1, 2, 1, 0, 1, 2, 1, 0, 1, 2, 1, 0, 1}, + {1, 0, 1, 2, 1, 0, 1, 1, 1, 0, 1, 2, 1, 0, 1}, + {1, 0, 1, 2, 1, 0, 0, 0, 0, 0, 1, 2, 1, 0, 1}, + {1, 0, 1, 2, 2, 1, 1, 1, 1, 1, 2, 2, 1, 0, 1}, + {1, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0, 1}, + {1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1}, + {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, + {2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2} + }; + + fill_image_view(val_in, view(img_in)); + fill_image_view(val_exp1, view(img_expected)); + gil::distance_transform(view(img_in), view(img_out), gil::distance_from::off_pixels, + gil::distance_type::euclidean_approximation, gil::mask_size::five); + BOOST_TEST(equal_pixels(const_view(img_out), const_view(img_expected))); + + fill_image_view(val_exp2, view(img_expected)); + gil::distance_transform(view(img_in), view(img_out), gil::distance_from::off_pixels, + gil::distance_type::manhattan, gil::mask_size::five); + BOOST_TEST(equal_pixels(const_view(img_out), const_view(img_expected))); + +} + +void test_all_uint8_t_input_float32_t_ouptut_distance_from_off_pixels() +{ + gil::gray8_image_t img_in(15, 15); + gil::gray32f_image_t img_expected(15, 15); + gil::gray32f_image_t img_out(15, 15); + + std::vector> val_in + { + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255} , + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 255, 255, 255, 255}, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, + { 255, 255, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0} + }; + + std::vector> val_exp_precise + { + {3.6055512f, 3.1622777f, 3, 3.1622777f, 3.6055512f, 4.2426405f, 4.1231055f, 3.1622777f, + 2.236068f, 1.4142135f, 1, 1.4142135f, 2.236068f, 3.1622777f, 4.1231055f}, + { 2.828427f, 2.236068f, 2, 2.236068f, 2.828427f, 3.6055512f, 4, + 3, 2, 1, 0, 1, 2, 3, 4}, + { 2.236068f, 1.4142135f, 1, 1.4142135f, 2.236068f, 3.1622777f, 4.1231055f, 3.1622777f, + 2.236068f, 1.4142135f, 1, 1.4142135f, 2.236068f, 3.1622777f, 4.1231055f}, + { 2, 1, 0, 1, 2, 3, 4, 3.6055512f, + 2.828427f, 2.236068f, 2, 2.236068f, 2.828427f, 3.6055512f, 4.472136f}, + { 2.236068f, 1.4142135f, 1, 1.4142135f, 2.236068f, 3.1622777f, 4.1231055f, 4.2426405f, + 3.6055512f, 3.1622777f, 3, 3.1622777f, 3.6055512f, 4.2426405f, 5}, + { 2.828427f, 2.236068f, 2, 2.236068f, 2.828427f, 3.6055512f, 4.472136f, 5, + 4.472136f, 4.1231055f, 4, 4.1231055f, 4.472136f, 5, 5.656854f}, + {3.6055512f, 3.1622777f, 3, 3.1622777f, 3.6055512f, 4.2426405f, 5, 5.8309517f, + 5.3851647f, 5.0990195f, 5, 5.0990195f, 5.3851647f, 5.8309517f, 6.4031243f}, + { 4.472136f, 4.1231055f, 4, 4.1231055f, 4.472136f, 5, 5.656854f, 6.4031243f, + 6.3245554f, 6.0827622f, 6, 6.0827622f, 6.3245554f, 6.7082043f, 7.0000005f}, + {5.3851647f, 5.0990195f, 5, 5.0990195f, 5.3851647f, 5.8309517f, 6.4031243f, 7.0710683f, + 7.2801094f, 7.0710683f, 7.0000005f, 6.7082043f, 6.3245554f, 6.0827622f, 6}, + {6.3245554f, 6.0827622f, 6, 6.0827622f, 6.3245554f, 6.7082043f, 7.2111025f, 7.8102503f, + 7.8102503f, 7.0710683f, 6.4031243f, 5.8309517f, 5.3851647f, 5.0990195f, 5}, + {7.2801094f, 7.0710683f, 7.0000005f, 7.0710683f, 7.2801094f, 7.6157737f, 8.062258f, 8.062258f, + 7.2111025f, 6.4031243f, 5.656854f, 5, 4.472136f, 4.1231055f, 4}, + { 8.246211f, 8.062258f, 8, 8.062258f, 8.246211f, 8.5440035f, 8.5440035f, 7.6157737f, + 6.7082043f, 5.8309517f, 5, 4.2426405f, 3.6055512f, 3.1622777f, 3}, + { 9.219544f, 9.055386f, 9, 9.055386f, 9.219544f, 9.219544f, 8.246211f, 7.2801094f, + 6.3245554f, 5.3851647f, 4.472136f, 3.6055512f, 2.828427f, 2.236068f, 2}, + {10.198039f, 10.049875f, 10, 10.049875f, 10.049875f, 9.055386f, 8.062258f, 7.0710683f, + 6.0827622f, 5.0990195f, 4.1231055f, 3.1622777f, 2.236068f, 1.4142135f, 1}, + {11.180341f, 11.045361f, 11, 11, 10, 9, 8, 7, + 6, 5, 4, 3, 2, 1, 0} + }; + + fill_image_view(val_in, view(img_in)); + fill_image_view(val_exp_precise, view(img_expected)); + gil::distance_transform(view(img_in), view(img_out), gil::distance_from::off_pixels, + gil::distance_type::precise_euclidean, gil::mask_size::not_applicable); + + check_for_negligible_varition(view(img_out), view(img_expected)); + + std::vector> val_exp_euclidean_three + { + { 3.6935883f, 3.2792969f, 2.8650055f, 3.2792969f, 3.6935883f, 4.1078796f, + 4.2342987f, 3.2792969f, 2.324295f, 1.3692932f, 0.95500183f, 1.3692932f, + 2.324295f, 3.2792969f, 4.2342987f}, + { 2.7385864f, 2.324295f, 1.9100037f, 2.324295f, 2.7385864f, 3.6935883f, + 3.8200073f, 2.8650055f, 1.9100037f, 0.95500183f, 0, 0.95500183f, + 1.9100037f, 2.8650055f, 3.8200073f}, + { 2.324295f, 1.3692932f, 0.95500183f, 1.3692932f, 2.324295f, 3.2792969f, + 4.2342987f, 3.2792969f, 2.324295f, 1.3692932f, 0.95500183f, 1.3692932f, + 2.324295f, 3.2792969f, 4.2342987f}, + { 1.9100037f, 0.95500183f, 0, 0.95500183f, 1.9100037f, 2.8650055f, + 3.8200073f, 3.6935883f, 2.7385864f, 2.324295f, 1.9100037f, 2.324295f, + 2.7385864f, 3.6935883f, 4.64859f}, + { 2.324295f, 1.3692932f, 0.95500183f, 1.3692932f, 2.324295f, 3.2792969f, + 4.2342987f, 4.1078796f, 3.6935883f, 3.2792969f, 2.8650055f, 3.2792969f, + 3.6935883f, 4.1078796f, 5.0628815f}, + { 2.7385864f, 2.324295f, 1.9100037f, 2.324295f, 2.7385864f, 3.6935883f, + 4.64859f, 5.0628815f, 4.64859f, 4.2342987f, 3.8200073f, 4.2342987f, + 4.64859f, 5.0628815f, 5.477173f}, + { 3.6935883f, 3.2792969f, 2.8650055f, 3.2792969f, 3.6935883f, 4.1078796f, + 5.0628815f, 6.0178833f, 5.603592f, 5.1893005f, 4.775009f, 5.1893005f, + 5.603592f, 6.0178833f, 6.4321747f}, + { 4.64859f, 4.2342987f, 3.8200073f, 4.2342987f, 4.64859f, 5.0628815f, + 5.477173f, 6.4321747f, 6.5585938f, 6.1443024f, 5.730011f, 6.1443024f, + 6.5585938f, 6.972885f, 6.685013f}, + { 5.603592f, 5.1893005f, 4.775009f, 5.1893005f, 5.603592f, 6.0178833f, + 6.4321747f, 6.846466f, 7.5135956f, 7.099304f, 6.685013f, 6.972885f, + 6.5585938f, 6.1443024f, 5.730011f}, + { 6.5585938f, 6.1443024f, 5.730011f, 6.1443024f, 6.5585938f, 6.972885f, + 7.3871765f, 7.801468f, 7.801468f, 6.846466f, 6.4321747f, 6.0178833f, + 5.603592f, 5.1893005f, 4.775009f}, + { 7.5135956f, 7.099304f, 6.685013f, 7.099304f, 7.5135956f, 7.927887f, + 8.342178f, 8.342178f, 7.3871765f, 6.4321747f, 5.477173f, 5.0628815f, + 4.64859f, 4.2342987f, 3.8200073f}, + { 8.468597f, 8.054306f, 7.6400146f, 8.054306f, 8.468597f, 8.882889f, + 8.882889f, 7.927887f, 6.972885f, 6.0178833f, 5.0628815f, 4.1078796f, + 3.6935883f, 3.2792969f, 2.8650055f}, + { 9.423599f, 9.009308f, 8.5950165f, 9.009308f, 9.423599f, 9.423599f, + 8.468597f, 7.5135956f, 6.5585938f, 5.603592f, 4.64859f, 3.6935883f, + 2.7385864f, 2.324295f, 1.9100037f}, + { 10.378601f, 9.96431f, 9.550018f, 9.96431f, 9.96431f, 9.009308f, + 8.054306f, 7.099304f, 6.1443024f, 5.1893005f, 4.2342987f, 3.2792969f, + 2.324295f, 1.3692932f, 0.95500183f}, + { 11.333603f, 10.919312f, 10.50502f, 10.50502f, 9.550018f, 8.5950165f, + 7.6400146f, 6.685013f, 5.730011f, 4.775009f, 3.8200073f, 2.8650055f, + 1.9100037f, 0.95500183f, 0.f} + }; + + fill_image_view(val_in, view(img_in)); + fill_image_view(val_exp_euclidean_three, view(img_expected)); + gil::distance_transform(view(img_in), view(img_out), gil::distance_from::off_pixels, + gil::distance_type::euclidean_approximation, gil::mask_size::three); + + check_for_negligible_varition(view(img_out), view(img_expected)); + + std::vector> val_exp_euclidean_five + { + {3.5969f, 3.1969f, 3, 3.1969f, 3.5969f, 4.2f, + 4.1969f, 3.1969f, 2.1969f, 1.4f, 1, 1.4f, + 2.1969f, 3.1969f, 4.1969f}, + { 2.8f, 2.1969f, 2, 2.1969f, 2.8f, 3.5969f, + 4, 3, 2, 1, 0, 1, + 2, 3, 4}, + {2.1969f, 1.4f, 1, 1.4f, 2.1969f, 3.1969f, + 4.1969f, 3.1969f, 2.1969f, 1.4f, 1, 1.4f, + 2.1969f, 3.1969f, 4.1969f}, + { 2, 1, 0, 1, 2, 3, + 4, 3.5969f, 2.8f, 2.1969f, 2, 2.1969f, + 2.8f, 3.5969f, 4.3938f}, + {2.1969f, 1.4f, 1, 1.4f, 2.1969f, 3.1969f, + 4.1969f, 4.2f, 3.5969f, 3.1969f, 3, 3.1969f, + 3.5969f, 4.2f, 4.9968996f}, + { 2.8f, 2.1969f, 2, 2.1969f, 2.8f, 3.5969f, + 4.3938f, 4.9968996f, 4.3938f, 4.1969f, 4, 4.1969f, + 4.3938f, 4.9968996f, 5.6f}, + {3.5969f, 3.1969f, 3, 3.1969f, 3.5969f, 4.2f, + 4.9968996f, 5.7938f, 5.3938f, 5.1969f, 5, 5.1969f, + 5.3938f, 5.7938f, 6.3968997f}, + {4.3938f, 4.1969f, 4, 4.1969f, 4.3938f, 4.9968996f, + 5.6f, 6.3968997f, 6.3938f, 6.1969f, 6, 6.1969f, + 6.3938f, 6.5906997f, 7}, + {5.3938f, 5.1969f, 5, 5.1969f, 5.3938f, 5.7938f, + 6.3968997f, 7, 7.3938f, 7.1969f, 7, 6.5906997f, + 6.3938f, 6.1969f, 6}, + {6.3938f, 6.1969f, 6, 6.1969f, 6.3938f, 6.5906997f, + 7.1937995f, 7.7969f, 7.7969f, 7, 6.3968997f, 5.7938f, + 5.3938f, 5.1969f, 5}, + {7.3938f, 7.1969f, 7, 7.1969f, 7.3938f, 7.5906997f, + 7.9907f, 7.9907f, 7.1937995f, 6.3968997f, 5.6f, 4.9968996f, + 4.3938f, 4.1969f, 4}, + {8.3938f, 8.196899f, 8, 8.196899f, 8.3938f, 8.5907f, + 8.5907f, 7.5906997f, 6.5906997f, 5.7938f, 4.9968996f, 4.2f, + 3.5969f, 3.1969f, 3}, + {9.3938f, 9.196899f, 9, 9.196899f, 9.3938f, 9.3938f, + 8.3938f, 7.3938f, 6.3938f, 5.3938f, 4.3938f, 3.5969f, + 2.8f, 2.1969f, 2}, + {10.393799f, 10.196899f, 10, 10.196899f, 10.196899f, 9.196899f, + 8.196899f, 7.1969f, 6.1969f, 5.1969f, 4.1969f, 3.1969f, + 2.1969f, 1.4f, 1}, + {11.393799f, 11.196899f, 11, 11, 10, 9, + 8, 7, 6, 5, 4, 3, + 2, 1, 0} + }; + + fill_image_view(val_in, view(img_in)); + fill_image_view(val_exp_euclidean_five, view(img_expected)); + gil::distance_transform(view(img_in), view(img_out), gil::distance_from::off_pixels, + gil::distance_type::euclidean_approximation, gil::mask_size::five); + + check_for_negligible_varition(view(img_out), view(img_expected)); + + + std::vector> val_exp_manhatten_three + { + {5, 4, 3, 4, 5, 6, 5, 4, 3, 2, 1, 2, 3, 4, 5}, + {4, 3, 2, 3, 4, 5, 4, 3, 2, 1, 0, 1, 2, 3, 4}, + {3, 2, 1, 2, 3, 4, 5, 4, 3, 2, 1, 2, 3, 4, 5}, + {2, 1, 0, 1, 2, 3, 4, 5, 4, 3, 2, 3, 4, 5, 6}, + {3, 2, 1, 2, 3, 4, 5, 6, 5, 4, 3, 4, 5, 6, 7}, + {4, 3, 2, 3, 4, 5, 6, 7, 6, 5, 4, 5, 6, 7, 8}, + {5, 4, 3, 4, 5, 6, 7, 8, 7, 6, 5, 6, 7, 8, 8}, + {6, 5, 4, 5, 6, 7, 8, 9, 8, 7, 6, 7, 8, 8, 7}, + {7, 6, 5, 6, 7, 8, 9, 10, 9, 8, 7, 8, 8, 7, 6}, + {8, 7, 6, 7, 8, 9, 10, 11, 10, 9, 8, 8, 7, 6, 5}, + {9, 8, 7, 8, 9, 10, 11, 11, 10, 9, 8, 7, 6, 5, 4}, + {10, 9, 8, 9, 10, 11, 11, 10, 9, 8, 7, 6, 5, 4, 3}, + {11, 10, 9, 10, 11, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2}, + {12, 11, 10, 11, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1}, + {13, 12, 11, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0} + }; + + fill_image_view(val_exp_manhatten_three, view(img_expected)); + gil::distance_transform(view(img_in), view(img_out), gil::distance_from::off_pixels, + gil::distance_type::manhattan, gil::mask_size::three); + BOOST_TEST(equal_pixels(const_view(img_out), const_view(img_expected))); + + + + std::vector> val_exp_manhatten_five + { + {5, 4, 3, 4, 5, 6, 5, 4, 3, 2, 1, 2, 3, 4, 5}, + {4, 3, 2, 3, 4, 5, 4, 3, 2, 1, 0, 1, 2, 3, 4}, + {3, 2, 1, 2, 3, 4, 5, 4, 3, 2, 1, 2, 3, 4, 5}, + {2, 1, 0, 1, 2, 3, 4, 5, 4, 3, 2, 3, 4, 5, 6}, + {3, 2, 1, 2, 3, 4, 5, 6, 5, 4, 3, 4, 5, 6, 7}, + {4, 3, 2, 3, 4, 5, 6, 7, 6, 5, 4, 5, 6, 7, 8}, + {5, 4, 3, 4, 5, 6, 7, 8, 7, 6, 5, 6, 7, 8, 8}, + {6, 5, 4, 5, 6, 7, 8, 9, 8, 7, 6, 7, 8, 8, 7}, + {7, 6, 5, 6, 7, 8, 9, 10, 9, 8, 7, 8, 8, 7, 6}, + {8, 7, 6, 7, 8, 9, 10, 11, 10, 9, 8, 8, 7, 6, 5}, + {9, 8, 7, 8, 9, 10, 11, 11, 10, 9, 8, 7, 6, 5, 4}, + {10, 9, 8, 9, 10, 11, 11, 10, 9, 8, 7, 6, 5, 4, 3}, + {11, 10, 9, 10, 11, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2}, + {12, 11, 10, 11, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1}, + {13, 12, 11, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0} + }; + + fill_image_view(val_exp_manhatten_five, view(img_expected)); + gil::distance_transform(view(img_in), view(img_out), gil::distance_from::off_pixels, + gil::distance_type::manhattan, gil::mask_size::five); + BOOST_TEST(equal_pixels(const_view(img_out), const_view(img_expected))); + + + std::vector> val_exp_chessboard_three + { + {3, 3, 3, 3, 3, 3, 4, 3, 2, 1, 1, 1, 2, 3, 4}, + {2, 2, 2, 2, 2, 3, 4, 3, 2, 1, 0, 1, 2, 3, 4}, + {2, 1, 1, 1, 2, 3, 4, 3, 2, 1, 1, 1, 2, 3, 4}, + {2, 1, 0, 1, 2, 3, 4, 3, 2, 2, 2, 2, 2, 3, 4}, + {2, 1, 1, 1, 2, 3, 4, 3, 3, 3, 3, 3, 3, 3, 4}, + {2, 2, 2, 2, 2, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4}, + {3, 3, 3, 3, 3, 3, 4, 5, 5, 5, 5, 5, 5, 5, 5}, + {4, 4, 4, 4, 4, 4, 4, 5, 6, 6, 6, 6, 6, 6, 6}, + {5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6}, + {6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5}, + {7, 7, 7, 7, 7, 7, 7, 7, 6, 5, 4, 4, 4, 4, 4}, + {8, 8, 8, 8, 8, 8, 8, 7, 6, 5, 4, 3, 3, 3, 3}, + {9, 9, 9, 9, 9, 9, 8, 7, 6, 5, 4, 3, 2, 2, 2}, + {10, 10, 10, 10, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1}, + {11, 11, 11, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0} + }; + + fill_image_view(val_exp_chessboard_three, view(img_expected)); + gil::distance_transform(view(img_in), view(img_out), gil::distance_from::off_pixels, + gil::distance_type::chessboard, gil::mask_size::three); + BOOST_TEST(equal_pixels(const_view(img_out), const_view(img_expected))); + + std::vector> val_exp_chessboard_five + { + {3, 3, 3, 3, 3, 3, 4, 3, 2, 1, 1, 1, 2, 3, 4}, + {2, 2, 2, 2, 2, 3, 4, 3, 2, 1, 0, 1, 2, 3, 4}, + {2, 1, 1, 1, 2, 3, 4, 3, 2, 1, 1, 1, 2, 3, 4}, + {2, 1, 0, 1, 2, 3, 4, 3, 2, 2, 2, 2, 2, 3, 4}, + {2, 1, 1, 1, 2, 3, 4, 3, 3, 3, 3, 3, 3, 3, 4}, + {2, 2, 2, 2, 2, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4}, + {3, 3, 3, 3, 3, 3, 4, 5, 5, 5, 5, 5, 5, 5, 5}, + {4, 4, 4, 4, 4, 4, 4, 5, 6, 6, 6, 6, 6, 6, 6}, + {5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6}, + {6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5}, + {7, 7, 7, 7, 7, 7, 7, 7, 6, 5, 4, 4, 4, 4, 4}, + {8, 8, 8, 8, 8, 8, 8, 7, 6, 5, 4, 3, 3, 3, 3}, + {9, 9, 9, 9, 9, 9, 8, 7, 6, 5, 4, 3, 2, 2, 2}, + {10, 10, 10, 10, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1}, + {11, 11, 11, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0} + }; + + fill_image_view(val_exp_chessboard_five, view(img_expected)); + gil::distance_transform(view(img_in), view(img_out), gil::distance_from::off_pixels, + gil::distance_type::chessboard, gil::mask_size::five); + BOOST_TEST(equal_pixels(const_view(img_out), const_view(img_expected))); + +} + +int main() +{ + test_manhattan_uint8_t_input_uint8_t_output_distance_from_off_pixels(); + test_chessboard_uint16_t_input_uint8_t_output_distance_from_on_pixels(); + test_euclidean_approx_and_manhattan_uint8_t_input_float32_t_output_distance_from_off_pixels(); + test_all_uint8_t_input_float32_t_ouptut_distance_from_off_pixels(); + return ::boost::report_errors(); +} From 2cedb4a98ce576ddadcbd0849c0f56678ddf9b21 Mon Sep 17 00:00:00 2001 From: harsh-4 Date: Sat, 3 Apr 2021 10:23:02 +0530 Subject: [PATCH 2/9] Fix b2 jamfile error --- test/core/image_processing/Jamfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/core/image_processing/Jamfile b/test/core/image_processing/Jamfile index 7210891057..43791c956c 100644 --- a/test/core/image_processing/Jamfile +++ b/test/core/image_processing/Jamfile @@ -23,4 +23,4 @@ run anisotropic_diffusion.cpp ; run hough_line_transform.cpp ; run hough_circle_transform.cpp ; run morphology.cpp ; -distance_transform.cpp ; +run distance_transform.cpp ; From 8c12da2bf646d0cb576dbe12abca933e269b7f9d Mon Sep 17 00:00:00 2001 From: harsh-4 Date: Sun, 4 Apr 2021 00:36:24 +0530 Subject: [PATCH 3/9] Improve test coverage --- .../image_processing/distance_transform.cpp | 208 +++++++++++------- 1 file changed, 123 insertions(+), 85 deletions(-) diff --git a/test/core/image_processing/distance_transform.cpp b/test/core/image_processing/distance_transform.cpp index e36a9cb185..ebafdf35c8 100644 --- a/test/core/image_processing/distance_transform.cpp +++ b/test/core/image_processing/distance_transform.cpp @@ -82,6 +82,8 @@ void test_chessboard_uint16_t_input_uint8_t_output_distance_from_on_pixels() gil::gray16_image_t img_in(7, 7); gil::gray8_image_t img_expected(7, 7); gil::gray8_image_t img_out(7, 7); + gil::gray32f_image_t img_expected_float32_t(7, 7); + gil::gray32f_image_t img_out_float32_t(7, 7); std::vector> val_in { @@ -94,7 +96,7 @@ void test_chessboard_uint16_t_input_uint8_t_output_distance_from_on_pixels() {0, 0, 0, 0, 0, 0, 0} }; - std::vector> val_exp + std::vector> val_exp_chessboard_three { {1, 0, 1, 2, 3, 4, 4}, {1, 1, 1, 2, 3, 3, 3}, @@ -106,12 +108,48 @@ void test_chessboard_uint16_t_input_uint8_t_output_distance_from_on_pixels() }; fill_image_view(val_in, view(img_in)); - fill_image_view(val_exp, view(img_expected)); + fill_image_view(val_exp_chessboard_three, view(img_expected)); gil::distance_transform(view(img_in), view(img_out), gil::distance_from::on_pixels, gil::distance_type::chessboard, gil::mask_size::three); BOOST_TEST(equal_pixels(const_view(img_out), const_view(img_expected))); + + std::vector> val_exp_manhattan_five + { + {1, 0, 1, 2, 3, 4, 5}, + {2, 1, 2, 3, 4, 5, 6}, + {3, 2, 3, 2, 3, 4, 5}, + {4, 3, 2, 1, 2, 3, 4}, + {3, 2, 1, 0, 1, 2, 3}, + {4, 3, 2, 1, 2, 3, 4}, + {5, 4, 3, 2, 3, 4, 5} + }; + + fill_image_view(val_exp_manhattan_five, view(img_expected)); + + gil::distance_transform(view(img_in), view(img_out), gil::distance_from::on_pixels, + gil::distance_type::manhattan, gil::mask_size::five); + + BOOST_TEST(equal_pixels(const_view(img_out), const_view(img_expected))); + + std::vector> val_exp_euclidean_precise + { + { 1, 0, 1, 2, 3, 4, 5}, + {1.4142135f, 1, 1.4142135f, 2.236068f, 3.1622777f, 3.6055512f, 4.2426405f}, + { 2.236068f, 2, 2.236068f, 2, 2.236068f, 2.828427f, 3.6055512f}, + {3.1622777f, 2.236068f, 1.4142135f, 1, 1.4142135f, 2.236068f, 3.1622777f}, + { 3, 2, 1, 0, 1, 2, 3}, + {3.1622777f, 2.236068f, 1.4142135f, 1, 1.4142135f, 2.236068f, 3.1622777f}, + {3.6055512f, 2.828427f, 2.236068f, 2, 2.236068f, 2.828427f, 3.6055512f} + }; + + fill_image_view(val_exp_euclidean_precise, view(img_expected_float32_t)); + + gil::distance_transform(view(img_in), view(img_out_float32_t), gil::distance_from::on_pixels, + gil::distance_type::precise_euclidean, gil::mask_size::not_applicable); + + BOOST_TEST(equal_pixels(const_view(img_out_float32_t), const_view(img_expected_float32_t))); } void test_euclidean_approx_and_manhattan_uint8_t_input_float32_t_output_distance_from_off_pixels() @@ -217,36 +255,36 @@ void test_all_uint8_t_input_float32_t_ouptut_distance_from_off_pixels() std::vector> val_exp_precise { - {3.6055512f, 3.1622777f, 3, 3.1622777f, 3.6055512f, 4.2426405f, 4.1231055f, 3.1622777f, - 2.236068f, 1.4142135f, 1, 1.4142135f, 2.236068f, 3.1622777f, 4.1231055f}, - { 2.828427f, 2.236068f, 2, 2.236068f, 2.828427f, 3.6055512f, 4, - 3, 2, 1, 0, 1, 2, 3, 4}, - { 2.236068f, 1.4142135f, 1, 1.4142135f, 2.236068f, 3.1622777f, 4.1231055f, 3.1622777f, - 2.236068f, 1.4142135f, 1, 1.4142135f, 2.236068f, 3.1622777f, 4.1231055f}, - { 2, 1, 0, 1, 2, 3, 4, 3.6055512f, - 2.828427f, 2.236068f, 2, 2.236068f, 2.828427f, 3.6055512f, 4.472136f}, - { 2.236068f, 1.4142135f, 1, 1.4142135f, 2.236068f, 3.1622777f, 4.1231055f, 4.2426405f, - 3.6055512f, 3.1622777f, 3, 3.1622777f, 3.6055512f, 4.2426405f, 5}, - { 2.828427f, 2.236068f, 2, 2.236068f, 2.828427f, 3.6055512f, 4.472136f, 5, - 4.472136f, 4.1231055f, 4, 4.1231055f, 4.472136f, 5, 5.656854f}, - {3.6055512f, 3.1622777f, 3, 3.1622777f, 3.6055512f, 4.2426405f, 5, 5.8309517f, - 5.3851647f, 5.0990195f, 5, 5.0990195f, 5.3851647f, 5.8309517f, 6.4031243f}, - { 4.472136f, 4.1231055f, 4, 4.1231055f, 4.472136f, 5, 5.656854f, 6.4031243f, - 6.3245554f, 6.0827622f, 6, 6.0827622f, 6.3245554f, 6.7082043f, 7.0000005f}, - {5.3851647f, 5.0990195f, 5, 5.0990195f, 5.3851647f, 5.8309517f, 6.4031243f, 7.0710683f, - 7.2801094f, 7.0710683f, 7.0000005f, 6.7082043f, 6.3245554f, 6.0827622f, 6}, - {6.3245554f, 6.0827622f, 6, 6.0827622f, 6.3245554f, 6.7082043f, 7.2111025f, 7.8102503f, - 7.8102503f, 7.0710683f, 6.4031243f, 5.8309517f, 5.3851647f, 5.0990195f, 5}, - {7.2801094f, 7.0710683f, 7.0000005f, 7.0710683f, 7.2801094f, 7.6157737f, 8.062258f, 8.062258f, - 7.2111025f, 6.4031243f, 5.656854f, 5, 4.472136f, 4.1231055f, 4}, - { 8.246211f, 8.062258f, 8, 8.062258f, 8.246211f, 8.5440035f, 8.5440035f, 7.6157737f, - 6.7082043f, 5.8309517f, 5, 4.2426405f, 3.6055512f, 3.1622777f, 3}, - { 9.219544f, 9.055386f, 9, 9.055386f, 9.219544f, 9.219544f, 8.246211f, 7.2801094f, - 6.3245554f, 5.3851647f, 4.472136f, 3.6055512f, 2.828427f, 2.236068f, 2}, - {10.198039f, 10.049875f, 10, 10.049875f, 10.049875f, 9.055386f, 8.062258f, 7.0710683f, - 6.0827622f, 5.0990195f, 4.1231055f, 3.1622777f, 2.236068f, 1.4142135f, 1}, - {11.180341f, 11.045361f, 11, 11, 10, 9, 8, 7, - 6, 5, 4, 3, 2, 1, 0} + {3.6055512f, 3.1622777f, 3, 3.1622777f, 3.6055512f, 4.2426405f, 4.1231055f, 3.1622777f, + 2.236068f, 1.4142135f, 1, 1.4142135f, 2.236068f, 3.1622777f, 4.1231055f}, + { 2.828427f, 2.236068f, 2, 2.236068f, 2.828427f, 3.6055512f, 4, + 3, 2, 1, 0, 1, 2, 3, 4}, + { 2.236068f, 1.4142135f, 1, 1.4142135f, 2.236068f, 3.1622777f, 4.1231055f, 3.1622777f, + 2.236068f, 1.4142135f, 1, 1.4142135f, 2.236068f, 3.1622777f, 4.1231055f}, + { 2, 1, 0, 1, 2, 3, 4, 3.6055512f, + 2.828427f, 2.236068f, 2, 2.236068f, 2.828427f, 3.6055512f, 4.472136f}, + { 2.236068f, 1.4142135f, 1, 1.4142135f, 2.236068f, 3.1622777f, 4.1231055f, 4.2426405f, + 3.6055512f, 3.1622777f, 3, 3.1622777f, 3.6055512f, 4.2426405f, 5}, + { 2.828427f, 2.236068f, 2, 2.236068f, 2.828427f, 3.6055512f, 4.472136f, 5, + 4.472136f, 4.1231055f, 4, 4.1231055f, 4.472136f, 5, 5.656854f}, + {3.6055512f, 3.1622777f, 3, 3.1622777f, 3.6055512f, 4.2426405f, 5, 5.8309517f, + 5.3851647f, 5.0990195f, 5, 5.0990195f, 5.3851647f, 5.8309517f, 6.4031243f}, + { 4.472136f, 4.1231055f, 4, 4.1231055f, 4.472136f, 5, 5.656854f, 6.4031243f, + 6.3245554f, 6.0827622f, 6, 6.0827622f, 6.3245554f, 6.7082043f, 7.0000005f}, + {5.3851647f, 5.0990195f, 5, 5.0990195f, 5.3851647f, 5.8309517f, 6.4031243f, 7.0710683f, + 7.2801094f, 7.0710683f, 7.0000005f, 6.7082043f, 6.3245554f, 6.0827622f, 6}, + {6.3245554f, 6.0827622f, 6, 6.0827622f, 6.3245554f, 6.7082043f, 7.2111025f, 7.8102503f, + 7.8102503f, 7.0710683f, 6.4031243f, 5.8309517f, 5.3851647f, 5.0990195f, 5}, + {7.2801094f, 7.0710683f, 7.0000005f, 7.0710683f, 7.2801094f, 7.6157737f, 8.062258f, 8.062258f, + 7.2111025f, 6.4031243f, 5.656854f, 5, 4.472136f, 4.1231055f, 4}, + { 8.246211f, 8.062258f, 8, 8.062258f, 8.246211f, 8.5440035f, 8.5440035f, 7.6157737f, + 6.7082043f, 5.8309517f, 5, 4.2426405f, 3.6055512f, 3.1622777f, 3}, + { 9.219544f, 9.055386f, 9, 9.055386f, 9.219544f, 9.219544f, 8.246211f, 7.2801094f, + 6.3245554f, 5.3851647f, 4.472136f, 3.6055512f, 2.828427f, 2.236068f, 2}, + {10.198039f, 10.049875f, 10, 10.049875f, 10.049875f, 9.055386f, 8.062258f, 7.0710683f, + 6.0827622f, 5.0990195f, 4.1231055f, 3.1622777f, 2.236068f, 1.4142135f, 1}, + {11.180341f, 11.045361f, 11, 11, 10, 9, 8, 7, + 6, 5, 4, 3, 2, 1, 0} }; fill_image_view(val_in, view(img_in)); @@ -258,27 +296,27 @@ void test_all_uint8_t_input_float32_t_ouptut_distance_from_off_pixels() std::vector> val_exp_euclidean_three { - { 3.6935883f, 3.2792969f, 2.8650055f, 3.2792969f, 3.6935883f, 4.1078796f, - 4.2342987f, 3.2792969f, 2.324295f, 1.3692932f, 0.95500183f, 1.3692932f, + { 3.6935883f, 3.2792969f, 2.8650055f, 3.2792969f, 3.6935883f, 4.1078796f, + 4.2342987f, 3.2792969f, 2.324295f, 1.3692932f, 0.95500183f, 1.3692932f, 2.324295f, 3.2792969f, 4.2342987f}, - { 2.7385864f, 2.324295f, 1.9100037f, 2.324295f, 2.7385864f, 3.6935883f, - 3.8200073f, 2.8650055f, 1.9100037f, 0.95500183f, 0, 0.95500183f, + { 2.7385864f, 2.324295f, 1.9100037f, 2.324295f, 2.7385864f, 3.6935883f, + 3.8200073f, 2.8650055f, 1.9100037f, 0.95500183f, 0, 0.95500183f, 1.9100037f, 2.8650055f, 3.8200073f}, - { 2.324295f, 1.3692932f, 0.95500183f, 1.3692932f, 2.324295f, 3.2792969f, - 4.2342987f, 3.2792969f, 2.324295f, 1.3692932f, 0.95500183f, 1.3692932f, + { 2.324295f, 1.3692932f, 0.95500183f, 1.3692932f, 2.324295f, 3.2792969f, + 4.2342987f, 3.2792969f, 2.324295f, 1.3692932f, 0.95500183f, 1.3692932f, 2.324295f, 3.2792969f, 4.2342987f}, - { 1.9100037f, 0.95500183f, 0, 0.95500183f, 1.9100037f, 2.8650055f, - 3.8200073f, 3.6935883f, 2.7385864f, 2.324295f, 1.9100037f, 2.324295f, - 2.7385864f, 3.6935883f, 4.64859f}, - { 2.324295f, 1.3692932f, 0.95500183f, 1.3692932f, 2.324295f, 3.2792969f, - 4.2342987f, 4.1078796f, 3.6935883f, 3.2792969f, 2.8650055f, 3.2792969f, + { 1.9100037f, 0.95500183f, 0, 0.95500183f, 1.9100037f, 2.8650055f, + 3.8200073f, 3.6935883f, 2.7385864f, 2.324295f, 1.9100037f, 2.324295f, + 2.7385864f, 3.6935883f, 4.64859f}, + { 2.324295f, 1.3692932f, 0.95500183f, 1.3692932f, 2.324295f, 3.2792969f, + 4.2342987f, 4.1078796f, 3.6935883f, 3.2792969f, 2.8650055f, 3.2792969f, 3.6935883f, 4.1078796f, 5.0628815f}, - { 2.7385864f, 2.324295f, 1.9100037f, 2.324295f, 2.7385864f, 3.6935883f, - 4.64859f, 5.0628815f, 4.64859f, 4.2342987f, 3.8200073f, 4.2342987f, + { 2.7385864f, 2.324295f, 1.9100037f, 2.324295f, 2.7385864f, 3.6935883f, + 4.64859f, 5.0628815f, 4.64859f, 4.2342987f, 3.8200073f, 4.2342987f, 4.64859f, 5.0628815f, 5.477173f}, { 3.6935883f, 3.2792969f, 2.8650055f, 3.2792969f, 3.6935883f, 4.1078796f, 5.0628815f, 6.0178833f, 5.603592f, 5.1893005f, 4.775009f, 5.1893005f, - 5.603592f, 6.0178833f, 6.4321747f}, + 5.603592f, 6.0178833f, 6.4321747f}, { 4.64859f, 4.2342987f, 3.8200073f, 4.2342987f, 4.64859f, 5.0628815f, 5.477173f, 6.4321747f, 6.5585938f, 6.1443024f, 5.730011f, 6.1443024f, 6.5585938f, 6.972885f, 6.685013f}, @@ -295,13 +333,13 @@ void test_all_uint8_t_input_float32_t_ouptut_distance_from_off_pixels() 8.882889f, 7.927887f, 6.972885f, 6.0178833f, 5.0628815f, 4.1078796f, 3.6935883f, 3.2792969f, 2.8650055f}, { 9.423599f, 9.009308f, 8.5950165f, 9.009308f, 9.423599f, 9.423599f, - 8.468597f, 7.5135956f, 6.5585938f, 5.603592f, 4.64859f, 3.6935883f, + 8.468597f, 7.5135956f, 6.5585938f, 5.603592f, 4.64859f, 3.6935883f, 2.7385864f, 2.324295f, 1.9100037f}, - { 10.378601f, 9.96431f, 9.550018f, 9.96431f, 9.96431f, 9.009308f, - 8.054306f, 7.099304f, 6.1443024f, 5.1893005f, 4.2342987f, 3.2792969f, + { 10.378601f, 9.96431f, 9.550018f, 9.96431f, 9.96431f, 9.009308f, + 8.054306f, 7.099304f, 6.1443024f, 5.1893005f, 4.2342987f, 3.2792969f, 2.324295f, 1.3692932f, 0.95500183f}, { 11.333603f, 10.919312f, 10.50502f, 10.50502f, 9.550018f, 8.5950165f, - 7.6400146f, 6.685013f, 5.730011f, 4.775009f, 3.8200073f, 2.8650055f, + 7.6400146f, 6.685013f, 5.730011f, 4.775009f, 3.8200073f, 2.8650055f, 1.9100037f, 0.95500183f, 0.f} }; @@ -371,17 +409,17 @@ void test_all_uint8_t_input_float32_t_ouptut_distance_from_off_pixels() std::vector> val_exp_manhatten_three { - {5, 4, 3, 4, 5, 6, 5, 4, 3, 2, 1, 2, 3, 4, 5}, - {4, 3, 2, 3, 4, 5, 4, 3, 2, 1, 0, 1, 2, 3, 4}, - {3, 2, 1, 2, 3, 4, 5, 4, 3, 2, 1, 2, 3, 4, 5}, - {2, 1, 0, 1, 2, 3, 4, 5, 4, 3, 2, 3, 4, 5, 6}, - {3, 2, 1, 2, 3, 4, 5, 6, 5, 4, 3, 4, 5, 6, 7}, - {4, 3, 2, 3, 4, 5, 6, 7, 6, 5, 4, 5, 6, 7, 8}, - {5, 4, 3, 4, 5, 6, 7, 8, 7, 6, 5, 6, 7, 8, 8}, - {6, 5, 4, 5, 6, 7, 8, 9, 8, 7, 6, 7, 8, 8, 7}, - {7, 6, 5, 6, 7, 8, 9, 10, 9, 8, 7, 8, 8, 7, 6}, - {8, 7, 6, 7, 8, 9, 10, 11, 10, 9, 8, 8, 7, 6, 5}, - {9, 8, 7, 8, 9, 10, 11, 11, 10, 9, 8, 7, 6, 5, 4}, + { 5, 4, 3, 4, 5, 6, 5, 4, 3, 2, 1, 2, 3, 4, 5}, + { 4, 3, 2, 3, 4, 5, 4, 3, 2, 1, 0, 1, 2, 3, 4}, + { 3, 2, 1, 2, 3, 4, 5, 4, 3, 2, 1, 2, 3, 4, 5}, + { 2, 1, 0, 1, 2, 3, 4, 5, 4, 3, 2, 3, 4, 5, 6}, + { 3, 2, 1, 2, 3, 4, 5, 6, 5, 4, 3, 4, 5, 6, 7}, + { 4, 3, 2, 3, 4, 5, 6, 7, 6, 5, 4, 5, 6, 7, 8}, + { 5, 4, 3, 4, 5, 6, 7, 8, 7, 6, 5, 6, 7, 8, 8}, + { 6, 5, 4, 5, 6, 7, 8, 9, 8, 7, 6, 7, 8, 8, 7}, + { 7, 6, 5, 6, 7, 8, 9, 10, 9, 8, 7, 8, 8, 7, 6}, + { 8, 7, 6, 7, 8, 9, 10, 11, 10, 9, 8, 8, 7, 6, 5}, + { 9, 8, 7, 8, 9, 10, 11, 11, 10, 9, 8, 7, 6, 5, 4}, {10, 9, 8, 9, 10, 11, 11, 10, 9, 8, 7, 6, 5, 4, 3}, {11, 10, 9, 10, 11, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2}, {12, 11, 10, 11, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1}, @@ -397,17 +435,17 @@ void test_all_uint8_t_input_float32_t_ouptut_distance_from_off_pixels() std::vector> val_exp_manhatten_five { - {5, 4, 3, 4, 5, 6, 5, 4, 3, 2, 1, 2, 3, 4, 5}, - {4, 3, 2, 3, 4, 5, 4, 3, 2, 1, 0, 1, 2, 3, 4}, - {3, 2, 1, 2, 3, 4, 5, 4, 3, 2, 1, 2, 3, 4, 5}, - {2, 1, 0, 1, 2, 3, 4, 5, 4, 3, 2, 3, 4, 5, 6}, - {3, 2, 1, 2, 3, 4, 5, 6, 5, 4, 3, 4, 5, 6, 7}, - {4, 3, 2, 3, 4, 5, 6, 7, 6, 5, 4, 5, 6, 7, 8}, - {5, 4, 3, 4, 5, 6, 7, 8, 7, 6, 5, 6, 7, 8, 8}, - {6, 5, 4, 5, 6, 7, 8, 9, 8, 7, 6, 7, 8, 8, 7}, - {7, 6, 5, 6, 7, 8, 9, 10, 9, 8, 7, 8, 8, 7, 6}, - {8, 7, 6, 7, 8, 9, 10, 11, 10, 9, 8, 8, 7, 6, 5}, - {9, 8, 7, 8, 9, 10, 11, 11, 10, 9, 8, 7, 6, 5, 4}, + { 5, 4, 3, 4, 5, 6, 5, 4, 3, 2, 1, 2, 3, 4, 5}, + { 4, 3, 2, 3, 4, 5, 4, 3, 2, 1, 0, 1, 2, 3, 4}, + { 3, 2, 1, 2, 3, 4, 5, 4, 3, 2, 1, 2, 3, 4, 5}, + { 2, 1, 0, 1, 2, 3, 4, 5, 4, 3, 2, 3, 4, 5, 6}, + { 3, 2, 1, 2, 3, 4, 5, 6, 5, 4, 3, 4, 5, 6, 7}, + { 4, 3, 2, 3, 4, 5, 6, 7, 6, 5, 4, 5, 6, 7, 8}, + { 5, 4, 3, 4, 5, 6, 7, 8, 7, 6, 5, 6, 7, 8, 8}, + { 6, 5, 4, 5, 6, 7, 8, 9, 8, 7, 6, 7, 8, 8, 7}, + { 7, 6, 5, 6, 7, 8, 9, 10, 9, 8, 7, 8, 8, 7, 6}, + { 8, 7, 6, 7, 8, 9, 10, 11, 10, 9, 8, 8, 7, 6, 5}, + { 9, 8, 7, 8, 9, 10, 11, 11, 10, 9, 8, 7, 6, 5, 4}, {10, 9, 8, 9, 10, 11, 11, 10, 9, 8, 7, 6, 5, 4, 3}, {11, 10, 9, 10, 11, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2}, {12, 11, 10, 11, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1}, @@ -422,19 +460,19 @@ void test_all_uint8_t_input_float32_t_ouptut_distance_from_off_pixels() std::vector> val_exp_chessboard_three { - {3, 3, 3, 3, 3, 3, 4, 3, 2, 1, 1, 1, 2, 3, 4}, - {2, 2, 2, 2, 2, 3, 4, 3, 2, 1, 0, 1, 2, 3, 4}, - {2, 1, 1, 1, 2, 3, 4, 3, 2, 1, 1, 1, 2, 3, 4}, - {2, 1, 0, 1, 2, 3, 4, 3, 2, 2, 2, 2, 2, 3, 4}, - {2, 1, 1, 1, 2, 3, 4, 3, 3, 3, 3, 3, 3, 3, 4}, - {2, 2, 2, 2, 2, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4}, - {3, 3, 3, 3, 3, 3, 4, 5, 5, 5, 5, 5, 5, 5, 5}, - {4, 4, 4, 4, 4, 4, 4, 5, 6, 6, 6, 6, 6, 6, 6}, - {5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6}, - {6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5}, - {7, 7, 7, 7, 7, 7, 7, 7, 6, 5, 4, 4, 4, 4, 4}, - {8, 8, 8, 8, 8, 8, 8, 7, 6, 5, 4, 3, 3, 3, 3}, - {9, 9, 9, 9, 9, 9, 8, 7, 6, 5, 4, 3, 2, 2, 2}, + { 3, 3, 3, 3, 3, 3, 4, 3, 2, 1, 1, 1, 2, 3, 4}, + { 2, 2, 2, 2, 2, 3, 4, 3, 2, 1, 0, 1, 2, 3, 4}, + { 2, 1, 1, 1, 2, 3, 4, 3, 2, 1, 1, 1, 2, 3, 4}, + { 2, 1, 0, 1, 2, 3, 4, 3, 2, 2, 2, 2, 2, 3, 4}, + { 2, 1, 1, 1, 2, 3, 4, 3, 3, 3, 3, 3, 3, 3, 4}, + { 2, 2, 2, 2, 2, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4}, + { 3, 3, 3, 3, 3, 3, 4, 5, 5, 5, 5, 5, 5, 5, 5}, + { 4, 4, 4, 4, 4, 4, 4, 5, 6, 6, 6, 6, 6, 6, 6}, + { 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6}, + { 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5}, + { 7, 7, 7, 7, 7, 7, 7, 7, 6, 5, 4, 4, 4, 4, 4}, + { 8, 8, 8, 8, 8, 8, 8, 7, 6, 5, 4, 3, 3, 3, 3}, + { 9, 9, 9, 9, 9, 9, 8, 7, 6, 5, 4, 3, 2, 2, 2}, {10, 10, 10, 10, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1}, {11, 11, 11, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0} }; From 05a18757bf211eeb5ff7a4834fe08b30de735f64 Mon Sep 17 00:00:00 2001 From: harsh-4 Date: Thu, 10 Jun 2021 13:46:53 +0530 Subject: [PATCH 4/9] Improve formatting; Correct name in copyright info --- .../gil/image_processing/distance_transform.hpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/include/boost/gil/image_processing/distance_transform.hpp b/include/boost/gil/image_processing/distance_transform.hpp index 188ead88f1..8d7fc536b0 100644 --- a/include/boost/gil/image_processing/distance_transform.hpp +++ b/include/boost/gil/image_processing/distance_transform.hpp @@ -1,5 +1,5 @@ // -// Copyright 2021 Harsit Pant +// Copyright 2021 Harshit Pant // // Use, modification and distribution are subject to the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at @@ -21,7 +21,8 @@ namespace boost { namespace gil { -namespace distance_type{ +namespace distance_type { + struct euclidean_approximation_t {}; struct manhattan_t {}; struct chessboard_t {}; @@ -41,9 +42,10 @@ struct check_distance_type std::is_same::value || std::is_same::value; }; -} +} // namespace distance_type namespace mask_size { + struct three_t {}; struct five_t {}; struct not_applicable_t {}; @@ -60,7 +62,7 @@ struct check_mask_size std::is_same::value || std::is_same::value; }; -} +} // namespace mask_size enum class distance_from { @@ -95,7 +97,7 @@ struct dt_parameters_are_compatible std::vector calculate_squared_euclidean_distance(ImageIterator f, std::ptrdiff_t n) From 91fadc5bb33c9bd4d359bbd1c6f7eab831202ecd Mon Sep 17 00:00:00 2001 From: harsh-4 Date: Thu, 10 Jun 2021 19:38:44 +0530 Subject: [PATCH 5/9] Improve Metafunctions Use constexpr wherever preferred; Replace static const bool by inheriting std::true_type or std::false_type in metafunctions. --- .../image_processing/distance_transform.hpp | 37 +++++++------------ 1 file changed, 14 insertions(+), 23 deletions(-) diff --git a/include/boost/gil/image_processing/distance_transform.hpp b/include/boost/gil/image_processing/distance_transform.hpp index 8d7fc536b0..4eef99edf9 100644 --- a/include/boost/gil/image_processing/distance_transform.hpp +++ b/include/boost/gil/image_processing/distance_transform.hpp @@ -37,10 +37,10 @@ static precise_euclidean_t precise_euclidean; template struct check_distance_type { - static const bool value = std::is_same::value || - std::is_same::value || - std::is_same::value || - std::is_same::value; + static constexpr bool value = std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value; }; } // namespace distance_type @@ -58,9 +58,9 @@ static not_applicable_t not_applicable; template struct check_mask_size { - static const bool value = std::is_same::value || - std::is_same::value || - std::is_same::value; + static constexpr bool value = std::is_same::value || + std::is_same::value || + std::is_same::value; }; } // namespace mask_size @@ -74,28 +74,19 @@ namespace detail { /// \breif Checks compatiblity of distance_type and mask_size used together. template -struct dt_parameters_are_compatible -{ - static const bool value = true; -}; +struct dt_parameters_are_compatible : std::true_type {}; template -struct dt_parameters_are_compatible -{ - static const bool value = false; -}; +struct dt_parameters_are_compatible + : std::false_type {}; template -struct dt_parameters_are_compatible -{ - static const bool value = false; -}; +struct dt_parameters_are_compatible + : std::false_type {}; template <> -struct dt_parameters_are_compatible -{ - static const bool value = true; -}; +struct dt_parameters_are_compatible + : std::true_type {}; /// \breif Value used as infinite distance for distance_transform. float constexpr dt_infinite = 1000000000; From f12a1451b1be9384a5f1a4da39d9fb2393a550bb Mon Sep 17 00:00:00 2001 From: harsh-4 Date: Fri, 11 Jun 2021 20:52:10 +0530 Subject: [PATCH 6/9] Move all metafunctions to detail namespace Moves 2 metafunctions: check_mask_size and check_distance_type to detail namespace and prefixes them with 'dt' (distance_transform) to avoid naming conflicts. --- .../image_processing/distance_transform.hpp | 53 +++++++++---------- 1 file changed, 26 insertions(+), 27 deletions(-) diff --git a/include/boost/gil/image_processing/distance_transform.hpp b/include/boost/gil/image_processing/distance_transform.hpp index 4eef99edf9..1b81641b3a 100644 --- a/include/boost/gil/image_processing/distance_transform.hpp +++ b/include/boost/gil/image_processing/distance_transform.hpp @@ -22,7 +22,6 @@ namespace boost { namespace gil { namespace distance_type { - struct euclidean_approximation_t {}; struct manhattan_t {}; struct chessboard_t {}; @@ -32,20 +31,9 @@ static euclidean_approximation_t euclidean_approximation; static manhattan_t manhattan; static chessboard_t chessboard; static precise_euclidean_t precise_euclidean; - -/// \breif Checks if distance_type used exists. -template -struct check_distance_type -{ - static constexpr bool value = std::is_same::value || - std::is_same::value || - std::is_same::value || - std::is_same::value; -}; } // namespace distance_type namespace mask_size { - struct three_t {}; struct five_t {}; struct not_applicable_t {}; @@ -53,15 +41,6 @@ struct not_applicable_t {}; static three_t three; static five_t five; static not_applicable_t not_applicable; - -/// \breif Checks if mask_size used exists. -template -struct check_mask_size -{ - static constexpr bool value = std::is_same::value || - std::is_same::value || - std::is_same::value; -}; } // namespace mask_size enum class distance_from @@ -72,6 +51,26 @@ enum class distance_from namespace detail { +/// \breif Checks if mask_size used exists. +template +struct dt_check_mask_size +{ + static constexpr bool value = std::is_same::value || + std::is_same::value || + std::is_same::value; +}; + +/// \breif Checks if distance_type used exists. +template +struct dt_check_distance_type +{ + static constexpr bool value = + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value; +}; + /// \breif Checks compatiblity of distance_type and mask_size used together. template struct dt_parameters_are_compatible : std::true_type {}; @@ -458,7 +457,7 @@ void distance_transorm_precise_impl(SrcView const& src_view, } } -} //namespace detail +} // namespace detail /// \addtogroup ImageProcessing /// @{ @@ -480,13 +479,13 @@ void distance_transform(SrcView const& src_view, DstView const& dst_view, distan gil_function_requires>(); gil_function_requires>(); - static_assert(is_same::type>::value && - is_same::type>::value, + static_assert(std::is_same::type>::value && + std::is_same::type>::value, "Source and destination image views must use gray color space."); - static_assert(distance_type::check_distance_type::value, + static_assert(detail::dt_check_distance_type::value, "Distance type not recognized."); - static_assert(mask_size::check_mask_size::value, "Mask Size not recognized."); + static_assert(detail::dt_check_mask_size::value, "Mask Size not recognized."); // Generates compile time error if invalid combination of distance_type and mask_size is used. static_assert(detail::dt_parameters_are_compatible::value, @@ -495,7 +494,7 @@ void distance_transform(SrcView const& src_view, DstView const& dst_view, distan BOOST_ASSERT(src_view.dimensions() == dst_view.dimensions()); - if(std::is_same::value) + if (std::is_same::value) distance_transform_mask_size_three_impl(src_view, dst_view, dist_from, dist_type); else if (std::is_same::value) From 0bfb69d4ef877705415d4830116c085f74328fea Mon Sep 17 00:00:00 2001 From: harsh-4 Date: Wed, 23 Jun 2021 09:03:55 +0530 Subject: [PATCH 7/9] Add some more explanatory and reference comments --- .../image_processing/distance_transform.hpp | 108 +++++++++--------- 1 file changed, 57 insertions(+), 51 deletions(-) diff --git a/include/boost/gil/image_processing/distance_transform.hpp b/include/boost/gil/image_processing/distance_transform.hpp index 1b81641b3a..f39b3ac2cb 100644 --- a/include/boost/gil/image_processing/distance_transform.hpp +++ b/include/boost/gil/image_processing/distance_transform.hpp @@ -91,8 +91,9 @@ struct dt_parameters_are_compatible float constexpr dt_infinite = 1000000000; /// \breif Calculates distance transfrom with mask size three. -/// Optimal local distances a, b for euclidean approximation from, -/// http://www.cmm.mines-paristech.fr/~marcoteg/cv/publi_pdf/MM_refs/1986_Borgefors_distance.pdf +/// Optimal local distances a, b for euclidean approximation from, +/// http://www.cmm.mines-paristech.fr/~marcoteg/cv/publi_pdf/MM_refs/1986_Borgefors_distance.pdf +/// Algorithm from - Principles of Digital Image Processing: Core Algorithms (Section 11.2.2). template void distance_transform_mask_size_three_impl(SrcView const& src_view, DstView const& dst_view, @@ -122,7 +123,7 @@ void distance_transform_mask_size_three_impl(SrcView const& src_view, { for (std::ptrdiff_t x = 0; x < src_view.width(); ++x) { - if(dist_from == distance_from::off_pixels) + if (dist_from == distance_from::off_pixels) { if (src_view(x, y)[0] == src_channel_min) intermediate_image_view(x + padding, y + padding)[0] = 0; @@ -139,9 +140,9 @@ void distance_transform_mask_size_three_impl(SrcView const& src_view, } } - float a, b; + float a, b; // a and b hold elements of the distance mask (see reference). - if(std::is_same::value) + if (std::is_same::value) { a = 0.95509f; b = 1.36930f; @@ -161,7 +162,7 @@ void distance_transform_mask_size_three_impl(SrcView const& src_view, { for (std::ptrdiff_t x = 0; x < src_view.width(); ++x) { - if(intermediate_image_view(x + padding, y + padding)[0] > 0) + if (intermediate_image_view(x + padding, y + padding)[0] > 0) { float const d1 = a + intermediate_image_view(x - 1 + padding, y + padding)[0]; float const d2 = b + intermediate_image_view(x - 1 + padding, y - 1 + padding)[0]; @@ -209,8 +210,9 @@ void distance_transform_mask_size_three_impl(SrcView const& src_view, } /// \breif Calculates distance transfrom with mask size five. -/// Optimal local distances a, b, c for euclidean approximation from, -/// http://www.cmm.mines-paristech.fr/~marcoteg/cv/publi_pdf/MM_refs/1986_Borgefors_distance.pdf +/// Optimal local distances a, b, c for euclidean approximation from, +/// http://www.cmm.mines-paristech.fr/~marcoteg/cv/publi_pdf/MM_refs/1986_Borgefors_distance.pdf +/// Algorithm from - Principles of Digital Image Processing: Core Algorithms (Section 11.2.2). template void distance_transform_mask_size_five_impl(SrcView const& src_view, DstView const& dst_view, @@ -244,7 +246,7 @@ void distance_transform_mask_size_five_impl(SrcView const& src_view, { for (std::ptrdiff_t x = 0; x < src_view.width(); ++x) { - if(dist_from == distance_from::off_pixels) + if (dist_from == distance_from::off_pixels) { if (src_view(x, y)[0] == src_channel_min) intermediate_image_view(x + padding, y + padding)[0] = 0; @@ -261,15 +263,15 @@ void distance_transform_mask_size_five_impl(SrcView const& src_view, } } - float a, b, c; + float a, b, c; // a, b and c hold elements of the distance mask (see reference). - if(std::is_same::value) + if (std::is_same::value) { a = 1; b = 1.4f; c = 2.19691f; } - else if(std::is_same::value) + else if (std::is_same::value) { a = 1; b = 2; @@ -286,7 +288,7 @@ void distance_transform_mask_size_five_impl(SrcView const& src_view, { for (std::ptrdiff_t x = 0; x < src_view.width(); ++x) { - if(intermediate_image_view(x + padding, y + padding)[0] > 0) + if (intermediate_image_view(x + padding, y + padding)[0] > 0) { float const d1 = c + intermediate_image_view(x - 1 + padding, y - 2 + padding)[0]; float const d2 = c + intermediate_image_view(x + 1 + padding, y - 2 + padding)[0]; @@ -344,47 +346,47 @@ void distance_transform_mask_size_five_impl(SrcView const& src_view, } /// \breif Calculates one-dimensional squared euclidean distance. -/// Reference - http://www.theoryofcomputing.org/articles/v008a019/v008a019.pdf -template -std::vector calculate_squared_euclidean_distance(ImageIterator f, std::ptrdiff_t n) +/// Reference - http://www.theoryofcomputing.org/articles/v008a019/v008a019.pdf (Section 2.1) +template +std::vector compute_1d_squared_euclidean_distance_transform + (ImageViewIterator f, std::ptrdiff_t n) { std::ptrdiff_t k = 0; - std::vector d(n); - std::vector v(n); - std::vector z(n + 1); + std::vector v(n); + std::vector z(n + 1); v[0] = 0; - z[0] = static_cast(-dt_infinite); - z[1] = static_cast(dt_infinite); - for(int q = 1; q < n ; ++q) + z[0] = -dt_infinite; + z[1] = dt_infinite; + for (std::ptrdiff_t q = 1; q < n ; ++q) { float s = static_cast(((f[q][0] + std::pow(q, 2)) - (f[v[k]][0] + std::pow(v[k], 2))) / (2 * q - 2 * v[k])); while (s <= z[k]) { - --k; + k = k - 1; s = static_cast(((f[q][0] + std::pow(q, 2)) - (f[v[k]][0] + std::pow(v[k], 2))) / (2 * q - 2 * v[k])); } - { - k = k + 1; - v[k] = static_cast(q); - z[k] = static_cast(s); - z[k + 1] = static_cast(dt_infinite); - } + k = k + 1; + v[k] = q; + z[k] = s; + z[k + 1] = dt_infinite; } k = 0; - for (int q = 0; q < n; ++q) + std::vector d_f(n); + for (std::ptrdiff_t q = 0; q < n; ++q) { - while(z[k+1] < q) + while (z[k+1] < q) { ++k; } - d[q] = static_cast(std::pow((q - v[k]), 2) + f[v[k]][0]); + d_f[q] = static_cast(std::pow((q - v[k]), 2) + f[v[k]][0]); } - return d; + return d_f; } -/// \breif Calculates precise euclidean distance transform. +/// \breif Calculates two dimensionsal (precise) euclidean distance transform. +/// Reference - http://www.theoryofcomputing.org/articles/v008a019/v008a019.pdf (Section 2.2) template void distance_transorm_precise_impl(SrcView const& src_view, DstView const& dst_view, @@ -411,34 +413,38 @@ void distance_transorm_precise_impl(SrcView const& src_view, } } } - - for (std::ptrdiff_t y = 0; y < intermediate_image_view.height(); ++y) + + // Computes one-dimensional distance transforms along each column of the grid (image). + for (std::ptrdiff_t x = 0; x < intermediate_image_view.width(); ++x) { - typename gray32f_view_t::x_iterator intermediate_row_itr = - intermediate_image_view.row_begin(y); + typename gray32f_view_t::y_iterator intermediate_col_itr = + intermediate_image_view.col_begin(x); - std::vector one_dimensional_squared_distance = calculate_squared_euclidean_distance - (intermediate_row_itr, intermediate_image_view.width()); + std::vector one_dimensional_sq_euclidean_dt_along_column = + compute_1d_squared_euclidean_distance_transform + (intermediate_col_itr, intermediate_image_view.height()); - for (std::ptrdiff_t x = 0; x < intermediate_image_view.width(); ++x) + for (std::ptrdiff_t y = 0; y < intermediate_image_view.height(); ++y) { - intermediate_row_itr[x][0] = one_dimensional_squared_distance[x]; + intermediate_col_itr[y][0] = one_dimensional_sq_euclidean_dt_along_column[y]; } } - for (std::ptrdiff_t x = 0; x < intermediate_image_view.width(); ++x) + // Computes one-dimensional distance transforms along each row of the grid (image). + for (std::ptrdiff_t y = 0; y < intermediate_image_view.height(); ++y) { - typename gray32f_view_t::y_iterator intermediate_col_itr = - intermediate_image_view.col_begin(x); + typename gray32f_view_t::x_iterator intermediate_row_itr = + intermediate_image_view.row_begin(y); - std::vector one_dimensional_squared_distance = calculate_squared_euclidean_distance - (intermediate_col_itr, intermediate_image_view.height()); + std::vector one_dimensional_sq_euclidean_dt_along_row = + compute_1d_squared_euclidean_distance_transform + (intermediate_row_itr, intermediate_image_view.width()); - for (std::ptrdiff_t y = 0; y < intermediate_image_view.height(); ++y) + for (std::ptrdiff_t x = 0; x < intermediate_image_view.width(); ++x) { - intermediate_col_itr[y][0] = one_dimensional_squared_distance[y]; + intermediate_row_itr[x][0] = one_dimensional_sq_euclidean_dt_along_row[x]; - float const distance_transform = std::sqrt(intermediate_col_itr[y][0]); + float const distance_transform = std::sqrt(intermediate_row_itr[x][0]); float constexpr dst_channel_max = (is_same::value) ? dt_infinite : static_cast( @@ -466,7 +472,7 @@ void distance_transorm_precise_impl(SrcView const& src_view, /// /// \param src_view - Source image view. /// \param dst_view - Destination image view. -/// \param dist_from - Specifies from where to find distance from, neareast, 'on' OR 'off' pixels. +/// \param dist_from - Specifies where to find distance from, neareast, 'on' OR 'off' pixels. /// \param dist_type - Specifies formula/method for distance calculation. /// \tparam SrcView - Source image view type. /// \tparam DstView - Destination image view type. From 76c6410c9cb421fc3dba02980624ea3e6b035f39 Mon Sep 17 00:00:00 2001 From: harsh-4 Date: Wed, 23 Jun 2021 14:02:44 +0530 Subject: [PATCH 8/9] improve test file formatting --- example/euclidean_distance_transform.cpp | 6 +- .../image_processing/distance_transform.cpp | 166 +++++++++--------- 2 files changed, 87 insertions(+), 85 deletions(-) diff --git a/example/euclidean_distance_transform.cpp b/example/euclidean_distance_transform.cpp index 2869ccbe9e..6826b77866 100644 --- a/example/euclidean_distance_transform.cpp +++ b/example/euclidean_distance_transform.cpp @@ -1,5 +1,5 @@ // -// Copyright 2021 Harsit Pant +// Copyright 2021 Harshit Pant // // Use, modification and distribution are subject to the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at @@ -76,6 +76,8 @@ int main(int argc, char* argv[]) } else { - std::cerr << "Incorrect options used."; + std::cerr << "This program fails to work with the set of arguments used. Please try again."; } + + return 0; } diff --git a/test/core/image_processing/distance_transform.cpp b/test/core/image_processing/distance_transform.cpp index ebafdf35c8..2c50d1d61f 100644 --- a/test/core/image_processing/distance_transform.cpp +++ b/test/core/image_processing/distance_transform.cpp @@ -1,5 +1,5 @@ // -// Copyright 2021 Harsit Pant +// Copyright 2021 Harshit Pant // // Use, modification and distribution are subject to the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at @@ -32,7 +32,7 @@ void check_for_negligible_varition(ImgView1 const& image_view1, ImgView2 const& for (std::ptrdiff_t x = 0; x < image_view1.width(); ++x) { float variation = std::abs(image_view1(x, y)[0] - image_view2(x, y)[0]); - BOOST_TEST_LT(variation, 0.1); + BOOST_TEST_LT(variation, 0.001); } } } @@ -44,27 +44,27 @@ void test_manhattan_uint8_t_input_uint8_t_output_distance_from_off_pixels() gil::gray8_image_t img_expected(7, 7); gil::gray8_image_t img_out(7, 7); - //test values from wikipedia, in 8 bit binary form + // test values from wikipedia, in 8 bit binary form std::vector> val_in { - {0, 0, 0, 0, 0, 0,0}, - {0,255,255,255,255,255,0}, - {0,255,255,255,255,255,0}, - {0,255,255,255,255,255,0}, - {0,255,255,255,255,255,0}, - {0,255,255,255,255,255,0}, - {0, 0, 0, 0, 0, 0,0} + {0, 0, 0, 0, 0, 0, 0}, + {0, 255, 255, 255, 255, 255, 0}, + {0, 255, 255, 255, 255, 255, 0}, + {0, 255, 255, 255, 255, 255, 0}, + {0, 255, 255, 255, 255, 255, 0}, + {0, 255, 255, 255, 255, 255, 0}, + {0, 0, 0, 0, 0, 0, 0} }; std::vector> val_exp { - {0,0,0,0,0,0,0}, - {0,1,1,1,1,1,0}, - {0,1,2,2,2,1,0}, - {0,1,2,3,2,1,0}, - {0,1,2,2,2,1,0}, - {0,1,1,1,1,1,0}, - {0,0,0,0,0,0,0} + {0, 0, 0, 0, 0, 0, 0}, + {0, 1, 1, 1, 1, 1, 0}, + {0, 1, 2, 2, 2, 1, 0}, + {0, 1, 2, 3, 2, 1, 0}, + {0, 1, 2, 2, 2, 1, 0}, + {0, 1, 1, 1, 1, 1, 0}, + {0, 0, 0, 0, 0, 0, 0} }; fill_image_view(val_in, view(img_in)); @@ -129,7 +129,7 @@ void test_chessboard_uint16_t_input_uint8_t_output_distance_from_on_pixels() fill_image_view(val_exp_manhattan_five, view(img_expected)); gil::distance_transform(view(img_in), view(img_out), gil::distance_from::on_pixels, - gil::distance_type::manhattan, gil::mask_size::five); + gil::distance_type::manhattan, gil::mask_size::five); BOOST_TEST(equal_pixels(const_view(img_out), const_view(img_expected))); @@ -147,7 +147,7 @@ void test_chessboard_uint16_t_input_uint8_t_output_distance_from_on_pixels() fill_image_view(val_exp_euclidean_precise, view(img_expected_float32_t)); gil::distance_transform(view(img_in), view(img_out_float32_t), gil::distance_from::on_pixels, - gil::distance_type::precise_euclidean, gil::mask_size::not_applicable); + gil::distance_type::precise_euclidean, gil::mask_size::not_applicable); BOOST_TEST(equal_pixels(const_view(img_out_float32_t), const_view(img_expected_float32_t))); } @@ -179,7 +179,7 @@ void test_euclidean_approx_and_manhattan_uint8_t_input_float32_t_output_distance std::vector> val_exp1 { - {1.4f, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.4f}, + {1.4f, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.4f}, { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, { 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1}, { 1, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0, 1}, @@ -236,7 +236,7 @@ void test_all_uint8_t_input_float32_t_ouptut_distance_from_off_pixels() std::vector> val_in { - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255} , + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 255, 255, 255, 255}, { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, { 255, 255, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, @@ -255,36 +255,36 @@ void test_all_uint8_t_input_float32_t_ouptut_distance_from_off_pixels() std::vector> val_exp_precise { - {3.6055512f, 3.1622777f, 3, 3.1622777f, 3.6055512f, 4.2426405f, 4.1231055f, 3.1622777f, + {3.6055512f, 3.1622777f, 3, 3.1622777f, 3.6055512f, 4.2426405f, 4.1231055f, 3.1622777f, 2.236068f, 1.4142135f, 1, 1.4142135f, 2.236068f, 3.1622777f, 4.1231055f}, - { 2.828427f, 2.236068f, 2, 2.236068f, 2.828427f, 3.6055512f, 4, - 3, 2, 1, 0, 1, 2, 3, 4}, - { 2.236068f, 1.4142135f, 1, 1.4142135f, 2.236068f, 3.1622777f, 4.1231055f, 3.1622777f, + { 2.828427f, 2.236068f, 2, 2.236068f, 2.828427f, 3.6055512f, 4, + 3, 2, 1, 0, 1, 2, 3, 4}, + { 2.236068f, 1.4142135f, 1, 1.4142135f, 2.236068f, 3.1622777f, 4.1231055f, 3.1622777f, 2.236068f, 1.4142135f, 1, 1.4142135f, 2.236068f, 3.1622777f, 4.1231055f}, - { 2, 1, 0, 1, 2, 3, 4, 3.6055512f, + { 2, 1, 0, 1, 2, 3, 4, 3.6055512f, 2.828427f, 2.236068f, 2, 2.236068f, 2.828427f, 3.6055512f, 4.472136f}, - { 2.236068f, 1.4142135f, 1, 1.4142135f, 2.236068f, 3.1622777f, 4.1231055f, 4.2426405f, + { 2.236068f, 1.4142135f, 1, 1.4142135f, 2.236068f, 3.1622777f, 4.1231055f, 4.2426405f, 3.6055512f, 3.1622777f, 3, 3.1622777f, 3.6055512f, 4.2426405f, 5}, - { 2.828427f, 2.236068f, 2, 2.236068f, 2.828427f, 3.6055512f, 4.472136f, 5, + { 2.828427f, 2.236068f, 2, 2.236068f, 2.828427f, 3.6055512f, 4.472136f, 5, 4.472136f, 4.1231055f, 4, 4.1231055f, 4.472136f, 5, 5.656854f}, - {3.6055512f, 3.1622777f, 3, 3.1622777f, 3.6055512f, 4.2426405f, 5, 5.8309517f, + {3.6055512f, 3.1622777f, 3, 3.1622777f, 3.6055512f, 4.2426405f, 5, 5.8309517f, 5.3851647f, 5.0990195f, 5, 5.0990195f, 5.3851647f, 5.8309517f, 6.4031243f}, - { 4.472136f, 4.1231055f, 4, 4.1231055f, 4.472136f, 5, 5.656854f, 6.4031243f, + { 4.472136f, 4.1231055f, 4, 4.1231055f, 4.472136f, 5, 5.656854f, 6.4031243f, 6.3245554f, 6.0827622f, 6, 6.0827622f, 6.3245554f, 6.7082043f, 7.0000005f}, - {5.3851647f, 5.0990195f, 5, 5.0990195f, 5.3851647f, 5.8309517f, 6.4031243f, 7.0710683f, + {5.3851647f, 5.0990195f, 5, 5.0990195f, 5.3851647f, 5.8309517f, 6.4031243f, 7.0710683f, 7.2801094f, 7.0710683f, 7.0000005f, 6.7082043f, 6.3245554f, 6.0827622f, 6}, - {6.3245554f, 6.0827622f, 6, 6.0827622f, 6.3245554f, 6.7082043f, 7.2111025f, 7.8102503f, + {6.3245554f, 6.0827622f, 6, 6.0827622f, 6.3245554f, 6.7082043f, 7.2111025f, 7.8102503f, 7.8102503f, 7.0710683f, 6.4031243f, 5.8309517f, 5.3851647f, 5.0990195f, 5}, - {7.2801094f, 7.0710683f, 7.0000005f, 7.0710683f, 7.2801094f, 7.6157737f, 8.062258f, 8.062258f, + {7.2801094f, 7.0710683f, 7.0000005f, 7.0710683f, 7.2801094f, 7.6157737f, 8.062258f, 8.062258f, 7.2111025f, 6.4031243f, 5.656854f, 5, 4.472136f, 4.1231055f, 4}, - { 8.246211f, 8.062258f, 8, 8.062258f, 8.246211f, 8.5440035f, 8.5440035f, 7.6157737f, + { 8.246211f, 8.062258f, 8, 8.062258f, 8.246211f, 8.5440035f, 8.5440035f, 7.6157737f, 6.7082043f, 5.8309517f, 5, 4.2426405f, 3.6055512f, 3.1622777f, 3}, - { 9.219544f, 9.055386f, 9, 9.055386f, 9.219544f, 9.219544f, 8.246211f, 7.2801094f, + { 9.219544f, 9.055386f, 9, 9.055386f, 9.219544f, 9.219544f, 8.246211f, 7.2801094f, 6.3245554f, 5.3851647f, 4.472136f, 3.6055512f, 2.828427f, 2.236068f, 2}, - {10.198039f, 10.049875f, 10, 10.049875f, 10.049875f, 9.055386f, 8.062258f, 7.0710683f, + {10.198039f, 10.049875f, 10, 10.049875f, 10.049875f, 9.055386f, 8.062258f, 7.0710683f, 6.0827622f, 5.0990195f, 4.1231055f, 3.1622777f, 2.236068f, 1.4142135f, 1}, - {11.180341f, 11.045361f, 11, 11, 10, 9, 8, 7, - 6, 5, 4, 3, 2, 1, 0} + {11.180341f, 11.045361f, 11, 11, 10, 9, 8, 7, + 6, 5, 4, 3, 2, 1, 0} }; fill_image_view(val_in, view(img_in)); @@ -352,51 +352,51 @@ void test_all_uint8_t_input_float32_t_ouptut_distance_from_off_pixels() std::vector> val_exp_euclidean_five { - {3.5969f, 3.1969f, 3, 3.1969f, 3.5969f, 4.2f, - 4.1969f, 3.1969f, 2.1969f, 1.4f, 1, 1.4f, - 2.1969f, 3.1969f, 4.1969f}, - { 2.8f, 2.1969f, 2, 2.1969f, 2.8f, 3.5969f, - 4, 3, 2, 1, 0, 1, - 2, 3, 4}, - {2.1969f, 1.4f, 1, 1.4f, 2.1969f, 3.1969f, - 4.1969f, 3.1969f, 2.1969f, 1.4f, 1, 1.4f, - 2.1969f, 3.1969f, 4.1969f}, - { 2, 1, 0, 1, 2, 3, - 4, 3.5969f, 2.8f, 2.1969f, 2, 2.1969f, - 2.8f, 3.5969f, 4.3938f}, - {2.1969f, 1.4f, 1, 1.4f, 2.1969f, 3.1969f, - 4.1969f, 4.2f, 3.5969f, 3.1969f, 3, 3.1969f, - 3.5969f, 4.2f, 4.9968996f}, - { 2.8f, 2.1969f, 2, 2.1969f, 2.8f, 3.5969f, - 4.3938f, 4.9968996f, 4.3938f, 4.1969f, 4, 4.1969f, - 4.3938f, 4.9968996f, 5.6f}, - {3.5969f, 3.1969f, 3, 3.1969f, 3.5969f, 4.2f, - 4.9968996f, 5.7938f, 5.3938f, 5.1969f, 5, 5.1969f, - 5.3938f, 5.7938f, 6.3968997f}, - {4.3938f, 4.1969f, 4, 4.1969f, 4.3938f, 4.9968996f, - 5.6f, 6.3968997f, 6.3938f, 6.1969f, 6, 6.1969f, - 6.3938f, 6.5906997f, 7}, - {5.3938f, 5.1969f, 5, 5.1969f, 5.3938f, 5.7938f, - 6.3968997f, 7, 7.3938f, 7.1969f, 7, 6.5906997f, - 6.3938f, 6.1969f, 6}, - {6.3938f, 6.1969f, 6, 6.1969f, 6.3938f, 6.5906997f, - 7.1937995f, 7.7969f, 7.7969f, 7, 6.3968997f, 5.7938f, - 5.3938f, 5.1969f, 5}, - {7.3938f, 7.1969f, 7, 7.1969f, 7.3938f, 7.5906997f, - 7.9907f, 7.9907f, 7.1937995f, 6.3968997f, 5.6f, 4.9968996f, - 4.3938f, 4.1969f, 4}, - {8.3938f, 8.196899f, 8, 8.196899f, 8.3938f, 8.5907f, - 8.5907f, 7.5906997f, 6.5906997f, 5.7938f, 4.9968996f, 4.2f, - 3.5969f, 3.1969f, 3}, - {9.3938f, 9.196899f, 9, 9.196899f, 9.3938f, 9.3938f, - 8.3938f, 7.3938f, 6.3938f, 5.3938f, 4.3938f, 3.5969f, - 2.8f, 2.1969f, 2}, - {10.393799f, 10.196899f, 10, 10.196899f, 10.196899f, 9.196899f, - 8.196899f, 7.1969f, 6.1969f, 5.1969f, 4.1969f, 3.1969f, - 2.1969f, 1.4f, 1}, - {11.393799f, 11.196899f, 11, 11, 10, 9, - 8, 7, 6, 5, 4, 3, - 2, 1, 0} + { 3.5969f, 3.1969f, 3, 3.1969f, 3.5969f, 4.2f, + 4.1969f, 3.1969f, 2.1969f, 1.4f, 1, 1.4f, + 2.1969f, 3.1969f, 4.1969f}, + { 2.8f, 2.1969f, 2, 2.1969f, 2.8f, 3.5969f, + 4, 3, 2, 1, 0, 1, + 2, 3, 4}, + { 2.1969f, 1.4f, 1, 1.4f, 2.1969f, 3.1969f, + 4.1969f, 3.1969f, 2.1969f, 1.4f, 1, 1.4f, + 2.1969f, 3.1969f, 4.1969f}, + { 2, 1, 0, 1, 2, 3, + 4, 3.5969f, 2.8f, 2.1969f, 2, 2.1969f, + 2.8f, 3.5969f, 4.3938f}, + { 2.1969f, 1.4f, 1, 1.4f, 2.1969f, 3.1969f, + 4.1969f, 4.2f, 3.5969f, 3.1969f, 3, 3.1969f, + 3.5969f, 4.2f, 4.9968996f}, + { 2.8f, 2.1969f, 2, 2.1969f, 2.8f, 3.5969f, + 4.3938f, 4.9968996f, 4.3938f, 4.1969f, 4, 4.1969f, + 4.3938f, 4.9968996f, 5.6f}, + { 3.5969f, 3.1969f, 3, 3.1969f, 3.5969f, 4.2f, + 4.9968996f, 5.7938f, 5.3938f, 5.1969f, 5, 5.1969f, + 5.3938f, 5.7938f, 6.3968997f}, + { 4.3938f, 4.1969f, 4, 4.1969f, 4.3938f, 4.9968996f, + 5.6f, 6.3968997f, 6.3938f, 6.1969f, 6, 6.1969f, + 6.3938f, 6.5906997f, 7}, + { 5.3938f, 5.1969f, 5, 5.1969f, 5.3938f, 5.7938f, + 6.3968997f, 7, 7.3938f, 7.1969f, 7, 6.5906997f, + 6.3938f, 6.1969f, 6}, + { 6.3938f, 6.1969f, 6, 6.1969f, 6.3938f, 6.5906997f, + 7.1937995f, 7.7969f, 7.7969f, 7, 6.3968997f, 5.7938f, + 5.3938f, 5.1969f, 5}, + { 7.3938f, 7.1969f, 7, 7.1969f, 7.3938f, 7.5906997f, + 7.9907f, 7.9907f, 7.1937995f, 6.3968997f, 5.6f, 4.9968996f, + 4.3938f, 4.1969f, 4}, + { 8.3938f, 8.196899f, 8, 8.196899f, 8.3938f, 8.5907f, + 8.5907f, 7.5906997f, 6.5906997f, 5.7938f, 4.9968996f, 4.2f, + 3.5969f, 3.1969f, 3}, + { 9.3938f, 9.196899f, 9, 9.196899f, 9.3938f, 9.3938f, + 8.3938f, 7.3938f, 6.3938f, 5.3938f, 4.3938f, 3.5969f, + 2.8f, 2.1969f, 2}, + {10.393799f, 10.196899f, 10, 10.196899f, 10.196899f, 9.196899f, + 8.196899f, 7.1969f, 6.1969f, 5.1969f, 4.1969f, 3.1969f, + 2.1969f, 1.4f, 1}, + {11.393799f, 11.196899f, 11, 11, 10, 9, + 8, 7, 6, 5, 4, 3, + 2, 1, 0} }; fill_image_view(val_in, view(img_in)); From bd907aff9bb30f17b199d0d47c2837fe53f87cb7 Mon Sep 17 00:00:00 2001 From: harsh-4 Date: Wed, 23 Jun 2021 19:33:14 +0530 Subject: [PATCH 9/9] Use clang-format for formatting Uses the clang-format configuration provided in the latest commit of PR #596. Formatting is applied to test file and example file as well. I have made no changes whatsoever after using the clang-format. --- example/euclidean_distance_transform.cpp | 74 +- .../image_processing/distance_transform.hpp | 414 +++--- .../image_processing/distance_transform.cpp | 1173 ++++++++++++----- 3 files changed, 1126 insertions(+), 535 deletions(-) diff --git a/example/euclidean_distance_transform.cpp b/example/euclidean_distance_transform.cpp index 6826b77866..50cac6aab0 100644 --- a/example/euclidean_distance_transform.cpp +++ b/example/euclidean_distance_transform.cpp @@ -5,10 +5,10 @@ // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // +#include #include -#include #include -#include +#include #include @@ -20,8 +20,9 @@ int main(int argc, char* argv[]) { if (argc != 6) { - std::cerr << "usage: " << argv[0] << " " - " "; + std::cerr << "usage: " << argv[0] + << " " + " "; return -1; } @@ -35,43 +36,74 @@ int main(int argc, char* argv[]) if (dist_from == "on_pixels" && dist_type == "euclidean_approximation" && mask_size == "three") { - distance_transform(view(input), view(output), gil::distance_from::on_pixels, - gil::distance_type::euclidean_approximation, gil::mask_size::three); + distance_transform( + view(input), + view(output), + gil::distance_from::on_pixels, + gil::distance_type::euclidean_approximation, + gil::mask_size::three); gil::write_view(argv[2], view(output), gil::png_tag{}); } - else if (dist_from == "off_pixels" && dist_type == "euclidean_approximation" && mask_size == "three") + else if ( + dist_from == "off_pixels" && dist_type == "euclidean_approximation" && mask_size == "three") { - distance_transform(view(input), view(output), gil::distance_from::off_pixels, - gil::distance_type::euclidean_approximation, gil::mask_size::three); + distance_transform( + view(input), + view(output), + gil::distance_from::off_pixels, + gil::distance_type::euclidean_approximation, + gil::mask_size::three); gil::write_view(argv[2], view(output), gil::png_tag{}); } - else if (dist_from == "on_pixels" && dist_type == "euclidean_approximation" && mask_size == "five") + else if ( + dist_from == "on_pixels" && dist_type == "euclidean_approximation" && mask_size == "five") { - distance_transform(view(input), view(output), gil::distance_from::on_pixels, - gil::distance_type::euclidean_approximation, gil::mask_size::five); + distance_transform( + view(input), + view(output), + gil::distance_from::on_pixels, + gil::distance_type::euclidean_approximation, + gil::mask_size::five); gil::write_view(argv[2], view(output), gil::png_tag{}); } - else if (dist_from == "off_pixels" && dist_type == "euclidean_approximation" && mask_size == "five") + else if ( + dist_from == "off_pixels" && dist_type == "euclidean_approximation" && mask_size == "five") { - distance_transform(view(input), view(output), gil::distance_from::off_pixels, - gil::distance_type::euclidean_approximation, gil::mask_size::five); + distance_transform( + view(input), + view(output), + gil::distance_from::off_pixels, + gil::distance_type::euclidean_approximation, + gil::mask_size::five); gil::write_view(argv[2], view(output), gil::png_tag{}); } - else if (dist_from == "on_pixels" && dist_type == "precise_euclidean" && mask_size == "not_applicable") + else if ( + dist_from == "on_pixels" && dist_type == "precise_euclidean" + && mask_size == "not_applicable") { - distance_transform(view(input), view(output), gil::distance_from::on_pixels, - gil::distance_type::precise_euclidean, gil::mask_size::not_applicable); + distance_transform( + view(input), + view(output), + gil::distance_from::on_pixels, + gil::distance_type::precise_euclidean, + gil::mask_size::not_applicable); gil::write_view(argv[2], view(output), gil::png_tag{}); } - else if (dist_from == "off_pixels" && dist_type == "precise_euclidean" && mask_size == "not_applicable") + else if ( + dist_from == "off_pixels" && dist_type == "precise_euclidean" + && mask_size == "not_applicable") { - distance_transform(view(input), view(output), gil::distance_from::off_pixels, - gil::distance_type::precise_euclidean, gil::mask_size::not_applicable); + distance_transform( + view(input), + view(output), + gil::distance_from::off_pixels, + gil::distance_type::precise_euclidean, + gil::mask_size::not_applicable); gil::write_view(argv[2], view(output), gil::png_tag{}); } else diff --git a/include/boost/gil/image_processing/distance_transform.hpp b/include/boost/gil/image_processing/distance_transform.hpp index f39b3ac2cb..96d22e3929 100644 --- a/include/boost/gil/image_processing/distance_transform.hpp +++ b/include/boost/gil/image_processing/distance_transform.hpp @@ -22,26 +22,40 @@ namespace boost { namespace gil { namespace distance_type { -struct euclidean_approximation_t {}; -struct manhattan_t {}; -struct chessboard_t {}; -struct precise_euclidean_t {}; +struct euclidean_approximation_t +{ +}; +struct manhattan_t +{ +}; +struct chessboard_t +{ +}; +struct precise_euclidean_t +{ +}; static euclidean_approximation_t euclidean_approximation; static manhattan_t manhattan; static chessboard_t chessboard; static precise_euclidean_t precise_euclidean; -} // namespace distance_type +} // namespace distance_type namespace mask_size { -struct three_t {}; -struct five_t {}; -struct not_applicable_t {}; +struct three_t +{ +}; +struct five_t +{ +}; +struct not_applicable_t +{ +}; static three_t three; static five_t five; static not_applicable_t not_applicable; -} // namespace mask_size +} // namespace mask_size enum class distance_from { @@ -55,37 +69,43 @@ namespace detail { template struct dt_check_mask_size { - static constexpr bool value = std::is_same::value || - std::is_same::value || - std::is_same::value; + static constexpr bool value = std::is_same::value + || std::is_same::value + || std::is_same::value; }; /// \breif Checks if distance_type used exists. template struct dt_check_distance_type { - static constexpr bool value = - std::is_same::value || - std::is_same::value || - std::is_same::value || - std::is_same::value; + static constexpr bool value + = std::is_same::value + || std::is_same::value + || std::is_same::value + || std::is_same::value; }; /// \breif Checks compatiblity of distance_type and mask_size used together. template -struct dt_parameters_are_compatible : std::true_type {}; +struct dt_parameters_are_compatible : std::true_type +{ +}; template -struct dt_parameters_are_compatible - : std::false_type {}; +struct dt_parameters_are_compatible : std::false_type +{ +}; template -struct dt_parameters_are_compatible - : std::false_type {}; +struct dt_parameters_are_compatible : std::false_type +{ +}; template <> -struct dt_parameters_are_compatible - : std::true_type {}; +struct dt_parameters_are_compatible + : std::true_type +{ +}; /// \breif Value used as infinite distance for distance_transform. float constexpr dt_infinite = 1000000000; @@ -94,30 +114,31 @@ float constexpr dt_infinite = 1000000000; /// Optimal local distances a, b for euclidean approximation from, /// http://www.cmm.mines-paristech.fr/~marcoteg/cv/publi_pdf/MM_refs/1986_Borgefors_distance.pdf /// Algorithm from - Principles of Digital Image Processing: Core Algorithms (Section 11.2.2). -template -void distance_transform_mask_size_three_impl(SrcView const& src_view, - DstView const& dst_view, - distance_from dist_from, - DistanceType /*Passes type*/) +template +void distance_transform_mask_size_three_impl( + SrcView const& src_view, + DstView const& dst_view, + distance_from dist_from, + DistanceType /*Passes type*/) { int const padding = 1; - gray32f_image_t intermediate_image(src_view.width() + 2 * padding, - src_view.height() + 2 * padding); - gray32f_view_t intermediate_image_view = view(intermediate_image); + gray32f_image_t intermediate_image( + src_view.width() + 2 * padding, src_view.height() + 2 * padding); + gray32f_view_t intermediate_image_view = view(intermediate_image); for (std::ptrdiff_t x = 0; x < intermediate_image_view.width(); ++x) { - intermediate_image_view(x, 0)[0] = dt_infinite ; + intermediate_image_view(x, 0)[0] = dt_infinite; intermediate_image_view(x, intermediate_image_view.height() - 1)[0] = dt_infinite; } for (std::ptrdiff_t y = 0; y < intermediate_image_view.height(); ++y) { - intermediate_image_view(0, y)[0] = dt_infinite ; - intermediate_image_view(intermediate_image_view.width() - 1, y)[0] = dt_infinite ; + intermediate_image_view(0, y)[0] = dt_infinite; + intermediate_image_view(intermediate_image_view.width() - 1, y)[0] = dt_infinite; } - float constexpr src_channel_min = - (std::numeric_limits ::type>::min)(); + float constexpr src_channel_min + = (std::numeric_limits::type>::min)(); for (std::ptrdiff_t y = 0; y < src_view.height(); ++y) { @@ -127,33 +148,33 @@ void distance_transform_mask_size_three_impl(SrcView const& src_view, { if (src_view(x, y)[0] == src_channel_min) intermediate_image_view(x + padding, y + padding)[0] = 0; - else + else intermediate_image_view(x + padding, y + padding)[0] = dt_infinite; } else { - if (src_view(x, y)[0] != src_channel_min) + if (src_view(x, y)[0] != src_channel_min) intermediate_image_view(x + padding, y + padding)[0] = 0; - else + else intermediate_image_view(x + padding, y + padding)[0] = dt_infinite; } } } - float a, b; // a and b hold elements of the distance mask (see reference). + float a, b; // a and b hold elements of the distance mask (see reference). if (std::is_same::value) { a = 0.95509f; b = 1.36930f; } - else if(std::is_same::value) - { + else if (std::is_same::value) + { a = 1; b = 2; } else - { + { a = 1; b = 1; } @@ -163,10 +184,10 @@ void distance_transform_mask_size_three_impl(SrcView const& src_view, for (std::ptrdiff_t x = 0; x < src_view.width(); ++x) { if (intermediate_image_view(x + padding, y + padding)[0] > 0) - { - float const d1 = a + intermediate_image_view(x - 1 + padding, y + padding)[0]; + { + float const d1 = a + intermediate_image_view(x - 1 + padding, y + padding)[0]; float const d2 = b + intermediate_image_view(x - 1 + padding, y - 1 + padding)[0]; - float const d3 = a + intermediate_image_view(x + padding, y - 1 + padding)[0]; + float const d3 = a + intermediate_image_view(x + padding, y - 1 + padding)[0]; float const d4 = b + intermediate_image_view(x + 1 + padding, y - 1 + padding)[0]; intermediate_image_view(x + padding, y + padding)[0] = std::min({d1, d2, d3, d4}); @@ -180,48 +201,57 @@ void distance_transform_mask_size_three_impl(SrcView const& src_view, { if (intermediate_image_view(x + padding, y + padding)[0] > 0) { - float const d1 = a + intermediate_image_view(x + 1 + padding, y + padding)[0]; + float const d1 = a + intermediate_image_view(x + 1 + padding, y + padding)[0]; float const d2 = b + intermediate_image_view(x + 1 + padding, y + 1 + padding)[0]; - float const d3 = a + intermediate_image_view(x + padding, y + 1 + padding)[0]; + float const d3 = a + intermediate_image_view(x + padding, y + 1 + padding)[0]; float const d4 = b + intermediate_image_view(x - 1 + padding, y + 1 + padding)[0]; - intermediate_image_view(x + padding, y + padding)[0] = std::min({ d1, d2, d3, d4, - static_cast(intermediate_image_view(x + padding, y + padding)[0]) }); - - float const distance_transform = intermediate_image_view - (x + padding, y + padding)[0]; - - float constexpr dst_channel_max = - (is_same::value) ? dt_infinite : static_cast( - (std::numeric_limits::type>::max)()); - - float constexpr dst_channel_min = - (is_same::value) ? 0.f : static_cast( - (std::numeric_limits::type>::min)()); - - dst_view(x, y)[0] = - static_cast::type>( - (distance_transform > dst_channel_max) ? dst_channel_max : - (distance_transform < dst_channel_min) ? dst_channel_min : - distance_transform); + intermediate_image_view(x + padding, y + padding)[0] = std::min( + {d1, + d2, + d3, + d4, + static_cast(intermediate_image_view(x + padding, y + padding)[0])}); + + float const distance_transform + = intermediate_image_view(x + padding, y + padding)[0]; + + float constexpr dst_channel_max + = (is_same::value) + ? dt_infinite + : static_cast( + (std::numeric_limits::type>::max)()); + + float constexpr dst_channel_min + = (is_same::value) + ? 0.f + : static_cast( + (std::numeric_limits::type>::min)()); + + dst_view(x, y)[0] + = static_cast::type>( + (distance_transform > dst_channel_max) ? dst_channel_max + : (distance_transform < dst_channel_min) ? dst_channel_min + : distance_transform); } } } -} +} /// \breif Calculates distance transfrom with mask size five. /// Optimal local distances a, b, c for euclidean approximation from, /// http://www.cmm.mines-paristech.fr/~marcoteg/cv/publi_pdf/MM_refs/1986_Borgefors_distance.pdf /// Algorithm from - Principles of Digital Image Processing: Core Algorithms (Section 11.2.2). -template -void distance_transform_mask_size_five_impl(SrcView const& src_view, - DstView const& dst_view, - distance_from dist_from, - DistanceType /*Passes type*/) +template +void distance_transform_mask_size_five_impl( + SrcView const& src_view, + DstView const& dst_view, + distance_from dist_from, + DistanceType /*Passes type*/) { int const padding = 2; - gray32f_image_t intermediate_image(src_view.width() + 2 * padding, - src_view.height() + 2 * padding); + gray32f_image_t intermediate_image( + src_view.width() + 2 * padding, src_view.height() + 2 * padding); gray32f_view_t intermediate_image_view = view(intermediate_image); for (std::ptrdiff_t x = 0; x < intermediate_image_view.width(); ++x) @@ -233,14 +263,14 @@ void distance_transform_mask_size_five_impl(SrcView const& src_view, } for (std::ptrdiff_t y = 0; y < intermediate_image_view.height(); ++y) { - intermediate_image_view(0, y)[0] = dt_infinite ; - intermediate_image_view(1, y)[0] = dt_infinite ; + intermediate_image_view(0, y)[0] = dt_infinite; + intermediate_image_view(1, y)[0] = dt_infinite; intermediate_image_view(intermediate_image_view.width() - 1, y)[0] = dt_infinite; intermediate_image_view(intermediate_image_view.width() - 2, y)[0] = dt_infinite; } - float constexpr src_channel_min = - (std::numeric_limits::type>::min)(); + float constexpr src_channel_min + = (std::numeric_limits::type>::min)(); for (std::ptrdiff_t y = 0; y < src_view.height(); ++y) { @@ -263,7 +293,7 @@ void distance_transform_mask_size_five_impl(SrcView const& src_view, } } - float a, b, c; // a, b and c hold elements of the distance mask (see reference). + float a, b, c; // a, b and c hold elements of the distance mask (see reference). if (std::is_same::value) { @@ -272,13 +302,13 @@ void distance_transform_mask_size_five_impl(SrcView const& src_view, c = 2.19691f; } else if (std::is_same::value) - { + { a = 1; b = 2; c = 3; } else - { + { a = 1; b = 1; c = 2; @@ -289,18 +319,18 @@ void distance_transform_mask_size_five_impl(SrcView const& src_view, for (std::ptrdiff_t x = 0; x < src_view.width(); ++x) { if (intermediate_image_view(x + padding, y + padding)[0] > 0) - { + { float const d1 = c + intermediate_image_view(x - 1 + padding, y - 2 + padding)[0]; float const d2 = c + intermediate_image_view(x + 1 + padding, y - 2 + padding)[0]; float const d3 = c + intermediate_image_view(x - 2 + padding, y - 1 + padding)[0]; float const d4 = b + intermediate_image_view(x - 1 + padding, y - 1 + padding)[0]; - float const d5 = a + intermediate_image_view(x + padding, y - 1 + padding)[0]; + float const d5 = a + intermediate_image_view(x + padding, y - 1 + padding)[0]; float const d6 = b + intermediate_image_view(x + 1 + padding, y - 1 + padding)[0]; float const d7 = c + intermediate_image_view(x + 2 + padding, y - 1 + padding)[0]; - float const d8 = a + intermediate_image_view(x - 1 + padding, y + padding)[0]; + float const d8 = a + intermediate_image_view(x - 1 + padding, y + padding)[0]; - intermediate_image_view(x + padding, y + padding)[0] = - std::min({d1, d2, d3, d4, d5, d6, d7, d8}); + intermediate_image_view(x + padding, y + padding)[0] + = std::min({d1, d2, d3, d4, d5, d6, d7, d8}); } } } @@ -315,41 +345,53 @@ void distance_transform_mask_size_five_impl(SrcView const& src_view, float const d2 = c + intermediate_image_view(x - 1 + padding, y + 2 + padding)[0]; float const d3 = c + intermediate_image_view(x + 2 + padding, y + 1 + padding)[0]; float const d4 = b + intermediate_image_view(x + 1 + padding, y + 1 + padding)[0]; - float const d5 = a + intermediate_image_view(x + padding, y + 1 + padding)[0]; + float const d5 = a + intermediate_image_view(x + padding, y + 1 + padding)[0]; float const d6 = b + intermediate_image_view(x - 1 + padding, y + 1 + padding)[0]; float const d7 = c + intermediate_image_view(x - 2 + padding, y + 1 + padding)[0]; - float const d8 = a + intermediate_image_view(x + 1 + padding, y + padding)[0]; - - intermediate_image_view(x + padding, y + padding)[0] = - std::min({ d1, d2, d3, d4, d5, d6, d7, d8, - static_cast(intermediate_image_view(x + padding, y + padding)[0]) }); - - float const distance_transform = - intermediate_image_view (x + padding, y + padding)[0]; - - float constexpr dst_channel_max = - (is_same::value) ? dt_infinite : static_cast( - (std::numeric_limits::type>::max)()); - - float constexpr dst_channel_min = - (is_same::value) ? 0.f : static_cast( - (std::numeric_limits::type>::min)()); - - dst_view(x, y)[0] = - static_cast::type>( - (distance_transform > dst_channel_max) ? dst_channel_max : - (distance_transform < dst_channel_min) ? dst_channel_min : - distance_transform); + float const d8 = a + intermediate_image_view(x + 1 + padding, y + padding)[0]; + + intermediate_image_view(x + padding, y + padding)[0] = std::min( + {d1, + d2, + d3, + d4, + d5, + d6, + d7, + d8, + static_cast(intermediate_image_view(x + padding, y + padding)[0])}); + + float const distance_transform + = intermediate_image_view(x + padding, y + padding)[0]; + + float constexpr dst_channel_max + = (is_same::value) + ? dt_infinite + : static_cast( + (std::numeric_limits::type>::max)()); + + float constexpr dst_channel_min + = (is_same::value) + ? 0.f + : static_cast( + (std::numeric_limits::type>::min)()); + + dst_view(x, y)[0] + = static_cast::type>( + (distance_transform > dst_channel_max) ? dst_channel_max + : (distance_transform < dst_channel_min) ? dst_channel_min + : distance_transform); } } } -} +} /// \breif Calculates one-dimensional squared euclidean distance. /// Reference - http://www.theoryofcomputing.org/articles/v008a019/v008a019.pdf (Section 2.1) -template -std::vector compute_1d_squared_euclidean_distance_transform - (ImageViewIterator f, std::ptrdiff_t n) +template +std::vector compute_1d_squared_euclidean_distance_transform( + ImageViewIterator f, + std::ptrdiff_t n) { std::ptrdiff_t k = 0; std::vector v(n); @@ -357,27 +399,28 @@ std::vector compute_1d_squared_euclidean_distance_transform v[0] = 0; z[0] = -dt_infinite; z[1] = dt_infinite; - for (std::ptrdiff_t q = 1; q < n ; ++q) + for (std::ptrdiff_t q = 1; q < n; ++q) { - float s = static_cast(((f[q][0] + std::pow(q, 2)) - - (f[v[k]][0] + std::pow(v[k], 2))) / (2 * q - 2 * v[k])); + float s = static_cast( + ((f[q][0] + std::pow(q, 2)) - (f[v[k]][0] + std::pow(v[k], 2))) / (2 * q - 2 * v[k])); while (s <= z[k]) { k = k - 1; - s = static_cast(((f[q][0] + std::pow(q, 2)) - - (f[v[k]][0] + std::pow(v[k], 2))) / (2 * q - 2 * v[k])); + s = static_cast( + ((f[q][0] + std::pow(q, 2)) - (f[v[k]][0] + std::pow(v[k], 2))) + / (2 * q - 2 * v[k])); } - k = k + 1; - v[k] = q; - z[k] = s; + k = k + 1; + v[k] = q; + z[k] = s; z[k + 1] = dt_infinite; } k = 0; - std::vector d_f(n); + std::vector d_f(n); for (std::ptrdiff_t q = 0; q < n; ++q) { - while (z[k+1] < q) - { + while (z[k + 1] < q) + { ++k; } d_f[q] = static_cast(std::pow((q - v[k]), 2) + f[v[k]][0]); @@ -387,15 +430,16 @@ std::vector compute_1d_squared_euclidean_distance_transform /// \breif Calculates two dimensionsal (precise) euclidean distance transform. /// Reference - http://www.theoryofcomputing.org/articles/v008a019/v008a019.pdf (Section 2.2) -template -void distance_transorm_precise_impl(SrcView const& src_view, - DstView const& dst_view, - distance_from dist_from) +template +void distance_transorm_precise_impl( + SrcView const& src_view, + DstView const& dst_view, + distance_from dist_from) { gray32f_image_t intermediate_image(src_view.dimensions()); - gray32f_view_t intermediate_image_view = view(intermediate_image); - float constexpr src_channel_min = - (std::numeric_limits::type>::min)(); + gray32f_view_t intermediate_image_view = view(intermediate_image); + float constexpr src_channel_min + = (std::numeric_limits::type>::min)(); for (std::ptrdiff_t y = 0; y < src_view.height(); ++y) { @@ -403,26 +447,30 @@ void distance_transorm_precise_impl(SrcView const& src_view, { if (dist_from == distance_from::off_pixels) { - if (src_view(x, y)[0] == src_channel_min) intermediate_image_view(x, y)[0] = 0; - else intermediate_image_view(x, y)[0] = dt_infinite; + if (src_view(x, y)[0] == src_channel_min) + intermediate_image_view(x, y)[0] = 0; + else + intermediate_image_view(x, y)[0] = dt_infinite; } else { - if (src_view(x, y)[0] != src_channel_min) intermediate_image_view(x, y)[0] = 0; - else intermediate_image_view(x, y)[0] = dt_infinite; + if (src_view(x, y)[0] != src_channel_min) + intermediate_image_view(x, y)[0] = 0; + else + intermediate_image_view(x, y)[0] = dt_infinite; } } } - + // Computes one-dimensional distance transforms along each column of the grid (image). for (std::ptrdiff_t x = 0; x < intermediate_image_view.width(); ++x) { - typename gray32f_view_t::y_iterator intermediate_col_itr = - intermediate_image_view.col_begin(x); + typename gray32f_view_t::y_iterator intermediate_col_itr + = intermediate_image_view.col_begin(x); - std::vector one_dimensional_sq_euclidean_dt_along_column = - compute_1d_squared_euclidean_distance_transform - (intermediate_col_itr, intermediate_image_view.height()); + std::vector one_dimensional_sq_euclidean_dt_along_column + = compute_1d_squared_euclidean_distance_transform( + intermediate_col_itr, intermediate_image_view.height()); for (std::ptrdiff_t y = 0; y < intermediate_image_view.height(); ++y) { @@ -433,43 +481,47 @@ void distance_transorm_precise_impl(SrcView const& src_view, // Computes one-dimensional distance transforms along each row of the grid (image). for (std::ptrdiff_t y = 0; y < intermediate_image_view.height(); ++y) { - typename gray32f_view_t::x_iterator intermediate_row_itr = - intermediate_image_view.row_begin(y); + typename gray32f_view_t::x_iterator intermediate_row_itr + = intermediate_image_view.row_begin(y); - std::vector one_dimensional_sq_euclidean_dt_along_row = - compute_1d_squared_euclidean_distance_transform - (intermediate_row_itr, intermediate_image_view.width()); + std::vector one_dimensional_sq_euclidean_dt_along_row + = compute_1d_squared_euclidean_distance_transform( + intermediate_row_itr, intermediate_image_view.width()); for (std::ptrdiff_t x = 0; x < intermediate_image_view.width(); ++x) { intermediate_row_itr[x][0] = one_dimensional_sq_euclidean_dt_along_row[x]; - - float const distance_transform = std::sqrt(intermediate_row_itr[x][0]); - float constexpr dst_channel_max = - (is_same::value) ? dt_infinite : static_cast( - (std::numeric_limits::type>::max)()); - - float constexpr dst_channel_min = - (is_same::value) ? 0.f : static_cast( - (std::numeric_limits::type>::min)()); + float const distance_transform = std::sqrt(intermediate_row_itr[x][0]); - dst_view(x, y)[0] = - static_cast::type>( - (distance_transform > dst_channel_max) ? dst_channel_max : - (distance_transform < dst_channel_min) ? dst_channel_min : - distance_transform); + float constexpr dst_channel_max + = (is_same::value) + ? dt_infinite + : static_cast( + (std::numeric_limits::type>::max)()); + + float constexpr dst_channel_min + = (is_same::value) + ? 0.f + : static_cast( + (std::numeric_limits::type>::min)()); + + dst_view(x, y)[0] + = static_cast::type>( + (distance_transform > dst_channel_max) ? dst_channel_max + : (distance_transform < dst_channel_min) ? dst_channel_min + : distance_transform); } } } -} // namespace detail +} // namespace detail /// \addtogroup ImageProcessing /// @{ -/// \breif Calculates distance to the nearest 'on' OR 'off' pixel (as specified), +/// \breif Calculates distance to the nearest 'on' OR 'off' pixel (as specified), /// for each pixel of a binary image. -/// +/// /// \param src_view - Source image view. /// \param dst_view - Destination image view. /// \param dist_from - Specifies where to find distance from, neareast, 'on' OR 'off' pixels. @@ -478,25 +530,31 @@ void distance_transorm_precise_impl(SrcView const& src_view, /// \tparam DstView - Destination image view type. /// \tparam DistanceType - Distance type choosen. /// \tparam MaskSize - Mask size choosen. -template -void distance_transform(SrcView const& src_view, DstView const& dst_view, distance_from dist_from, - DistanceType dist_type, MaskSize /*Passes type*/) +template +void distance_transform( + SrcView const& src_view, + DstView const& dst_view, + distance_from dist_from, + DistanceType dist_type, + MaskSize /*Passes type*/) { gil_function_requires>(); gil_function_requires>(); - static_assert(std::is_same::type>::value && - std::is_same::type>::value, - "Source and destination image views must use gray color space."); + static_assert( + std::is_same::type>::value + && std::is_same::type>::value, + "Source and destination image views must use gray color space."); - static_assert(detail::dt_check_distance_type::value, - "Distance type not recognized."); + static_assert( + detail::dt_check_distance_type::value, "Distance type not recognized."); static_assert(detail::dt_check_mask_size::value, "Mask Size not recognized."); // Generates compile time error if invalid combination of distance_type and mask_size is used. - static_assert(detail::dt_parameters_are_compatible::value, - "distance_transform is incompatible with combination of " - "distance_type and mask_size used."); + static_assert( + detail::dt_parameters_are_compatible::value, + "distance_transform is incompatible with combination of " + "distance_type and mask_size used."); BOOST_ASSERT(src_view.dimensions() == dst_view.dimensions()); @@ -510,5 +568,5 @@ void distance_transform(SrcView const& src_view, DstView const& dst_view, distan distance_transorm_precise_impl(src_view, dst_view, dist_from); } /// @} -}} // namespace boost::gil -#endif // BOOST_GIL_IMAGE_PROCESSING_DISTANCE_TRANSFORM_HPP +}} // namespace boost::gil +#endif // BOOST_GIL_IMAGE_PROCESSING_DISTANCE_TRANSFORM_HPP diff --git a/test/core/image_processing/distance_transform.cpp b/test/core/image_processing/distance_transform.cpp index 2c50d1d61f..effe58fe1d 100644 --- a/test/core/image_processing/distance_transform.cpp +++ b/test/core/image_processing/distance_transform.cpp @@ -5,15 +5,17 @@ // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // -#include #include +#include + #include + #include namespace gil = boost::gil; -template -void fill_image_view(std::vector >& values, ImgView image_view) +template +void fill_image_view(std::vector>& values, ImgView image_view) { for (std::ptrdiff_t y = 0; y < image_view.height(); ++y) { @@ -24,8 +26,8 @@ void fill_image_view(std::vector >& values, ImgView image_view) } } -template -void check_for_negligible_varition(ImgView1 const& image_view1, ImgView2 const& image_view2) +template +void check_for_negligible_varition(ImgView1 const& image_view1, ImgView2 const& image_view2) { for (std::ptrdiff_t y = 0; y < image_view1.height(); ++y) { @@ -39,39 +41,38 @@ void check_for_negligible_varition(ImgView1 const& image_view1, ImgView2 const& void test_manhattan_uint8_t_input_uint8_t_output_distance_from_off_pixels() { - gil::gray8_image_t img_in(7, 7); gil::gray8_image_t img_expected(7, 7); gil::gray8_image_t img_out(7, 7); // test values from wikipedia, in 8 bit binary form - std::vector> val_in - { - {0, 0, 0, 0, 0, 0, 0}, + std::vector> val_in{ + {0, 0, 0, 0, 0, 0, 0}, {0, 255, 255, 255, 255, 255, 0}, {0, 255, 255, 255, 255, 255, 0}, {0, 255, 255, 255, 255, 255, 0}, {0, 255, 255, 255, 255, 255, 0}, {0, 255, 255, 255, 255, 255, 0}, - {0, 0, 0, 0, 0, 0, 0} - }; + {0, 0, 0, 0, 0, 0, 0}}; - std::vector> val_exp - { + std::vector> val_exp{ {0, 0, 0, 0, 0, 0, 0}, {0, 1, 1, 1, 1, 1, 0}, {0, 1, 2, 2, 2, 1, 0}, {0, 1, 2, 3, 2, 1, 0}, {0, 1, 2, 2, 2, 1, 0}, {0, 1, 1, 1, 1, 1, 0}, - {0, 0, 0, 0, 0, 0, 0} - }; + {0, 0, 0, 0, 0, 0, 0}}; fill_image_view(val_in, view(img_in)); fill_image_view(val_exp, view(img_expected)); - gil::distance_transform(view(img_in), view(img_out), gil::distance_from::off_pixels, - gil::distance_type::manhattan, gil::mask_size::three); + gil::distance_transform( + view(img_in), + view(img_out), + gil::distance_from::off_pixels, + gil::distance_type::manhattan, + gil::mask_size::three); BOOST_TEST(equal_pixels(const_view(img_out), const_view(img_expected))); } @@ -85,69 +86,73 @@ void test_chessboard_uint16_t_input_uint8_t_output_distance_from_on_pixels() gil::gray32f_image_t img_expected_float32_t(7, 7); gil::gray32f_image_t img_out_float32_t(7, 7); - std::vector> val_in - { - {0, 65535, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 65535, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0} - }; - - std::vector> val_exp_chessboard_three - { + std::vector> val_in{ + {0, 65535, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 65535, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0}}; + + std::vector> val_exp_chessboard_three{ {1, 0, 1, 2, 3, 4, 4}, {1, 1, 1, 2, 3, 3, 3}, {2, 2, 2, 2, 2, 2, 3}, {3, 2, 1, 1, 1, 2, 3}, {3, 2, 1, 0, 1, 2, 3}, {3, 2, 1, 1, 1, 2, 3}, - {3, 2, 2, 2, 2, 2, 3} - }; + {3, 2, 2, 2, 2, 2, 3}}; fill_image_view(val_in, view(img_in)); fill_image_view(val_exp_chessboard_three, view(img_expected)); - gil::distance_transform(view(img_in), view(img_out), gil::distance_from::on_pixels, - gil::distance_type::chessboard, gil::mask_size::three); + gil::distance_transform( + view(img_in), + view(img_out), + gil::distance_from::on_pixels, + gil::distance_type::chessboard, + gil::mask_size::three); BOOST_TEST(equal_pixels(const_view(img_out), const_view(img_expected))); - std::vector> val_exp_manhattan_five - { + std::vector> val_exp_manhattan_five{ {1, 0, 1, 2, 3, 4, 5}, {2, 1, 2, 3, 4, 5, 6}, {3, 2, 3, 2, 3, 4, 5}, {4, 3, 2, 1, 2, 3, 4}, {3, 2, 1, 0, 1, 2, 3}, {4, 3, 2, 1, 2, 3, 4}, - {5, 4, 3, 2, 3, 4, 5} - }; + {5, 4, 3, 2, 3, 4, 5}}; fill_image_view(val_exp_manhattan_five, view(img_expected)); - gil::distance_transform(view(img_in), view(img_out), gil::distance_from::on_pixels, - gil::distance_type::manhattan, gil::mask_size::five); + gil::distance_transform( + view(img_in), + view(img_out), + gil::distance_from::on_pixels, + gil::distance_type::manhattan, + gil::mask_size::five); BOOST_TEST(equal_pixels(const_view(img_out), const_view(img_expected))); - std::vector> val_exp_euclidean_precise - { - { 1, 0, 1, 2, 3, 4, 5}, - {1.4142135f, 1, 1.4142135f, 2.236068f, 3.1622777f, 3.6055512f, 4.2426405f}, - { 2.236068f, 2, 2.236068f, 2, 2.236068f, 2.828427f, 3.6055512f}, - {3.1622777f, 2.236068f, 1.4142135f, 1, 1.4142135f, 2.236068f, 3.1622777f}, - { 3, 2, 1, 0, 1, 2, 3}, - {3.1622777f, 2.236068f, 1.4142135f, 1, 1.4142135f, 2.236068f, 3.1622777f}, - {3.6055512f, 2.828427f, 2.236068f, 2, 2.236068f, 2.828427f, 3.6055512f} - }; + std::vector> val_exp_euclidean_precise{ + {1, 0, 1, 2, 3, 4, 5}, + {1.4142135f, 1, 1.4142135f, 2.236068f, 3.1622777f, 3.6055512f, 4.2426405f}, + {2.236068f, 2, 2.236068f, 2, 2.236068f, 2.828427f, 3.6055512f}, + {3.1622777f, 2.236068f, 1.4142135f, 1, 1.4142135f, 2.236068f, 3.1622777f}, + {3, 2, 1, 0, 1, 2, 3}, + {3.1622777f, 2.236068f, 1.4142135f, 1, 1.4142135f, 2.236068f, 3.1622777f}, + {3.6055512f, 2.828427f, 2.236068f, 2, 2.236068f, 2.828427f, 3.6055512f}}; fill_image_view(val_exp_euclidean_precise, view(img_expected_float32_t)); - gil::distance_transform(view(img_in), view(img_out_float32_t), gil::distance_from::on_pixels, - gil::distance_type::precise_euclidean, gil::mask_size::not_applicable); + gil::distance_transform( + view(img_in), + view(img_out_float32_t), + gil::distance_from::on_pixels, + gil::distance_type::precise_euclidean, + gil::mask_size::not_applicable); BOOST_TEST(equal_pixels(const_view(img_out_float32_t), const_view(img_expected_float32_t))); } @@ -158,46 +163,41 @@ void test_euclidean_approx_and_manhattan_uint8_t_input_float32_t_output_distance gil::gray32f_image_t img_expected(15, 15); gil::gray32f_image_t img_out(15, 15); - std::vector> val_in - { + std::vector> val_in{ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, - {255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255}, - {255, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 255}, - {255, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 255}, - {255, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 255}, - {255, 0, 255, 255, 255, 0, 0, 0, 0, 0, 255, 255, 255, 0, 255}, - {255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255}, - {255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255}, - {255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255}, - {255, 0, 255, 255, 255, 0, 0, 0, 0, 0, 255, 255, 255, 0, 255}, - {255, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 255}, - {255, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 255}, - {255, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 255}, - {255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255}, - {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255} - }; - - std::vector> val_exp1 - { - {1.4f, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.4f}, - { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, - { 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1}, - { 1, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0, 1}, - { 1, 0, 1, 2, 1.4f, 1, 1, 1, 1, 1, 1.4f, 2, 1, 0, 1}, - { 1, 0, 1, 2, 1, 0, 0, 0, 0, 0, 1, 2, 1, 0, 1}, - { 1, 0, 1, 2, 1, 0, 1, 1, 1, 0, 1, 2, 1, 0, 1}, - { 1, 0, 1, 2, 1, 0, 1, 2, 1, 0, 1, 2, 1, 0, 1}, - { 1, 0, 1, 2, 1, 0, 1, 1, 1, 0, 1, 2, 1, 0, 1}, - { 1, 0, 1, 2, 1, 0, 0, 0, 0, 0, 1, 2, 1, 0, 1}, - { 1, 0, 1, 2, 1.4f, 1, 1, 1, 1, 1, 1.4f, 2, 1, 0, 1}, - { 1, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0, 1}, - { 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1}, - { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, - {1.4f, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.4f} - }; - - std::vector> val_exp2 - { + {255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255}, + {255, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 255}, + {255, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 255}, + {255, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 255}, + {255, 0, 255, 255, 255, 0, 0, 0, 0, 0, 255, 255, 255, 0, 255}, + {255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255}, + {255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255}, + {255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255}, + {255, 0, 255, 255, 255, 0, 0, 0, 0, 0, 255, 255, 255, 0, 255}, + {255, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 255}, + {255, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 255}, + {255, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 255}, + {255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255}, + {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}}; + + std::vector> val_exp1{ + {1.4f, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.4f}, + {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, + {1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1}, + {1, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0, 1}, + {1, 0, 1, 2, 1.4f, 1, 1, 1, 1, 1, 1.4f, 2, 1, 0, 1}, + {1, 0, 1, 2, 1, 0, 0, 0, 0, 0, 1, 2, 1, 0, 1}, + {1, 0, 1, 2, 1, 0, 1, 1, 1, 0, 1, 2, 1, 0, 1}, + {1, 0, 1, 2, 1, 0, 1, 2, 1, 0, 1, 2, 1, 0, 1}, + {1, 0, 1, 2, 1, 0, 1, 1, 1, 0, 1, 2, 1, 0, 1}, + {1, 0, 1, 2, 1, 0, 0, 0, 0, 0, 1, 2, 1, 0, 1}, + {1, 0, 1, 2, 1.4f, 1, 1, 1, 1, 1, 1.4f, 2, 1, 0, 1}, + {1, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0, 1}, + {1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1}, + {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, + {1.4f, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.4f}}; + + std::vector> val_exp2{ {2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2}, {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, {1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1}, @@ -212,20 +212,26 @@ void test_euclidean_approx_and_manhattan_uint8_t_input_float32_t_output_distance {1, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0, 1}, {1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1}, {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, - {2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2} - }; + {2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2}}; fill_image_view(val_in, view(img_in)); fill_image_view(val_exp1, view(img_expected)); - gil::distance_transform(view(img_in), view(img_out), gil::distance_from::off_pixels, - gil::distance_type::euclidean_approximation, gil::mask_size::five); + gil::distance_transform( + view(img_in), + view(img_out), + gil::distance_from::off_pixels, + gil::distance_type::euclidean_approximation, + gil::mask_size::five); BOOST_TEST(equal_pixels(const_view(img_out), const_view(img_expected))); fill_image_view(val_exp2, view(img_expected)); - gil::distance_transform(view(img_in), view(img_out), gil::distance_from::off_pixels, - gil::distance_type::manhattan, gil::mask_size::five); + gil::distance_transform( + view(img_in), + view(img_out), + gil::distance_from::off_pixels, + gil::distance_type::manhattan, + gil::mask_size::five); BOOST_TEST(equal_pixels(const_view(img_out), const_view(img_expected))); - } void test_all_uint8_t_input_float32_t_ouptut_distance_from_off_pixels() @@ -234,278 +240,773 @@ void test_all_uint8_t_input_float32_t_ouptut_distance_from_off_pixels() gil::gray32f_image_t img_expected(15, 15); gil::gray32f_image_t img_out(15, 15); - std::vector> val_in - { - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 255, 255, 255, 255}, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, - { 255, 255, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0} - }; - - std::vector> val_exp_precise - { - {3.6055512f, 3.1622777f, 3, 3.1622777f, 3.6055512f, 4.2426405f, 4.1231055f, 3.1622777f, - 2.236068f, 1.4142135f, 1, 1.4142135f, 2.236068f, 3.1622777f, 4.1231055f}, - { 2.828427f, 2.236068f, 2, 2.236068f, 2.828427f, 3.6055512f, 4, - 3, 2, 1, 0, 1, 2, 3, 4}, - { 2.236068f, 1.4142135f, 1, 1.4142135f, 2.236068f, 3.1622777f, 4.1231055f, 3.1622777f, - 2.236068f, 1.4142135f, 1, 1.4142135f, 2.236068f, 3.1622777f, 4.1231055f}, - { 2, 1, 0, 1, 2, 3, 4, 3.6055512f, - 2.828427f, 2.236068f, 2, 2.236068f, 2.828427f, 3.6055512f, 4.472136f}, - { 2.236068f, 1.4142135f, 1, 1.4142135f, 2.236068f, 3.1622777f, 4.1231055f, 4.2426405f, - 3.6055512f, 3.1622777f, 3, 3.1622777f, 3.6055512f, 4.2426405f, 5}, - { 2.828427f, 2.236068f, 2, 2.236068f, 2.828427f, 3.6055512f, 4.472136f, 5, - 4.472136f, 4.1231055f, 4, 4.1231055f, 4.472136f, 5, 5.656854f}, - {3.6055512f, 3.1622777f, 3, 3.1622777f, 3.6055512f, 4.2426405f, 5, 5.8309517f, - 5.3851647f, 5.0990195f, 5, 5.0990195f, 5.3851647f, 5.8309517f, 6.4031243f}, - { 4.472136f, 4.1231055f, 4, 4.1231055f, 4.472136f, 5, 5.656854f, 6.4031243f, - 6.3245554f, 6.0827622f, 6, 6.0827622f, 6.3245554f, 6.7082043f, 7.0000005f}, - {5.3851647f, 5.0990195f, 5, 5.0990195f, 5.3851647f, 5.8309517f, 6.4031243f, 7.0710683f, - 7.2801094f, 7.0710683f, 7.0000005f, 6.7082043f, 6.3245554f, 6.0827622f, 6}, - {6.3245554f, 6.0827622f, 6, 6.0827622f, 6.3245554f, 6.7082043f, 7.2111025f, 7.8102503f, - 7.8102503f, 7.0710683f, 6.4031243f, 5.8309517f, 5.3851647f, 5.0990195f, 5}, - {7.2801094f, 7.0710683f, 7.0000005f, 7.0710683f, 7.2801094f, 7.6157737f, 8.062258f, 8.062258f, - 7.2111025f, 6.4031243f, 5.656854f, 5, 4.472136f, 4.1231055f, 4}, - { 8.246211f, 8.062258f, 8, 8.062258f, 8.246211f, 8.5440035f, 8.5440035f, 7.6157737f, - 6.7082043f, 5.8309517f, 5, 4.2426405f, 3.6055512f, 3.1622777f, 3}, - { 9.219544f, 9.055386f, 9, 9.055386f, 9.219544f, 9.219544f, 8.246211f, 7.2801094f, - 6.3245554f, 5.3851647f, 4.472136f, 3.6055512f, 2.828427f, 2.236068f, 2}, - {10.198039f, 10.049875f, 10, 10.049875f, 10.049875f, 9.055386f, 8.062258f, 7.0710683f, - 6.0827622f, 5.0990195f, 4.1231055f, 3.1622777f, 2.236068f, 1.4142135f, 1}, - {11.180341f, 11.045361f, 11, 11, 10, 9, 8, 7, - 6, 5, 4, 3, 2, 1, 0} - }; + std::vector> val_in{ + {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, + {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 255, 255, 255, 255}, + {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, + {255, 255, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, + {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, + {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, + {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, + {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, + {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, + {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, + {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, + {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, + {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, + {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, + {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0}}; + + std::vector> val_exp_precise{ + {3.6055512f, + 3.1622777f, + 3, + 3.1622777f, + 3.6055512f, + 4.2426405f, + 4.1231055f, + 3.1622777f, + 2.236068f, + 1.4142135f, + 1, + 1.4142135f, + 2.236068f, + 3.1622777f, + 4.1231055f}, + {2.828427f, 2.236068f, 2, 2.236068f, 2.828427f, 3.6055512f, 4, 3, 2, 1, 0, 1, 2, 3, 4}, + {2.236068f, + 1.4142135f, + 1, + 1.4142135f, + 2.236068f, + 3.1622777f, + 4.1231055f, + 3.1622777f, + 2.236068f, + 1.4142135f, + 1, + 1.4142135f, + 2.236068f, + 3.1622777f, + 4.1231055f}, + {2, + 1, + 0, + 1, + 2, + 3, + 4, + 3.6055512f, + 2.828427f, + 2.236068f, + 2, + 2.236068f, + 2.828427f, + 3.6055512f, + 4.472136f}, + {2.236068f, + 1.4142135f, + 1, + 1.4142135f, + 2.236068f, + 3.1622777f, + 4.1231055f, + 4.2426405f, + 3.6055512f, + 3.1622777f, + 3, + 3.1622777f, + 3.6055512f, + 4.2426405f, + 5}, + {2.828427f, + 2.236068f, + 2, + 2.236068f, + 2.828427f, + 3.6055512f, + 4.472136f, + 5, + 4.472136f, + 4.1231055f, + 4, + 4.1231055f, + 4.472136f, + 5, + 5.656854f}, + {3.6055512f, + 3.1622777f, + 3, + 3.1622777f, + 3.6055512f, + 4.2426405f, + 5, + 5.8309517f, + 5.3851647f, + 5.0990195f, + 5, + 5.0990195f, + 5.3851647f, + 5.8309517f, + 6.4031243f}, + {4.472136f, + 4.1231055f, + 4, + 4.1231055f, + 4.472136f, + 5, + 5.656854f, + 6.4031243f, + 6.3245554f, + 6.0827622f, + 6, + 6.0827622f, + 6.3245554f, + 6.7082043f, + 7.0000005f}, + {5.3851647f, + 5.0990195f, + 5, + 5.0990195f, + 5.3851647f, + 5.8309517f, + 6.4031243f, + 7.0710683f, + 7.2801094f, + 7.0710683f, + 7.0000005f, + 6.7082043f, + 6.3245554f, + 6.0827622f, + 6}, + {6.3245554f, + 6.0827622f, + 6, + 6.0827622f, + 6.3245554f, + 6.7082043f, + 7.2111025f, + 7.8102503f, + 7.8102503f, + 7.0710683f, + 6.4031243f, + 5.8309517f, + 5.3851647f, + 5.0990195f, + 5}, + {7.2801094f, + 7.0710683f, + 7.0000005f, + 7.0710683f, + 7.2801094f, + 7.6157737f, + 8.062258f, + 8.062258f, + 7.2111025f, + 6.4031243f, + 5.656854f, + 5, + 4.472136f, + 4.1231055f, + 4}, + {8.246211f, + 8.062258f, + 8, + 8.062258f, + 8.246211f, + 8.5440035f, + 8.5440035f, + 7.6157737f, + 6.7082043f, + 5.8309517f, + 5, + 4.2426405f, + 3.6055512f, + 3.1622777f, + 3}, + {9.219544f, + 9.055386f, + 9, + 9.055386f, + 9.219544f, + 9.219544f, + 8.246211f, + 7.2801094f, + 6.3245554f, + 5.3851647f, + 4.472136f, + 3.6055512f, + 2.828427f, + 2.236068f, + 2}, + {10.198039f, + 10.049875f, + 10, + 10.049875f, + 10.049875f, + 9.055386f, + 8.062258f, + 7.0710683f, + 6.0827622f, + 5.0990195f, + 4.1231055f, + 3.1622777f, + 2.236068f, + 1.4142135f, + 1}, + {11.180341f, 11.045361f, 11, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}}; fill_image_view(val_in, view(img_in)); fill_image_view(val_exp_precise, view(img_expected)); - gil::distance_transform(view(img_in), view(img_out), gil::distance_from::off_pixels, - gil::distance_type::precise_euclidean, gil::mask_size::not_applicable); + gil::distance_transform( + view(img_in), + view(img_out), + gil::distance_from::off_pixels, + gil::distance_type::precise_euclidean, + gil::mask_size::not_applicable); check_for_negligible_varition(view(img_out), view(img_expected)); - std::vector> val_exp_euclidean_three - { - { 3.6935883f, 3.2792969f, 2.8650055f, 3.2792969f, 3.6935883f, 4.1078796f, - 4.2342987f, 3.2792969f, 2.324295f, 1.3692932f, 0.95500183f, 1.3692932f, - 2.324295f, 3.2792969f, 4.2342987f}, - { 2.7385864f, 2.324295f, 1.9100037f, 2.324295f, 2.7385864f, 3.6935883f, - 3.8200073f, 2.8650055f, 1.9100037f, 0.95500183f, 0, 0.95500183f, - 1.9100037f, 2.8650055f, 3.8200073f}, - { 2.324295f, 1.3692932f, 0.95500183f, 1.3692932f, 2.324295f, 3.2792969f, - 4.2342987f, 3.2792969f, 2.324295f, 1.3692932f, 0.95500183f, 1.3692932f, - 2.324295f, 3.2792969f, 4.2342987f}, - { 1.9100037f, 0.95500183f, 0, 0.95500183f, 1.9100037f, 2.8650055f, - 3.8200073f, 3.6935883f, 2.7385864f, 2.324295f, 1.9100037f, 2.324295f, - 2.7385864f, 3.6935883f, 4.64859f}, - { 2.324295f, 1.3692932f, 0.95500183f, 1.3692932f, 2.324295f, 3.2792969f, - 4.2342987f, 4.1078796f, 3.6935883f, 3.2792969f, 2.8650055f, 3.2792969f, - 3.6935883f, 4.1078796f, 5.0628815f}, - { 2.7385864f, 2.324295f, 1.9100037f, 2.324295f, 2.7385864f, 3.6935883f, - 4.64859f, 5.0628815f, 4.64859f, 4.2342987f, 3.8200073f, 4.2342987f, - 4.64859f, 5.0628815f, 5.477173f}, - { 3.6935883f, 3.2792969f, 2.8650055f, 3.2792969f, 3.6935883f, 4.1078796f, - 5.0628815f, 6.0178833f, 5.603592f, 5.1893005f, 4.775009f, 5.1893005f, - 5.603592f, 6.0178833f, 6.4321747f}, - { 4.64859f, 4.2342987f, 3.8200073f, 4.2342987f, 4.64859f, 5.0628815f, - 5.477173f, 6.4321747f, 6.5585938f, 6.1443024f, 5.730011f, 6.1443024f, - 6.5585938f, 6.972885f, 6.685013f}, - { 5.603592f, 5.1893005f, 4.775009f, 5.1893005f, 5.603592f, 6.0178833f, - 6.4321747f, 6.846466f, 7.5135956f, 7.099304f, 6.685013f, 6.972885f, - 6.5585938f, 6.1443024f, 5.730011f}, - { 6.5585938f, 6.1443024f, 5.730011f, 6.1443024f, 6.5585938f, 6.972885f, - 7.3871765f, 7.801468f, 7.801468f, 6.846466f, 6.4321747f, 6.0178833f, - 5.603592f, 5.1893005f, 4.775009f}, - { 7.5135956f, 7.099304f, 6.685013f, 7.099304f, 7.5135956f, 7.927887f, - 8.342178f, 8.342178f, 7.3871765f, 6.4321747f, 5.477173f, 5.0628815f, - 4.64859f, 4.2342987f, 3.8200073f}, - { 8.468597f, 8.054306f, 7.6400146f, 8.054306f, 8.468597f, 8.882889f, - 8.882889f, 7.927887f, 6.972885f, 6.0178833f, 5.0628815f, 4.1078796f, - 3.6935883f, 3.2792969f, 2.8650055f}, - { 9.423599f, 9.009308f, 8.5950165f, 9.009308f, 9.423599f, 9.423599f, - 8.468597f, 7.5135956f, 6.5585938f, 5.603592f, 4.64859f, 3.6935883f, - 2.7385864f, 2.324295f, 1.9100037f}, - { 10.378601f, 9.96431f, 9.550018f, 9.96431f, 9.96431f, 9.009308f, - 8.054306f, 7.099304f, 6.1443024f, 5.1893005f, 4.2342987f, 3.2792969f, - 2.324295f, 1.3692932f, 0.95500183f}, - { 11.333603f, 10.919312f, 10.50502f, 10.50502f, 9.550018f, 8.5950165f, - 7.6400146f, 6.685013f, 5.730011f, 4.775009f, 3.8200073f, 2.8650055f, - 1.9100037f, 0.95500183f, 0.f} - }; + std::vector> val_exp_euclidean_three{ + {3.6935883f, + 3.2792969f, + 2.8650055f, + 3.2792969f, + 3.6935883f, + 4.1078796f, + 4.2342987f, + 3.2792969f, + 2.324295f, + 1.3692932f, + 0.95500183f, + 1.3692932f, + 2.324295f, + 3.2792969f, + 4.2342987f}, + {2.7385864f, + 2.324295f, + 1.9100037f, + 2.324295f, + 2.7385864f, + 3.6935883f, + 3.8200073f, + 2.8650055f, + 1.9100037f, + 0.95500183f, + 0, + 0.95500183f, + 1.9100037f, + 2.8650055f, + 3.8200073f}, + {2.324295f, + 1.3692932f, + 0.95500183f, + 1.3692932f, + 2.324295f, + 3.2792969f, + 4.2342987f, + 3.2792969f, + 2.324295f, + 1.3692932f, + 0.95500183f, + 1.3692932f, + 2.324295f, + 3.2792969f, + 4.2342987f}, + {1.9100037f, + 0.95500183f, + 0, + 0.95500183f, + 1.9100037f, + 2.8650055f, + 3.8200073f, + 3.6935883f, + 2.7385864f, + 2.324295f, + 1.9100037f, + 2.324295f, + 2.7385864f, + 3.6935883f, + 4.64859f}, + {2.324295f, + 1.3692932f, + 0.95500183f, + 1.3692932f, + 2.324295f, + 3.2792969f, + 4.2342987f, + 4.1078796f, + 3.6935883f, + 3.2792969f, + 2.8650055f, + 3.2792969f, + 3.6935883f, + 4.1078796f, + 5.0628815f}, + {2.7385864f, + 2.324295f, + 1.9100037f, + 2.324295f, + 2.7385864f, + 3.6935883f, + 4.64859f, + 5.0628815f, + 4.64859f, + 4.2342987f, + 3.8200073f, + 4.2342987f, + 4.64859f, + 5.0628815f, + 5.477173f}, + {3.6935883f, + 3.2792969f, + 2.8650055f, + 3.2792969f, + 3.6935883f, + 4.1078796f, + 5.0628815f, + 6.0178833f, + 5.603592f, + 5.1893005f, + 4.775009f, + 5.1893005f, + 5.603592f, + 6.0178833f, + 6.4321747f}, + {4.64859f, + 4.2342987f, + 3.8200073f, + 4.2342987f, + 4.64859f, + 5.0628815f, + 5.477173f, + 6.4321747f, + 6.5585938f, + 6.1443024f, + 5.730011f, + 6.1443024f, + 6.5585938f, + 6.972885f, + 6.685013f}, + {5.603592f, + 5.1893005f, + 4.775009f, + 5.1893005f, + 5.603592f, + 6.0178833f, + 6.4321747f, + 6.846466f, + 7.5135956f, + 7.099304f, + 6.685013f, + 6.972885f, + 6.5585938f, + 6.1443024f, + 5.730011f}, + {6.5585938f, + 6.1443024f, + 5.730011f, + 6.1443024f, + 6.5585938f, + 6.972885f, + 7.3871765f, + 7.801468f, + 7.801468f, + 6.846466f, + 6.4321747f, + 6.0178833f, + 5.603592f, + 5.1893005f, + 4.775009f}, + {7.5135956f, + 7.099304f, + 6.685013f, + 7.099304f, + 7.5135956f, + 7.927887f, + 8.342178f, + 8.342178f, + 7.3871765f, + 6.4321747f, + 5.477173f, + 5.0628815f, + 4.64859f, + 4.2342987f, + 3.8200073f}, + {8.468597f, + 8.054306f, + 7.6400146f, + 8.054306f, + 8.468597f, + 8.882889f, + 8.882889f, + 7.927887f, + 6.972885f, + 6.0178833f, + 5.0628815f, + 4.1078796f, + 3.6935883f, + 3.2792969f, + 2.8650055f}, + {9.423599f, + 9.009308f, + 8.5950165f, + 9.009308f, + 9.423599f, + 9.423599f, + 8.468597f, + 7.5135956f, + 6.5585938f, + 5.603592f, + 4.64859f, + 3.6935883f, + 2.7385864f, + 2.324295f, + 1.9100037f}, + {10.378601f, + 9.96431f, + 9.550018f, + 9.96431f, + 9.96431f, + 9.009308f, + 8.054306f, + 7.099304f, + 6.1443024f, + 5.1893005f, + 4.2342987f, + 3.2792969f, + 2.324295f, + 1.3692932f, + 0.95500183f}, + {11.333603f, + 10.919312f, + 10.50502f, + 10.50502f, + 9.550018f, + 8.5950165f, + 7.6400146f, + 6.685013f, + 5.730011f, + 4.775009f, + 3.8200073f, + 2.8650055f, + 1.9100037f, + 0.95500183f, + 0.f}}; fill_image_view(val_in, view(img_in)); fill_image_view(val_exp_euclidean_three, view(img_expected)); - gil::distance_transform(view(img_in), view(img_out), gil::distance_from::off_pixels, - gil::distance_type::euclidean_approximation, gil::mask_size::three); + gil::distance_transform( + view(img_in), + view(img_out), + gil::distance_from::off_pixels, + gil::distance_type::euclidean_approximation, + gil::mask_size::three); check_for_negligible_varition(view(img_out), view(img_expected)); - std::vector> val_exp_euclidean_five - { - { 3.5969f, 3.1969f, 3, 3.1969f, 3.5969f, 4.2f, - 4.1969f, 3.1969f, 2.1969f, 1.4f, 1, 1.4f, - 2.1969f, 3.1969f, 4.1969f}, - { 2.8f, 2.1969f, 2, 2.1969f, 2.8f, 3.5969f, - 4, 3, 2, 1, 0, 1, - 2, 3, 4}, - { 2.1969f, 1.4f, 1, 1.4f, 2.1969f, 3.1969f, - 4.1969f, 3.1969f, 2.1969f, 1.4f, 1, 1.4f, - 2.1969f, 3.1969f, 4.1969f}, - { 2, 1, 0, 1, 2, 3, - 4, 3.5969f, 2.8f, 2.1969f, 2, 2.1969f, - 2.8f, 3.5969f, 4.3938f}, - { 2.1969f, 1.4f, 1, 1.4f, 2.1969f, 3.1969f, - 4.1969f, 4.2f, 3.5969f, 3.1969f, 3, 3.1969f, - 3.5969f, 4.2f, 4.9968996f}, - { 2.8f, 2.1969f, 2, 2.1969f, 2.8f, 3.5969f, - 4.3938f, 4.9968996f, 4.3938f, 4.1969f, 4, 4.1969f, - 4.3938f, 4.9968996f, 5.6f}, - { 3.5969f, 3.1969f, 3, 3.1969f, 3.5969f, 4.2f, - 4.9968996f, 5.7938f, 5.3938f, 5.1969f, 5, 5.1969f, - 5.3938f, 5.7938f, 6.3968997f}, - { 4.3938f, 4.1969f, 4, 4.1969f, 4.3938f, 4.9968996f, - 5.6f, 6.3968997f, 6.3938f, 6.1969f, 6, 6.1969f, - 6.3938f, 6.5906997f, 7}, - { 5.3938f, 5.1969f, 5, 5.1969f, 5.3938f, 5.7938f, - 6.3968997f, 7, 7.3938f, 7.1969f, 7, 6.5906997f, - 6.3938f, 6.1969f, 6}, - { 6.3938f, 6.1969f, 6, 6.1969f, 6.3938f, 6.5906997f, - 7.1937995f, 7.7969f, 7.7969f, 7, 6.3968997f, 5.7938f, - 5.3938f, 5.1969f, 5}, - { 7.3938f, 7.1969f, 7, 7.1969f, 7.3938f, 7.5906997f, - 7.9907f, 7.9907f, 7.1937995f, 6.3968997f, 5.6f, 4.9968996f, - 4.3938f, 4.1969f, 4}, - { 8.3938f, 8.196899f, 8, 8.196899f, 8.3938f, 8.5907f, - 8.5907f, 7.5906997f, 6.5906997f, 5.7938f, 4.9968996f, 4.2f, - 3.5969f, 3.1969f, 3}, - { 9.3938f, 9.196899f, 9, 9.196899f, 9.3938f, 9.3938f, - 8.3938f, 7.3938f, 6.3938f, 5.3938f, 4.3938f, 3.5969f, - 2.8f, 2.1969f, 2}, - {10.393799f, 10.196899f, 10, 10.196899f, 10.196899f, 9.196899f, - 8.196899f, 7.1969f, 6.1969f, 5.1969f, 4.1969f, 3.1969f, - 2.1969f, 1.4f, 1}, - {11.393799f, 11.196899f, 11, 11, 10, 9, - 8, 7, 6, 5, 4, 3, - 2, 1, 0} - }; + std::vector> val_exp_euclidean_five{ + {3.5969f, + 3.1969f, + 3, + 3.1969f, + 3.5969f, + 4.2f, + 4.1969f, + 3.1969f, + 2.1969f, + 1.4f, + 1, + 1.4f, + 2.1969f, + 3.1969f, + 4.1969f}, + {2.8f, 2.1969f, 2, 2.1969f, 2.8f, 3.5969f, 4, 3, 2, 1, 0, 1, 2, 3, 4}, + {2.1969f, + 1.4f, + 1, + 1.4f, + 2.1969f, + 3.1969f, + 4.1969f, + 3.1969f, + 2.1969f, + 1.4f, + 1, + 1.4f, + 2.1969f, + 3.1969f, + 4.1969f}, + {2, 1, 0, 1, 2, 3, 4, 3.5969f, 2.8f, 2.1969f, 2, 2.1969f, 2.8f, 3.5969f, 4.3938f}, + {2.1969f, + 1.4f, + 1, + 1.4f, + 2.1969f, + 3.1969f, + 4.1969f, + 4.2f, + 3.5969f, + 3.1969f, + 3, + 3.1969f, + 3.5969f, + 4.2f, + 4.9968996f}, + {2.8f, + 2.1969f, + 2, + 2.1969f, + 2.8f, + 3.5969f, + 4.3938f, + 4.9968996f, + 4.3938f, + 4.1969f, + 4, + 4.1969f, + 4.3938f, + 4.9968996f, + 5.6f}, + {3.5969f, + 3.1969f, + 3, + 3.1969f, + 3.5969f, + 4.2f, + 4.9968996f, + 5.7938f, + 5.3938f, + 5.1969f, + 5, + 5.1969f, + 5.3938f, + 5.7938f, + 6.3968997f}, + {4.3938f, + 4.1969f, + 4, + 4.1969f, + 4.3938f, + 4.9968996f, + 5.6f, + 6.3968997f, + 6.3938f, + 6.1969f, + 6, + 6.1969f, + 6.3938f, + 6.5906997f, + 7}, + {5.3938f, + 5.1969f, + 5, + 5.1969f, + 5.3938f, + 5.7938f, + 6.3968997f, + 7, + 7.3938f, + 7.1969f, + 7, + 6.5906997f, + 6.3938f, + 6.1969f, + 6}, + {6.3938f, + 6.1969f, + 6, + 6.1969f, + 6.3938f, + 6.5906997f, + 7.1937995f, + 7.7969f, + 7.7969f, + 7, + 6.3968997f, + 5.7938f, + 5.3938f, + 5.1969f, + 5}, + {7.3938f, + 7.1969f, + 7, + 7.1969f, + 7.3938f, + 7.5906997f, + 7.9907f, + 7.9907f, + 7.1937995f, + 6.3968997f, + 5.6f, + 4.9968996f, + 4.3938f, + 4.1969f, + 4}, + {8.3938f, + 8.196899f, + 8, + 8.196899f, + 8.3938f, + 8.5907f, + 8.5907f, + 7.5906997f, + 6.5906997f, + 5.7938f, + 4.9968996f, + 4.2f, + 3.5969f, + 3.1969f, + 3}, + {9.3938f, + 9.196899f, + 9, + 9.196899f, + 9.3938f, + 9.3938f, + 8.3938f, + 7.3938f, + 6.3938f, + 5.3938f, + 4.3938f, + 3.5969f, + 2.8f, + 2.1969f, + 2}, + {10.393799f, + 10.196899f, + 10, + 10.196899f, + 10.196899f, + 9.196899f, + 8.196899f, + 7.1969f, + 6.1969f, + 5.1969f, + 4.1969f, + 3.1969f, + 2.1969f, + 1.4f, + 1}, + {11.393799f, 11.196899f, 11, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}}; fill_image_view(val_in, view(img_in)); fill_image_view(val_exp_euclidean_five, view(img_expected)); - gil::distance_transform(view(img_in), view(img_out), gil::distance_from::off_pixels, - gil::distance_type::euclidean_approximation, gil::mask_size::five); + gil::distance_transform( + view(img_in), + view(img_out), + gil::distance_from::off_pixels, + gil::distance_type::euclidean_approximation, + gil::mask_size::five); check_for_negligible_varition(view(img_out), view(img_expected)); - std::vector> val_exp_manhatten_three - { - { 5, 4, 3, 4, 5, 6, 5, 4, 3, 2, 1, 2, 3, 4, 5}, - { 4, 3, 2, 3, 4, 5, 4, 3, 2, 1, 0, 1, 2, 3, 4}, - { 3, 2, 1, 2, 3, 4, 5, 4, 3, 2, 1, 2, 3, 4, 5}, - { 2, 1, 0, 1, 2, 3, 4, 5, 4, 3, 2, 3, 4, 5, 6}, - { 3, 2, 1, 2, 3, 4, 5, 6, 5, 4, 3, 4, 5, 6, 7}, - { 4, 3, 2, 3, 4, 5, 6, 7, 6, 5, 4, 5, 6, 7, 8}, - { 5, 4, 3, 4, 5, 6, 7, 8, 7, 6, 5, 6, 7, 8, 8}, - { 6, 5, 4, 5, 6, 7, 8, 9, 8, 7, 6, 7, 8, 8, 7}, - { 7, 6, 5, 6, 7, 8, 9, 10, 9, 8, 7, 8, 8, 7, 6}, - { 8, 7, 6, 7, 8, 9, 10, 11, 10, 9, 8, 8, 7, 6, 5}, - { 9, 8, 7, 8, 9, 10, 11, 11, 10, 9, 8, 7, 6, 5, 4}, - {10, 9, 8, 9, 10, 11, 11, 10, 9, 8, 7, 6, 5, 4, 3}, - {11, 10, 9, 10, 11, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2}, - {12, 11, 10, 11, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1}, - {13, 12, 11, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0} - }; + std::vector> val_exp_manhatten_three{ + {5, 4, 3, 4, 5, 6, 5, 4, 3, 2, 1, 2, 3, 4, 5}, + {4, 3, 2, 3, 4, 5, 4, 3, 2, 1, 0, 1, 2, 3, 4}, + {3, 2, 1, 2, 3, 4, 5, 4, 3, 2, 1, 2, 3, 4, 5}, + {2, 1, 0, 1, 2, 3, 4, 5, 4, 3, 2, 3, 4, 5, 6}, + {3, 2, 1, 2, 3, 4, 5, 6, 5, 4, 3, 4, 5, 6, 7}, + {4, 3, 2, 3, 4, 5, 6, 7, 6, 5, 4, 5, 6, 7, 8}, + {5, 4, 3, 4, 5, 6, 7, 8, 7, 6, 5, 6, 7, 8, 8}, + {6, 5, 4, 5, 6, 7, 8, 9, 8, 7, 6, 7, 8, 8, 7}, + {7, 6, 5, 6, 7, 8, 9, 10, 9, 8, 7, 8, 8, 7, 6}, + {8, 7, 6, 7, 8, 9, 10, 11, 10, 9, 8, 8, 7, 6, 5}, + {9, 8, 7, 8, 9, 10, 11, 11, 10, 9, 8, 7, 6, 5, 4}, + {10, 9, 8, 9, 10, 11, 11, 10, 9, 8, 7, 6, 5, 4, 3}, + {11, 10, 9, 10, 11, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2}, + {12, 11, 10, 11, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1}, + {13, 12, 11, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}}; fill_image_view(val_exp_manhatten_three, view(img_expected)); - gil::distance_transform(view(img_in), view(img_out), gil::distance_from::off_pixels, - gil::distance_type::manhattan, gil::mask_size::three); + gil::distance_transform( + view(img_in), + view(img_out), + gil::distance_from::off_pixels, + gil::distance_type::manhattan, + gil::mask_size::three); BOOST_TEST(equal_pixels(const_view(img_out), const_view(img_expected))); - - std::vector> val_exp_manhatten_five - { - { 5, 4, 3, 4, 5, 6, 5, 4, 3, 2, 1, 2, 3, 4, 5}, - { 4, 3, 2, 3, 4, 5, 4, 3, 2, 1, 0, 1, 2, 3, 4}, - { 3, 2, 1, 2, 3, 4, 5, 4, 3, 2, 1, 2, 3, 4, 5}, - { 2, 1, 0, 1, 2, 3, 4, 5, 4, 3, 2, 3, 4, 5, 6}, - { 3, 2, 1, 2, 3, 4, 5, 6, 5, 4, 3, 4, 5, 6, 7}, - { 4, 3, 2, 3, 4, 5, 6, 7, 6, 5, 4, 5, 6, 7, 8}, - { 5, 4, 3, 4, 5, 6, 7, 8, 7, 6, 5, 6, 7, 8, 8}, - { 6, 5, 4, 5, 6, 7, 8, 9, 8, 7, 6, 7, 8, 8, 7}, - { 7, 6, 5, 6, 7, 8, 9, 10, 9, 8, 7, 8, 8, 7, 6}, - { 8, 7, 6, 7, 8, 9, 10, 11, 10, 9, 8, 8, 7, 6, 5}, - { 9, 8, 7, 8, 9, 10, 11, 11, 10, 9, 8, 7, 6, 5, 4}, - {10, 9, 8, 9, 10, 11, 11, 10, 9, 8, 7, 6, 5, 4, 3}, - {11, 10, 9, 10, 11, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2}, - {12, 11, 10, 11, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1}, - {13, 12, 11, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0} - }; + std::vector> val_exp_manhatten_five{ + {5, 4, 3, 4, 5, 6, 5, 4, 3, 2, 1, 2, 3, 4, 5}, + {4, 3, 2, 3, 4, 5, 4, 3, 2, 1, 0, 1, 2, 3, 4}, + {3, 2, 1, 2, 3, 4, 5, 4, 3, 2, 1, 2, 3, 4, 5}, + {2, 1, 0, 1, 2, 3, 4, 5, 4, 3, 2, 3, 4, 5, 6}, + {3, 2, 1, 2, 3, 4, 5, 6, 5, 4, 3, 4, 5, 6, 7}, + {4, 3, 2, 3, 4, 5, 6, 7, 6, 5, 4, 5, 6, 7, 8}, + {5, 4, 3, 4, 5, 6, 7, 8, 7, 6, 5, 6, 7, 8, 8}, + {6, 5, 4, 5, 6, 7, 8, 9, 8, 7, 6, 7, 8, 8, 7}, + {7, 6, 5, 6, 7, 8, 9, 10, 9, 8, 7, 8, 8, 7, 6}, + {8, 7, 6, 7, 8, 9, 10, 11, 10, 9, 8, 8, 7, 6, 5}, + {9, 8, 7, 8, 9, 10, 11, 11, 10, 9, 8, 7, 6, 5, 4}, + {10, 9, 8, 9, 10, 11, 11, 10, 9, 8, 7, 6, 5, 4, 3}, + {11, 10, 9, 10, 11, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2}, + {12, 11, 10, 11, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1}, + {13, 12, 11, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}}; fill_image_view(val_exp_manhatten_five, view(img_expected)); - gil::distance_transform(view(img_in), view(img_out), gil::distance_from::off_pixels, - gil::distance_type::manhattan, gil::mask_size::five); + gil::distance_transform( + view(img_in), + view(img_out), + gil::distance_from::off_pixels, + gil::distance_type::manhattan, + gil::mask_size::five); BOOST_TEST(equal_pixels(const_view(img_out), const_view(img_expected))); - std::vector> val_exp_chessboard_three - { - { 3, 3, 3, 3, 3, 3, 4, 3, 2, 1, 1, 1, 2, 3, 4}, - { 2, 2, 2, 2, 2, 3, 4, 3, 2, 1, 0, 1, 2, 3, 4}, - { 2, 1, 1, 1, 2, 3, 4, 3, 2, 1, 1, 1, 2, 3, 4}, - { 2, 1, 0, 1, 2, 3, 4, 3, 2, 2, 2, 2, 2, 3, 4}, - { 2, 1, 1, 1, 2, 3, 4, 3, 3, 3, 3, 3, 3, 3, 4}, - { 2, 2, 2, 2, 2, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4}, - { 3, 3, 3, 3, 3, 3, 4, 5, 5, 5, 5, 5, 5, 5, 5}, - { 4, 4, 4, 4, 4, 4, 4, 5, 6, 6, 6, 6, 6, 6, 6}, - { 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6}, - { 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5}, - { 7, 7, 7, 7, 7, 7, 7, 7, 6, 5, 4, 4, 4, 4, 4}, - { 8, 8, 8, 8, 8, 8, 8, 7, 6, 5, 4, 3, 3, 3, 3}, - { 9, 9, 9, 9, 9, 9, 8, 7, 6, 5, 4, 3, 2, 2, 2}, - {10, 10, 10, 10, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1}, - {11, 11, 11, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0} - }; - + std::vector> val_exp_chessboard_three{ + {3, 3, 3, 3, 3, 3, 4, 3, 2, 1, 1, 1, 2, 3, 4}, + {2, 2, 2, 2, 2, 3, 4, 3, 2, 1, 0, 1, 2, 3, 4}, + {2, 1, 1, 1, 2, 3, 4, 3, 2, 1, 1, 1, 2, 3, 4}, + {2, 1, 0, 1, 2, 3, 4, 3, 2, 2, 2, 2, 2, 3, 4}, + {2, 1, 1, 1, 2, 3, 4, 3, 3, 3, 3, 3, 3, 3, 4}, + {2, 2, 2, 2, 2, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4}, + {3, 3, 3, 3, 3, 3, 4, 5, 5, 5, 5, 5, 5, 5, 5}, + {4, 4, 4, 4, 4, 4, 4, 5, 6, 6, 6, 6, 6, 6, 6}, + {5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6}, + {6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5}, + {7, 7, 7, 7, 7, 7, 7, 7, 6, 5, 4, 4, 4, 4, 4}, + {8, 8, 8, 8, 8, 8, 8, 7, 6, 5, 4, 3, 3, 3, 3}, + {9, 9, 9, 9, 9, 9, 8, 7, 6, 5, 4, 3, 2, 2, 2}, + {10, 10, 10, 10, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1}, + {11, 11, 11, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}}; + fill_image_view(val_exp_chessboard_three, view(img_expected)); - gil::distance_transform(view(img_in), view(img_out), gil::distance_from::off_pixels, - gil::distance_type::chessboard, gil::mask_size::three); + gil::distance_transform( + view(img_in), + view(img_out), + gil::distance_from::off_pixels, + gil::distance_type::chessboard, + gil::mask_size::three); BOOST_TEST(equal_pixels(const_view(img_out), const_view(img_expected))); - std::vector> val_exp_chessboard_five - { - {3, 3, 3, 3, 3, 3, 4, 3, 2, 1, 1, 1, 2, 3, 4}, - {2, 2, 2, 2, 2, 3, 4, 3, 2, 1, 0, 1, 2, 3, 4}, - {2, 1, 1, 1, 2, 3, 4, 3, 2, 1, 1, 1, 2, 3, 4}, - {2, 1, 0, 1, 2, 3, 4, 3, 2, 2, 2, 2, 2, 3, 4}, - {2, 1, 1, 1, 2, 3, 4, 3, 3, 3, 3, 3, 3, 3, 4}, - {2, 2, 2, 2, 2, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4}, - {3, 3, 3, 3, 3, 3, 4, 5, 5, 5, 5, 5, 5, 5, 5}, - {4, 4, 4, 4, 4, 4, 4, 5, 6, 6, 6, 6, 6, 6, 6}, - {5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6}, - {6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5}, - {7, 7, 7, 7, 7, 7, 7, 7, 6, 5, 4, 4, 4, 4, 4}, - {8, 8, 8, 8, 8, 8, 8, 7, 6, 5, 4, 3, 3, 3, 3}, - {9, 9, 9, 9, 9, 9, 8, 7, 6, 5, 4, 3, 2, 2, 2}, - {10, 10, 10, 10, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1}, - {11, 11, 11, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0} - }; - + std::vector> val_exp_chessboard_five{ + {3, 3, 3, 3, 3, 3, 4, 3, 2, 1, 1, 1, 2, 3, 4}, + {2, 2, 2, 2, 2, 3, 4, 3, 2, 1, 0, 1, 2, 3, 4}, + {2, 1, 1, 1, 2, 3, 4, 3, 2, 1, 1, 1, 2, 3, 4}, + {2, 1, 0, 1, 2, 3, 4, 3, 2, 2, 2, 2, 2, 3, 4}, + {2, 1, 1, 1, 2, 3, 4, 3, 3, 3, 3, 3, 3, 3, 4}, + {2, 2, 2, 2, 2, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4}, + {3, 3, 3, 3, 3, 3, 4, 5, 5, 5, 5, 5, 5, 5, 5}, + {4, 4, 4, 4, 4, 4, 4, 5, 6, 6, 6, 6, 6, 6, 6}, + {5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6}, + {6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5}, + {7, 7, 7, 7, 7, 7, 7, 7, 6, 5, 4, 4, 4, 4, 4}, + {8, 8, 8, 8, 8, 8, 8, 7, 6, 5, 4, 3, 3, 3, 3}, + {9, 9, 9, 9, 9, 9, 8, 7, 6, 5, 4, 3, 2, 2, 2}, + {10, 10, 10, 10, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1}, + {11, 11, 11, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}}; + fill_image_view(val_exp_chessboard_five, view(img_expected)); - gil::distance_transform(view(img_in), view(img_out), gil::distance_from::off_pixels, - gil::distance_type::chessboard, gil::mask_size::five); + gil::distance_transform( + view(img_in), + view(img_out), + gil::distance_from::off_pixels, + gil::distance_type::chessboard, + gil::mask_size::five); BOOST_TEST(equal_pixels(const_view(img_out), const_view(img_expected))); - } int main()