mirror of
https://github.com/boostorg/gil.git
synced 2026-01-25 06:12:22 +00:00
* 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
125 lines
4.0 KiB
C++
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();
|
|
}
|