Skip to content

Commit

Permalink
Resolve merge conflicts
Browse files Browse the repository at this point in the history
  • Loading branch information
meshtag committed Jun 4, 2022
1 parent 843ea37 commit 1a2a908
Show file tree
Hide file tree
Showing 6 changed files with 248 additions and 5 deletions.
11 changes: 6 additions & 5 deletions include/boost/gil/algorithm.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1416,11 +1416,12 @@ void view_multiplies_scalar(SrcView const& src_view, Scalar const& scalar, DstVi
/// \brief Boundary options for image boundary extension
enum class boundary_option
{
output_ignore, /// do nothing to the output
output_zero, /// set the output to zero
extend_padded, /// assume the source boundaries to be padded already
extend_zero, /// assume the source boundaries to be zero
extend_constant /// assume the source boundaries to be the boundary value
output_ignore, /// do nothing to the output
output_zero, /// set the output to zero
extend_padded, /// assume the source boundaries to be padded already
extend_zero, /// assume the source boundaries to be zero
extend_constant, /// assume the source boundaries to be the boundary value
extend_reflection /// assumes boundary values as reflection of source row pixels
};

namespace detail
Expand Down
13 changes: 13 additions & 0 deletions include/boost/gil/image_processing/convolve.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Copyright 2005-2007 Adobe Systems Incorporated
// Copyright 2019 Miral Shah <[email protected]>
// Copyright 2019-2021 Pranam Lashkari <[email protected]>
// Copyright 2021 Prathamesh Tagore <[email protected]>
//
// Distributed under the Boost Software License, Version 1.0
// See accompanying file LICENSE_1_0.txt or copy at
Expand Down Expand Up @@ -143,6 +144,18 @@ void correlate_rows_impl(
pixel_assigns_t<src_pixel_ref_t, PixelAccum>()(src_view.row_end(y)[-1], filler);
std::fill_n(it_buffer, kernel.right_size(), filler);
}
else if (option == boundary_option::extend_reflection)
{
assign_pixels(src_view.row_begin(y), src_view.row_begin(y) + kernel.left_size(),
it_buffer);
std::reverse(buffer.begin(), buffer.begin() + kernel.left_size());
it_buffer += kernel.left_size();
assign_pixels(src_view.row_begin(y), src_view.row_end(y), it_buffer);
it_buffer += width;
assign_pixels(src_view.row_end(y) - kernel.right_size(), src_view.row_end(y),
it_buffer);
std::reverse(buffer.end() - kernel.right_size(), buffer.end());
}

correlator(
&buffer.front(), &buffer.front() + width,
Expand Down
70 changes: 70 additions & 0 deletions test/core/image_processing/convolve.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//
// Copyright 2019-2020 Mateusz Loskot <mateusz at loskot dot net>
// Copyright 2021 Pranam Lashkari <[email protected]>
// Copyright 2021 Prathamesh Tagore <[email protected]>
//
// Distributed under the Boost Software License, Version 1.0
// See accompanying file LICENSE_1_0.txt or copy at
Expand Down Expand Up @@ -111,12 +112,81 @@ struct test_image_5x5_kernel_3x3_identity
}
};

