2
0
mirror of https://github.com/boostorg/gil.git synced 2026-01-25 06:12:22 +00:00
Files
gil/test/core/image_processing/simple_kernels.cpp
Olzhas Zhumabek 01c39629f8 Filter generation (#342)
* Implement generation of simple kernels

This commits implements mean and
Gaussian kernel generators,
roughly documents them, and has
tests. But tests for Gaussian have
accuracy problem

* Use difference for testing Gaussian

This commit applies percentage based
difference check on generation of
Gaussian kernels, as exact values are
dependant on platform. The error margin
is set to 5% in this commit

* Remove debugging code

In simple_kernels.cpp, there was
some debugging code, mostly streams
related stuff and commented out code,
which is now removed.

* Address review comments

This commit adds inline to kernel
generator functions, uses
std::ptrdiff_t instead of long int,
resolves some conversion warnings
and does small cosmetic changes

* Remove useless iostream include

There was stray include from debugging
code, now removed

* Use \code and \endcode for formula

This commit applies formatting to
formula of normalized mean

* Change are_equal to is_equal

Change a function name in
simple_kernels.cpp test

* Remove redundant function

In simple_kernels.cpp test there was
a function that was not used at all,
now removed

* Cosmetic changes

Mostly opening brackets moved
2019-07-23 06:14:02 +06:00

125 lines
4.0 KiB
C++

#include <boost/gil/image_processing/numeric.hpp>
#include <boost/gil/image.hpp>
#include <boost/gil/image_view.hpp>
#include <boost/gil/typedefs.hpp>
#include <boost/core/lightweight_test.hpp>
namespace gil = boost::gil;
void test_normalized_mean_generation()
{
gil::gray32f_image_t kernel_image(gil::point_t(5, 5));
auto view = gil::view(kernel_image);
gil::generate_normalized_mean(view);
bool is_correct = true;
boost::gil::for_each_pixel(view, [&is_correct](gil::gray32f_pixel_t& pixel)
{
const auto chosen_channel = std::integral_constant<int, 0>{};
const auto expected_value = static_cast<float>(1 / 25.f);
if (pixel.at(chosen_channel) != expected_value)
is_correct = false;
});
BOOST_TEST(is_correct);
}
void test_normalized_mean_throw()
{
gil::gray32f_image_t kernel_image(gil::point_t(5, 6));
auto view = gil::view(kernel_image);
bool have_thrown = false;
try
{
gil::generate_normalized_mean(view);
} catch(std::invalid_argument& e)
{
have_thrown = true;
}
BOOST_TEST(have_thrown);
}
void test_unnormalized_mean_generation()
{
gil::gray32f_image_t kernel_image(gil::point_t(5, 5));
auto view = gil::view(kernel_image);
gil::generate_unnormalized_mean(view);
bool is_correct = true;
boost::gil::for_each_pixel(view, [&is_correct](gil::gray32f_pixel_t& pixel)
{
const auto chosen_channel = std::integral_constant<int, 0>{};
const auto expected_value = 1.f;
if (pixel.at(chosen_channel) != expected_value)
is_correct = false;
});
BOOST_TEST(is_correct);
}
void test_unnormalized_mean_throw() {
gil::gray32f_image_t kernel_image(gil::point_t(5, 6));
auto view = gil::view(kernel_image);
bool have_thrown = false;
try
{
gil::generate_unnormalized_mean(view);
} catch(std::invalid_argument& e)
{
have_thrown = true;
}
BOOST_TEST(have_thrown);
}
void test_gaussian_kernel_generation()
{
gil::gray32f_image_t kernel_image(gil::point_t(7, 7));
auto view = gil::view(kernel_image);
gil::generate_gaussian_kernel(view, 0.84089642);
bool is_correct = true;
const float expected_values[7][7] =
{
{0.00000067f, 0.00002292f, 0.00019117f, 0.00038771f, 0.00019117f, 0.00002292f, 0.00000067f},
{0.00002292f, 0.00078633f, 0.00655965f, 0.01330373f, 0.00655965f, 0.00078633f, 0.00002292f},
{0.00019117f, 0.00655965f, 0.05472157f, 0.11098164f, 0.05472157f, 0.00655965f, 0.00019117f},
{0.00038771f, 0.01330373f, 0.11098164f, 0.25508352f, 0.11098164f, 0.01330373f, 0.00038711f},
{0.00019117f, 0.00655965f, 0.05472157f, 0.11098164f, 0.05472157f, 0.00655965f, 0.00019117f},
{0.00002292f, 0.00078633f, 0.00655965f, 0.01330373f, 0.00655965f, 0.00078633f, 0.00002292f},
{0.00000067f, 0.00002292f, 0.00019117f, 0.00038771f, 0.00019117f, 0.00002292f, 0.00000067f}
};
const auto chosen_channel = std::integral_constant<int, 0>{};
for (gil::gray32f_view_t::coord_t y = 0; y < view.height(); ++y)
{
for (gil::gray32f_view_t::coord_t x = 0; x < view.width(); ++x)
{
auto output = view(x, y).at(chosen_channel);
auto expected = expected_values[y][x];
auto percent_difference = std::ceil(std::abs(expected - output) / expected);
BOOST_TEST(percent_difference < 5);
}
}
}
void test_gaussian_kernel_throw()
{
gil::gray32f_image_t kernel_image(gil::point_t(5, 6));
auto view = gil::view(kernel_image);
bool have_thrown = false;
try
{
gil::generate_gaussian_kernel(view, 0.5);
} catch(std::invalid_argument& e)
{
have_thrown = true;
}
BOOST_TEST(have_thrown);
}
int main()
{
test_normalized_mean_generation();
test_normalized_mean_throw();
test_unnormalized_mean_generation();
test_unnormalized_mean_throw();
test_gaussian_kernel_generation();
test_gaussian_kernel_throw();
return boost::report_errors();
}