Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added definition of gaussian adaptive threshold #379

Merged
merged 1 commit into from
Aug 19, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 11 additions & 7 deletions example/adaptive_threshold.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
//
#include <boost/gil.hpp>
#include <boost/gil/extension/io/png.hpp>
#include <iostream>

using namespace boost::gil;

Expand All @@ -16,14 +17,17 @@ int main()
read_image("test_adaptive.png", img, png_tag{});
gray8_image_t img_out(img.dimensions());

// performing binary threshold on each channel of the image
// if the pixel value is more than 150 than it will be set to 255 else to 0
boost::gil::threshold_adaptive(const_view(img), view(img_out), 11);
write_view("out-threshold-adaptive.png", view(img_out), png_tag{});
boost::gil::threshold_adaptive(const_view(img), view(img_out), 11, threshold_adaptive_method::mean, threshold_direction::regular, 2);
write_view("out-threshold-adaptive-mean.png", view(img_out), png_tag{});

boost::gil::threshold_adaptive(const_view(img), view(img_out), 11, threshold_adaptive_method::mean, threshold_direction::inverse, 2);
write_view("out-threshold-adaptive-mean-inv.png", view(img_out), png_tag{});

// if the pixel value is more than 150 than it will be set to 150 else no change
boost::gil::threshold_adaptive(const_view(img), view(img_out), 11, threshold_adaptive_method::mean, threshold_direction::inverse);
write_view("out-threshold-adaptive-inv.png", view(img_out), png_tag{});
boost::gil::threshold_adaptive(const_view(img), view(img_out), 7, threshold_adaptive_method::gaussian, threshold_direction::regular, 2);
write_view("out-threshold-adaptive-gaussian.png", view(img_out), png_tag{});

boost::gil::threshold_adaptive(const_view(img), view(img_out), 11, threshold_adaptive_method::gaussian, threshold_direction::inverse, 2);
write_view("out-threshold-adaptive-gaussian-inv.png", view(img_out), png_tag{});

return 0;
}
Binary file modified example/test_adaptive.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
54 changes: 37 additions & 17 deletions include/boost/gil/image_processing/threshold.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,12 @@
#include <vector>
#include <cmath>

#include <boost/assert.hpp>

#include <boost/gil/image.hpp>
#include <boost/gil/extension/numeric/kernel.hpp>
#include <boost/gil/extension/numeric/convolve.hpp>
#include <boost/assert.hpp>
#include <boost/gil/image_processing/numeric.hpp>

namespace boost { namespace gil {

Expand Down Expand Up @@ -403,31 +405,49 @@ void threshold_adaptive
typedef typename channel_type<SrcView>::type source_channel_t;
typedef typename channel_type<DstView>::type result_channel_t;

image<typename SrcView::value_type> temp_img(src_view.width(), src_view.height());
typename image<typename SrcView::value_type>::view_t temp_view = view(temp_img);
SrcView temp_conv(temp_view);

if (method == threshold_adaptive_method::mean)
{
std::vector<float> mean_kernel_values(kernel_size, 1.0f/kernel_size);
kernel_1d<float> kernel(mean_kernel_values.begin(), kernel_size, kernel_size/2);

image<typename SrcView::value_type> temp_img(src_view.width(), src_view.height());
typename image<typename SrcView::value_type>::view_t temp_view = view(temp_img);
SrcView temp_conv(temp_view);

convolve_1d<pixel<float, typename SrcView::value_type::layout_t>>(
src_view, kernel, temp_view
);
}
else if (method == threshold_adaptive_method::gaussian)
{
gray32f_image_t gaussian_kernel_values(kernel_size, kernel_size);
generate_gaussian_kernel(view(gaussian_kernel_values), 1.0);

gray32f_view_t gaussian_kernel_view = view(gaussian_kernel_values);
kernel_2d<float> kernel(
kernel_size,
kernel_size / 2,
kernel_size / 2
);

if (direction == threshold_direction::regular)
{
detail::adaptive_impl<source_channel_t, result_channel_t>(src_view, temp_conv, dst_view,
[max_value, constant](source_channel_t px, source_channel_t threshold) -> result_channel_t
{ return px > (threshold - constant) ? max_value : 0; });
}
else
{
detail::adaptive_impl<source_channel_t, result_channel_t>(src_view, temp_conv, dst_view,
[max_value, constant](source_channel_t px, source_channel_t threshold) -> result_channel_t
{ return px > (threshold - constant) ? 0 : max_value; });
}
std::transform(gaussian_kernel_view.begin(), gaussian_kernel_view.end(), kernel.begin(),
[](gray32f_pixel_t pixel) -> float {return pixel.at(std::integral_constant<int, 0>{}); }
);

convolve_2d(src_view, kernel, temp_view);
}

if (direction == threshold_direction::regular)
{
detail::adaptive_impl<source_channel_t, result_channel_t>(src_view, temp_conv, dst_view,
[max_value, constant](source_channel_t px, source_channel_t threshold) -> result_channel_t
{ return px > (threshold - constant) ? max_value : 0; });
}
else
{
detail::adaptive_impl<source_channel_t, result_channel_t>(src_view, temp_conv, dst_view,
[max_value, constant](source_channel_t px, source_channel_t threshold) -> result_channel_t
{ return px > (threshold - constant) ? 0 : max_value; });
}
}

Expand Down