struct test_image_5x5_kernel_1x9_boundary_extend_reflection
{
template <typename Image>
void operator()(Image const&)
{
using image_t = Image;
using pixel_t = typename image_t::value_type;
using channel_t = typename gil::channel_type<pixel_t>::type;
auto img = fixture::generate_image<image_t>(5, 5, fixture::random_value<channel_t>{});
auto img_view = gil::view(img);
image_t img_out_up_left_offset(img), img_expected_row_up_offset(img);
image_t img_expected_col_left_offset(img), img_out_down_right_offset(img);
image_t img_expected_row_down_offset(img), img_expected_col_right_offset(img);
int kernel_shift_up_left_offset = 2, kernel_shift_down_right_offset = -2;

fixture::row_conv1D_offset_img_generator(img_view, gil::view(img_expected_row_up_offset),
kernel_shift_up_left_offset);
fixture::row_conv1D_offset_img_generator(img_view, gil::view(img_expected_row_up_offset),
-1, 0, 1, img_view.height(), 1);
fixture::row_conv1D_offset_img_generator(img_view, gil::view(img_expected_row_up_offset),
1, 0, 0, img_view.height(), 2);

fixture::col_conv1D_offset_img_generator(gil::view(img_expected_row_up_offset),
gil::view(img_expected_col_left_offset), kernel_shift_up_left_offset);
fixture::col_conv1D_offset_img_generator(gil::view(img_expected_row_up_offset),
gil::view(img_expected_col_left_offset), -1, 1, 0, 1, img_view.width());
fixture::col_conv1D_offset_img_generator(gil::view(img_expected_row_up_offset),
gil::view(img_expected_col_left_offset), 1, 0, 0, 2, img_view.width());

fixture::row_conv1D_offset_img_generator(img_view, gil::view(img_expected_row_down_offset),
kernel_shift_down_right_offset, 0, 2, img_view.height(), img_view.width());
fixture::row_conv1D_offset_img_generator(img_view, gil::view(img_expected_row_down_offset),
-1, 0, img_view.width() - 1, img_view.height(), img_view.width());
fixture::row_conv1D_offset_img_generator(img_view, gil::view(img_expected_row_down_offset),
1, 0, img_view.width() - 2, img_view.height(), img_view.width());

fixture::col_conv1D_offset_img_generator(gil::view(img_expected_row_down_offset),
gil::view(img_expected_col_right_offset), kernel_shift_down_right_offset, 2, 0,
img_view.height(), img_view.width());
fixture::col_conv1D_offset_img_generator(gil::view(img_expected_row_down_offset),
gil::view(img_expected_col_right_offset), -1, img_view.height() - 1, 0,
img_view.height(), img_view.width());
fixture::col_conv1D_offset_img_generator(gil::view(img_expected_row_down_offset),
gil::view(img_expected_col_right_offset), 1, img_view.height() - 2, 0,
img_view.height(), img_view.width());

auto const kernel_up_left_offset = fixture::create_kernel<channel_t>(
{0, 0, 0, 0, 0, 0, 1, 0, 0});
gil::detail::convolve_1d<pixel_t>(gil::const_view(img), kernel_up_left_offset,
gil::view(img_out_up_left_offset), gil::boundary_option::extend_reflection);

auto const kernel_down_right_offset = fixture::create_kernel<channel_t>(
{0, 0, 1, 0, 0, 0, 0, 0, 0});
gil::detail::convolve_1d<pixel_t>(gil::const_view(img), kernel_down_right_offset,
gil::view(img_out_down_right_offset), gil::boundary_option::extend_reflection);

BOOST_TEST(gil::equal_pixels(gil::const_view(img_out_up_left_offset),
gil::const_view(img_expected_col_left_offset)));
BOOST_TEST(gil::equal_pixels(gil::const_view(img_out_down_right_offset),
gil::const_view(img_expected_col_right_offset)));
}
static void run()
{
boost::mp11::mp_for_each<fixture::image_types>(
test_image_5x5_kernel_1x9_boundary_extend_reflection{});
}
};

int main()
{
test_image_1x1_kernel_1x1_identity::run();
test_image_1x1_kernel_3x3_identity::run();
test_image_3x3_kernel_3x3_identity::run();
test_image_5x5_kernel_3x3_identity::run();

test_image_5x5_kernel_1x9_boundary_extend_reflection::run();
return ::boost::report_errors();
}
52 changes: 52 additions & 0 deletions test/core/image_processing/convolve_cols.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//
// Copyright 2019-2020 Mateusz Loskot <mateusz at loskot dot net>
// Copyright 2021 Pranam Lashkari <[email protected]>
// Copyright 2021 Prathamesh Tagore <[email protected]>
//
// Distributed under the Boost Software License, Version 1.0
// See accompanying file LICENSE_1_0.txt or copy at
Expand Down Expand Up @@ -65,10 +66,61 @@ struct test_image_1x1_kernel_3x3_identity
}
};

