1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
|
//
// Copyright 2020 Olzhas Zhumabek <anonymous.from.applecity@gmail.com>
//
// 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 <boost/gil/algorithm.hpp>
#include <boost/gil/extension/io/png.hpp>
#include <boost/gil/image.hpp>
#include "boost/gil/extension/image_processing/diffusion.hpp"
#include <boost/gil/image_view.hpp>
#include <boost/gil/io/typedefs.hpp>
#include <boost/gil/typedefs.hpp>
#include <cmath>
#include <iostream>
#include <string>
#include <type_traits>
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<gil::uint8_t>(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<gil::uint8_t>(p[0]), static_cast<gil::uint8_t>(p[1]),
static_cast<gil::uint8_t>(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]
<< " <input.png> <output.png>"
" <colorspace: gray|rgb> <positive iteration count> <positive kappa~30>\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<unsigned int>(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";
}
}
|