Skip to content

Commit

Permalink
Add tests for checking boundary options in 1D convolution
Browse files Browse the repository at this point in the history
Second Draft

Third draft

Fourth draft

Fifth draft

Sixth draft

Seventh draft

Eight draft

Ninth draft

Tenth draft

Eleventh draft

Add tests for checking boundary options in 1D convolution

Add tests for checking boundary options in 1D convolution

Add tests for checking boundary options in 1D convolution
  • Loading branch information
meshtag committed May 29, 2021
1 parent fe1621e commit 8ecfae0
Show file tree
Hide file tree
Showing 3 changed files with 585 additions and 1 deletion.
234 changes: 233 additions & 1 deletion test/extension/numeric/convolve.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//
// Copyright 2019-2020 Mateusz Loskot <mateusz at loskot dot net>
// 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 @@ -100,7 +101,6 @@ struct test_image_5x5_kernel_3x3_identity

auto const kernel = fixture::create_kernel<channel_t>({0, 0, 0, 0, 1, 0, 0, 0, 0});
gil::detail::convolve_1d<pixel_t>(gil::const_view(img_out), kernel, gil::view(img_out));
// TODO: Test different boundary options

BOOST_TEST(gil::equal_pixels(gil::const_view(img), gil::const_view(img_out)));
}
Expand All @@ -110,12 +110,244 @@ struct test_image_5x5_kernel_3x3_identity
}
};

// Convention used for naming variables :
// 1. img : Original image which is to be used for testing.
// 2. img_out : Output image obtained after applying 1D row and column convolution using library
// function.
// 3. img_expected_row : Expected image after applying row convolution on "img".
// 4. img_expected_col : Expected image after applying column convolution on "img_expected_row".

struct test_image_5x5_kernel_1x9_boundary_extend_zero
{
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(img), img_expected_row(img_view.width(), img_view.height());
image_t img_expected_col(img_view.width(), img_view.height());

for (std::ptrdiff_t y = 0; y < img_view.height(); ++y)
{
auto img_it = img_view.row_begin(y);
auto img_expected_row_it = gil::view(img_expected_row).row_begin(y);
for (std::ptrdiff_t x = 2; x < img_view.width(); ++x)
img_expected_row_it[x] = img_it[x - 2];
}
for (std::ptrdiff_t x = 0; x < img_view.width(); ++x)
{
auto img_expected_row_it = gil::view(img_expected_row).col_begin(x);
auto img_expected_col_it = gil::view(img_expected_col).col_begin(x);
for (std::ptrdiff_t y = 2; y < img_view.height(); ++y)
img_expected_col_it[y] = img_expected_row_it[y - 2];
}

auto const kernel = fixture::create_kernel<channel_t>({0, 0, 0, 0, 0, 0, 1, 0, 0});
gil::detail::convolve_1d<pixel_t>(gil::const_view(img_out), kernel, gil::view(img_out),
boost::gil::boundary_option::extend_zero);

BOOST_TEST(gil::equal_pixels(gil::const_view(img_out), gil::const_view(img_expected_col)));
}
static void run()
{
boost::mp11::mp_for_each<fixture::image_types>(
test_image_5x5_kernel_1x9_boundary_extend_zero{});
}
};

struct test_image_5x5_kernel_1x9_boundary_extend_constant
{
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(img), img_expected_row(img);

for (std::ptrdiff_t y = 0; y < img_view.height(); ++y)
{
auto img_it = img_view.row_begin(y);
auto img_expected_row_it = gil::view(img_expected_row).row_begin(y);
for (std::ptrdiff_t x = 2; x < img_view.width(); ++x)
img_expected_row_it[x] = img_it[x - 2];
img_expected_row_it[1] = img_it[0];
}
image_t img_expected_col(img_expected_row);
for (std::ptrdiff_t x = 0; x < img_view.width(); ++x)
{
auto img_expected_row_it = gil::view(img_expected_row).col_begin(x);
auto img_expected_col_it = gil::view(img_expected_col).col_begin(x);
for (std::ptrdiff_t y = 2; y < img_view.height(); ++y)
img_expected_col_it[y] = img_expected_row_it[y - 2];
img_expected_col_it[1] = img_expected_row_it[0];
}

auto const kernel = fixture::create_kernel<channel_t>({0, 0, 0, 0, 0, 0, 1, 0, 0});
gil::detail::convolve_1d<pixel_t>(gil::const_view(img_out), kernel, gil::view(img_out),
boost::gil::boundary_option::extend_constant);

BOOST_TEST(gil::equal_pixels(gil::const_view(img_out), gil::const_view(img_expected_col)));
}
static void run()
{
boost::mp11::mp_for_each<fixture::image_types>(
test_image_5x5_kernel_1x9_boundary_extend_constant{});
}
};