struct test_image_5x5_kernel_1x9_boundary_extend_reflection
{
template <typename Image>
void operator()(Image const&)
{
using image_t = Image;
using pixel_t = typename image_t::value_type;
using channel_t = typename gil::channel_type<pixel_t>::type;
auto img = fixture::generate_image<image_t>(5, 5, fixture::random_value<channel_t>{});
auto img_view = gil::view(img);
image_t img_out_left_offset(img), img_expected_left_offset(img);
image_t img_out_right_offset(img), img_expected_right_offset(img);
int kernel_shift_left_offset = 2, kernel_shift_right_offset = -2;

fixture::col_conv1D_offset_img_generator(img_view, gil::view(img_expected_left_offset),
kernel_shift_left_offset);
fixture::col_conv1D_offset_img_generator(img_view, gil::view(img_expected_left_offset),
-1, 1, 0, 1, img_view.width());
fixture::col_conv1D_offset_img_generator(img_view, gil::view(img_expected_left_offset),
1, 0, 0, 2, img_view.width());

fixture::col_conv1D_offset_img_generator(img_view, gil::view(img_expected_right_offset),
kernel_shift_right_offset, 2, 0, img_view.height(), img_view.width());
fixture::col_conv1D_offset_img_generator(img_view, gil::view(img_expected_right_offset),
-1, img_view.height() - 1, 0, img_view.height(), img_view.width());
fixture::col_conv1D_offset_img_generator(img_view, gil::view(img_expected_right_offset),
1, img_view.height() - 2, 0, img_view.height(), img_view.width());

auto const kernel_left_offset = fixture::create_kernel<channel_t>(
{0, 0, 0, 0, 0, 0, 1, 0, 0});
gil::convolve_cols<pixel_t>(gil::const_view(img), kernel_left_offset,
gil::view(img_out_left_offset), gil::boundary_option::extend_reflection);

auto const kernel_right_offset = fixture::create_kernel<channel_t>(
{0, 0, 1, 0, 0, 0, 0, 0, 0});
gil::convolve_cols<pixel_t>(gil::const_view(img), kernel_right_offset,
gil::view(img_out_right_offset), gil::boundary_option::extend_reflection);

BOOST_TEST(gil::equal_pixels(gil::const_view(img_out_left_offset),
gil::const_view(img_expected_left_offset)));
BOOST_TEST(gil::equal_pixels(gil::const_view(img_out_right_offset),
gil::const_view(img_expected_right_offset)));
}
static void run()
{
boost::mp11::mp_for_each<fixture::image_types>(
test_image_5x5_kernel_1x9_boundary_extend_reflection{});
}
};

int main()
{
test_image_1x1_kernel_1x1_identity::run();
test_image_1x1_kernel_3x3_identity::run();

test_image_5x5_kernel_1x9_boundary_extend_reflection::run();
return ::boost::report_errors();
}
52 changes: 52 additions & 0 deletions test/core/image_processing/convolve_rows.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//
// Copyright 2019-2020 Mateusz Loskot <mateusz at loskot dot net>
// Copyright 2021 Pranam Lashkari <[email protected]>
// Copyright 2021 Prathamesh Tagore <[email protected]>
//
// Distributed under the Boost Software License, Version 1.0
// See accompanying file LICENSE_1_0.txt or copy at
Expand Down Expand Up @@ -65,10 +66,61 @@ struct test_image_1x1_kernel_3x3_identity
}
};

struct test_image_5x5_kernel_1x9_boundary_extend_reflection
{
template <typename Image>
void operator()(Image const&)
{
using image_t = Image;
using pixel_t = typename image_t::value_type;
using channel_t = typename gil::channel_type<pixel_t>::type;
auto img = fixture::generate_image<image_t>(5, 5, fixture::random_value<channel_t>{});
auto img_view = gil::view(img);
image_t img_out_up_offset(img), img_expected_up_offset(img);
image_t img_out_down_offset(img), img_expected_down_offset(img);
int kernel_shift_up_offset = 2, kernel_shift_down_offset = -2;

fixture::row_conv1D_offset_img_generator(img_view, gil::view(img_expected_up_offset),
kernel_shift_up_offset);
fixture::row_conv1D_offset_img_generator(img_view, gil::view(img_expected_up_offset),
-1, 0, 1, img_view.height(), 1);
fixture::row_conv1D_offset_img_generator(img_view, gil::view(img_expected_up_offset),
1, 0, 0, img_view.height(), 2);

fixture::row_conv1D_offset_img_generator(img_view, gil::view(img_expected_down_offset),
kernel_shift_down_offset, 0, 2, img_view.height(), img_view.width());
fixture::row_conv1D_offset_img_generator(img_view, gil::view(img_expected_down_offset),
-1, 0, img_view.width() - 1, img_view.height(), img_view.width());
fixture::row_conv1D_offset_img_generator(img_view, gil::view(img_expected_down_offset),
1, 0, img_view.width() - 2, img_view.height(), img_view.width());

auto const kernel_up_offset = fixture::create_kernel<channel_t>(
{0, 0, 0, 0, 0, 0, 1, 0, 0});
gil::convolve_rows<pixel_t>(gil::const_view(img), kernel_up_offset,
gil::view(img_out_up_offset), gil::boundary_option::extend_reflection);

auto const kernel_down_offset = fixture::create_kernel<channel_t>(
{0, 0, 1, 0, 0, 0, 0, 0, 0});
gil::convolve_rows<pixel_t>(gil::const_view(img), kernel_down_offset,
gil::view(img_out_down_offset), gil::boundary_option::extend_reflection);

BOOST_TEST(gil::equal_pixels(gil::const_view(img_out_up_offset),
gil::const_view(img_expected_up_offset)));
BOOST_TEST(gil::equal_pixels(gil::const_view(img_out_down_offset),
gil::const_view(img_expected_down_offset)));
}
static void run()
{
boost::mp11::mp_for_each<fixture::image_types>(
test_image_5x5_kernel_1x9_boundary_extend_reflection{});
}
};

