Skip to content

Commit

Permalink
Added all standard morphological transformations (#541)
Browse files Browse the repository at this point in the history
* Added all standard morphological transformations

* Improved comments and some other things

* Applied adviced changes

* Applied adviced changes

* Should handle grayscale dilation/erosion

* Checking

* Added test cases and improved code structure

* Added command line control

* Added command line control

* Rectified some things

* Rectified some more things

* Improved comments

* Improved comments

* Improved doxygen comments and added more test cases

* Improved compatibility for builds and rectifying whitespace use

* Minor improvement in comments

* Did clang formatting

* pushed enum class inside namespace 'detail' and some other things

* Should handle multichannel images

* Clang formatting attempt

* got rid of if/else comparators for target_element

* Adds morphology.hpp declaration in boost/gil.hpp

* Fix newline

* (std::max)(a, b) instead of std::max(a, b)

* Improved Formatting
  • Loading branch information
meshtag committed Feb 13, 2021
1 parent 2676d31 commit 1e85267
Show file tree
Hide file tree
Showing 8 changed files with 580 additions and 1 deletion.
1 change: 1 addition & 0 deletions example/Jamfile
Expand Up @@ -30,6 +30,7 @@ local sources =
histogram.cpp
interleaved_ptr.cpp
mandelbrot.cpp
morphology.cpp
packed_pixel.cpp
resize.cpp
sobel_scharr.cpp
Expand Down
139 changes: 139 additions & 0 deletions example/morphology.cpp
@@ -0,0 +1,139 @@
//
// 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>

// 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.
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 atleast 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{});
}
}
Binary file added example/morphology_original.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions include/boost/gil.hpp
Expand Up @@ -57,6 +57,7 @@
#include <boost/gil/image_processing/histogram_matching.hpp>
#include <boost/gil/image_processing/hough_parameter.hpp>
#include <boost/gil/image_processing/hough_transform.hpp>
#include <boost/gil/image_processing/morphology.hpp>
#include <boost/gil/image_processing/numeric.hpp>
#include <boost/gil/image_processing/scaling.hpp>
#include <boost/gil/image_processing/threshold.hpp>
Expand Down

0 comments on commit 1e85267

Please sign in to comment.