struct test_image_5x5_kernel_1x9_boundary_output_zero
{
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(img), img_expected_row(img_view.width(), img_view.height());
image_t img_expected_col(img_view.width(), img_view.height());

for (std::ptrdiff_t y = 0; y < img_view.height(); ++y)
{
auto img_it = img_view.row_begin(y);
auto img_expected_row_it = gil::view(img_expected_row).row_begin(y);
for (std::ptrdiff_t x = 1; x < img_view.width() - 1; ++x)
img_expected_row_it[x] = img_it[x - 1];
}
for (std::ptrdiff_t x = 0; x < img_view.width(); ++x)
{
auto img_expected_row_it = gil::view(img_expected_row).col_begin(x);
auto img_expected_col_it = gil::view(img_expected_col).col_begin(x);
for (std::ptrdiff_t y = 1; y < img_view.height() - 1; ++y)
img_expected_col_it[y] = img_expected_row_it[y - 1];
}

auto const kernel = fixture::create_kernel<channel_t>({0, 0, 1});
gil::detail::convolve_1d<pixel_t>(gil::const_view(img_out), kernel, gil::view(img_out),
boost::gil::boundary_option::output_zero);

BOOST_TEST(gil::equal_pixels(gil::const_view(img_out), gil::const_view(img_expected_col)));
}
static void run()
{
boost::mp11::mp_for_each<fixture::image_types>(
test_image_5x5_kernel_1x9_boundary_output_zero{});
}
};

struct test_image_5x5_kernel_1x9_boundary_output_ignore
{
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(img), img_expected_row(img);

for (std::ptrdiff_t y = 0; y < img_view.height(); ++y)
{
auto img_it = img_view.row_begin(y);
auto img_expected_row_it = gil::view(img_expected_row).row_begin(y);
for (std::ptrdiff_t x = 1; x < img_view.width() - 1; ++x)
img_expected_row_it[x] = img_it[x - 1];
}
image_t img_expected_col(img_expected_row);
for (std::ptrdiff_t x = 0; x < img_view.width(); ++x)
{
auto img_expected_row_it = gil::view(img_expected_row).col_begin(x);
auto img_expected_col_it = gil::view(img_expected_col).col_begin(x);
for (std::ptrdiff_t y = 1; y < img_view.height() - 1; ++y)
img_expected_col_it[y] = img_expected_row_it[y - 1];
}

auto const kernel = fixture::create_kernel<channel_t>({0, 0, 1});
gil::detail::convolve_1d<pixel_t>(gil::const_view(img_out), kernel, gil::view(img_out),
gil::boundary_option::output_ignore);

BOOST_TEST(gil::equal_pixels(gil::const_view(img_out), gil::const_view(img_expected_col)));
}
static void run()
{
boost::mp11::mp_for_each<fixture::image_types>(
test_image_5x5_kernel_1x9_boundary_output_ignore{});
}
};

struct test_image_5x5_kernel_1x9_boundary_extend_padded
{
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(img), img_expected_row(img);

for (std::ptrdiff_t y = 0; y < img_view.height(); ++y)
{
auto img_it = img_view.row_begin(y);
auto img_expected_row_it = gil::view(img_expected_row).row_begin(y);
for (std::ptrdiff_t x = 1; x < img_view.width(); ++x)
img_expected_row_it[x] = img_it[x - 1];
}
image_t img_expected_col(img_expected_row);
for (std::ptrdiff_t x = 0; x < img_view.width(); ++x)
{
auto img_expected_row_it = gil::view(img_expected_row).col_begin(x);
auto img_expected_col_it = gil::view(img_expected_col).col_begin(x);
for (std::ptrdiff_t y = 1; y < img_view.width(); ++y)
img_expected_col_it[y] = img_expected_row_it[y - 1];
}

auto const kernel = fixture::create_kernel<channel_t>({0, 0, 1});
gil::detail::convolve_1d<pixel_t>(gil::const_view(img_out), kernel, gil::view(img_out),
gil::boundary_option::extend_padded);

// First row and first column of "img_out" and "img_expected_col" are intentionally made
// similar.
auto img_out_it1 = gil::view(img_out).col_begin(0);
auto img_expected_col_it1 = gil::view(img_expected_col).col_begin(0);
for (std::ptrdiff_t x = 0; x < gil::view(img_out).width(); ++x)
img_expected_col_it1[x] = img_out_it1[x];

auto img_out_it2 = gil::view(img_out).row_begin(0);
auto img_expected_col_it2 = gil::view(img_expected_col).row_begin(0);
for (std::ptrdiff_t y = 0; y < gil::view(img_out).height(); ++y)
img_expected_col_it2[y] = img_out_it2[y];

BOOST_TEST(gil::equal_pixels(gil::const_view(img_out), gil::const_view(img_expected_col)));

}
static void run()
{
boost::mp11::mp_for_each<fixture::image_types>(
test_image_5x5_kernel_1x9_boundary_extend_padded{});
}
};

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_zero::run();
test_image_5x5_kernel_1x9_boundary_extend_constant::run();
test_image_5x5_kernel_1x9_boundary_output_zero::run();
test_image_5x5_kernel_1x9_boundary_output_ignore::run();
test_image_5x5_kernel_1x9_boundary_extend_padded::run();
return ::boost::report_errors();
}
Loading

0 comments on commit 8ecfae0

Please sign in to comment.