int main()
{
test_image_1x1_kernel_1x1_identity::run();
test_image_1x1_kernel_3x3_identity::run();

test_image_5x5_kernel_1x9_boundary_extend_reflection::run();
return ::boost::report_errors();
}
55 changes: 55 additions & 0 deletions test/core/image_processing/test_fixture.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//
// Copyright 2019 Mateusz Loskot <mateusz at loskot dot net>
// Copyright 2021 Pranam Lashkari <[email protected]>
// Copyright 2021 Prathamesh Tagore <[email protected]>
//
// Distributed under the Boost Software License, Version 1.0
// See accompanying file LICENSE_1_0.txt or copy at
Expand Down Expand Up @@ -28,4 +29,58 @@ auto create_kernel(std::initializer_list<T> const& values)
return kernel;
}

// Adds an offset similar to 1D row convolution with kernel {0, 0, 0, 0, 0, 0, 1, 0, 0}
// (for offset = 2) having its anchor point at 5th element and boundary option as "extend_zero".
template <typename SrcView, typename DstView>
void row_conv1D_offset_img_generator(SrcView src_view, DstView dst_view, int const offset,
std::ptrdiff_t start_row = 0, std::ptrdiff_t start_col = 0, std::ptrdiff_t end_row = -1,
std::ptrdiff_t end_col = -1)
{
BOOST_ASSERT(src_view.dimensions() == dst_view.dimensions());
static_assert(color_spaces_are_compatible
<
typename color_space_type<SrcView>::type,
typename color_space_type<DstView>::type
>::value, "Source and destination views must have pixels with the same color space");

if (end_row == -1)
end_row = src_view.height();
if (end_col == -1)
end_col = src_view.width();
for (std::ptrdiff_t y = start_row; y < end_row; ++y)
{
auto src_it = src_view.row_begin(y);
auto dst_it = dst_view.row_begin(y);
for (std::ptrdiff_t x = offset + start_col; x < end_col; ++x)
dst_it[x] = src_it[x - offset];
}
}

// Adds an offset similar to 1D column convolution with kernel {0, 0, 0, 0, 0, 0, 1, 0, 0}
// (for offset = 2) having its anchor point at 5th element and boundary option as "extend_zero".
template <typename SrcView, typename DstView>
void col_conv1D_offset_img_generator(SrcView src_view, DstView dst_view, int const offset,
std::ptrdiff_t start_row = 0, std::ptrdiff_t start_col = 0, std::ptrdiff_t end_row = -1,
std::ptrdiff_t end_col = -1)
{
BOOST_ASSERT(src_view.dimensions() == dst_view.dimensions());
static_assert(color_spaces_are_compatible
<
typename color_space_type<SrcView>::type,
typename color_space_type<DstView>::type
>::value, "Source and destination views must have pixels with the same color space");

if (end_row == -1)
end_row = src_view.height();
if (end_col == -1)
end_col = src_view.width();
for (std::ptrdiff_t x = start_col; x < end_col; ++x)
{
auto src_it = src_view.col_begin(x);
auto dst_it = dst_view.col_begin(x);
for (std::ptrdiff_t y = offset + start_row; y < end_row; ++y)
dst_it[y] = src_it[y - offset];
}
}

}}}} // namespace boost::gil::test::fixture

0 comments on commit 1a2a908

Please sign in to comment.