// // Copyright 2020 Olzhas Zhumabek // // 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 "boost/gil/extension/image_processing/diffusion.hpp" #include #include #include #include #include #include #include namespace gil = boost::gil; // Demonstrates Anisotropic Diffusion // This example uses the Perona-Malik's diffusion algorithm, which is the default in GIL. // In addition, Gaussian conductivity and two wide range conductivity functions are also available. // see include/boost/gil/image_processing/diffusion.hpp void gray_version(std::string const& input_path, std::string const& output_path, unsigned int iteration_count, float kappa) { gil::gray8_image_t input; gil::read_image(input_path, input, gil::png_tag{}); auto input_view = gil::view(input); gil::gray32f_image_t gray(input.dimensions()); auto gray_view = gil::view(gray); gil::transform_pixels(input_view, gray_view, [](const gil::gray8_pixel_t& p) { return p[0]; }); double sum_before = 0; gil::for_each_pixel(gray_view, [&sum_before](gil::gray32f_pixel_t p) { sum_before += p[0]; }); gil::gray32f_image_t output(gray.dimensions()); auto output_view = gil::view(output); // gil::anisotropic_diffusion(gray_view, output_view, iteration_count, {kappa, delta_t}); gil::default_anisotropic_diffusion(gray_view, output_view, iteration_count, kappa); double sum_after = 0; gil::for_each_pixel(output_view, [&sum_after](gil::gray32f_pixel_t p) { sum_after += p[0]; }); gil::gray8_image_t true_output(output.dimensions()); gil::transform_pixels(output_view, gil::view(true_output), [](gil::gray32f_pixel_t p) { return static_cast(p[0]); }); gil::write_view(output_path, gil::view(true_output), gil::png_tag{}); std::cout << "sum of intensity before diffusion: " << sum_before << '\n' << "sum of intensity after diffusion: " << sum_after << '\n' << "difference: " << sum_after - sum_before << '\n'; } void rgb_version(const std::string& input_path, const std::string& output_path, unsigned int iteration_count, float kappa) { gil::rgb8_image_t input; gil::read_image(input_path, input, gil::png_tag{}); auto input_view = gil::view(input); gil::rgb32f_image_t gray(input.dimensions()); auto gray_view = gil::view(gray); gil::transform_pixels(input_view, gray_view, [](const gil::rgb8_pixel_t& p) { return gil::rgb32f_pixel_t(p[0], p[1], p[2]); }); double sum_before[3] = {}; gil::for_each_pixel(gray_view, [&sum_before](gil::rgb32f_pixel_t p) { sum_before[0] += p[0]; sum_before[1] += p[1]; sum_before[2] += p[2]; }); gil::rgb32f_image_t output(gray.dimensions()); auto output_view = gil::view(output); // gil::anisotropic_diffusion(gray_view, output_view, iteration_count, {kappa, delta_t}); gil::default_anisotropic_diffusion(gray_view, output_view, iteration_count, kappa); double sum_after[3] = {}; gil::for_each_pixel(output_view, [&sum_after](gil::rgb32f_pixel_t p) { sum_after[0] += p[0]; sum_after[1] += p[1]; sum_after[2] += p[2]; }); gil::rgb8_image_t true_output(output.dimensions()); gil::transform_pixels(output_view, gil::view(true_output), [](gil::rgb32f_pixel_t p) { return gil::rgb8_pixel_t(static_cast(p[0]), static_cast(p[1]), static_cast(p[2])); }); gil::write_view(output_path, gil::view(true_output), gil::png_tag{}); std::cout << "sum of intensity before diffusion: (" << sum_before[0] << ", " << sum_before[1] << ", " << sum_before[2] << ")\n" << "sum of intensity after diffusion: (" << sum_after[0] << ", " << sum_after[1] << ", " << sum_after[2] << ")\n" << "difference: (" << sum_after[0] - sum_before[0] << ", " << sum_after[1] - sum_before[1] << ", " << sum_after[2] - sum_before[2] << ")\n"; } int main(int argc, char* argv[]) { if (argc != 6) { std::cerr << "usage: " << argv[0] << " " " \n"; return -1; } std::string input_path = argv[1]; std::string output_path = argv[2]; std::string colorspace = argv[3]; unsigned int iteration_count = static_cast(std::stoul(argv[4])); float kappa = std::stof(argv[5]); if (colorspace == "gray") { gray_version(input_path, output_path, iteration_count, kappa); } else if (colorspace == "rgb") { rgb_version(input_path, output_path, iteration_count, kappa); } else { std::cerr << "unknown colorspace option passed (did you type gray with A?)\n"; } }