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 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
|
//
// Copyright 2021 Prathamesh Tagore <prathameshtagore@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.hpp>
#include <boost/gil/extension/io/png.hpp>
#include <iostream>
#include <map>
#include <string>
#include <vector>
// Demonstrates a number of morphological operations
// The structuring element is defined as an instance of a kernel_2d<float>:
// Default structuring element is SE = [1,1,1]
// |1,1,1|
// [1,1,1]
// SE(1,1)(center pixel) is the one which coincides with the currently
// considered pixel of the image to be convolved. The structuring element can be
// easily changed by the user.
// The example demonstrates the following morphological operations:
// - black_hat
// - top_hat
// - morphological_gradient
// - dilation
// - erosion
// - opening
// - closing
// - binary
// These operations are defined in include/boost/gil/image_processing/morphology.hpp
namespace gil = boost::gil;
int main(int argc, char** argv)
{
std::map<std::string, bool> operations;
if (argc < 4 || argc > 11)
{
throw std::invalid_argument(
"Wrong format of command line arguments.\n"
"Correct format is <Input_image.png> <Output_image_template>"
" <operation1> <operation2> <operation3> <operation4> <operation5> "
"<operation6>"
" <operation7> <operation8>\n");
// User has to enter at least one operation and they can enter maximum 8
// operations considering binary conversion to be an
// operation.Output_image_template argument is the common component which
// will be added in names of all output images followed by a hyphen and
// the operation name.
// Example :
// ./example_morphology morphology_original.png out black_hat top_hat
// morphological_gradient dilation erosion opening closing binary
// Order of arguments entered will not matter with the exception of binary
// operation used for binary morphological operations.If binary is entered
// through the command line, it will always be the first operation to be
// applied.
return -1;
}
else
{
for (int i = 3; i < argc; ++i)
operations[argv[i]] = true;
}
gil::gray8_image_t img;
gil::read_image(argv[1], img, gil::png_tag{});
// Image can be converted to a binary format with high value as 255 and low
// value as 0 by using the threshold operator . This can be used for binary
// morphological operations . Convenient threshold for binary conversion may
// be chosen by the user.
if (operations["binary"])
{
threshold_binary(view(img), view(img), 170, 255);
std::string name = argv[2];
name += "-binary.png";
gil::write_view(name, view(img), gil::png_tag{});
}
std::vector<float> ker_vec(9, 1.0f); // Structuring element
gil::detail::kernel_2d<float> ker_mat(ker_vec.begin(), ker_vec.size(), 1, 1);
gil::gray8_image_t img_out_dilation(img.dimensions()), img_out_erosion(img.dimensions()),
img_out_opening(img.dimensions());
gil::gray8_image_t img_out_closing(img.dimensions()), img_out_mg(img.dimensions()),
img_out_top_hat(img.dimensions());
gil::gray8_image_t img_out_black_hat(img.dimensions());
// Do not pass empty input image views in functions defined below for
// morphological operations to avoid errors.
if (operations["dilation"])
{
// dilate(input_image_view,output_image_view,structuring_element,iterations)
dilate(view(img), view(img_out_dilation), ker_mat, 1);
std::string name = argv[2];
name += "-dilation.png";
gil::write_view(name, view(img_out_dilation), gil::png_tag{});
}
if (operations["erosion"])
{
// erode(input_image_view,output_image_view,structuring_element,iterations)
erode(view(img), view(img_out_erosion), ker_mat, 1);
std::string name = argv[2];
name += "-erosion.png";
gil::write_view(name, view(img_out_erosion), gil::png_tag{});
}
if (operations["opening"])
{
// opening(input_image_view,output_image_view,structuring_element)
opening(view(img), view(img_out_opening), ker_mat);
std::string name = argv[2];
name += "-opening.png";
gil::write_view(name, view(img_out_opening), gil::png_tag{});
}
if (operations["closing"])
{
// closing(input_image_view,output_image_view,structuring_element)
closing(view(img), view(img_out_closing), ker_mat);
std::string name = argv[2];
name += "-closing.png";
gil::write_view(name, view(img_out_closing), gil::png_tag{});
}
if (operations["morphological_gradient"])
{
// morphological_gradient(input_image_view,output_image_view,structuring_element)
morphological_gradient(view(img), view(img_out_mg), ker_mat);
std::string name = argv[2];
name += "-morphological_gradient.png";
gil::write_view(name, view(img_out_mg), gil::png_tag{});
}
if (operations["top_hat"])
{
// top_hat(input_image_view,output_image_view,structuring_element)
top_hat(view(img), view(img_out_top_hat), ker_mat);
std::string name = argv[2];
name += "-top_hat.png";
gil::write_view(name, view(img_out_top_hat), gil::png_tag{});
}
if (operations["black_hat"])
{
// black_hat(input_image_view,output_image_view,structuring_element)
black_hat(view(img), view(img_out_black_hat), ker_mat);
std::string name = argv[2];
name += "-black_hat.png";
gil::write_view(name, view(img_out_black_hat), gil::png_tag{});
}
}
|