Skip to content

Commit

Permalink
implemented median_filter
Browse files Browse the repository at this point in the history
tests for median_filter added
  • Loading branch information
miralshah365 committed Oct 11, 2019
1 parent 427b3f0 commit f448f2c
Show file tree
Hide file tree
Showing 4 changed files with 147 additions and 2 deletions.
80 changes: 79 additions & 1 deletion include/boost/gil/image_processing/filter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,12 @@ void box_filter(
if (anchor == -1) anchor = static_cast<int>(kernel_size / 2);
kernel_1d<float> kernel(kernel_values.begin(), kernel_size, anchor);

convolve_1d<pixel<float, typename SrcView::value_type::layout_t>>(src_view, kernel, dst_view, option);
convolve_1d<pixel<float, typename SrcView::value_type::layout_t>>(
src_view,
kernel,
dst_view,
option
);
}

template <typename SrcView, typename DstView>
Expand All @@ -60,6 +65,79 @@ void blur(
box_filter(src_view, dst_view, kernel_size, anchor, true, option);
}


namespace detail
{
template <typename SrcView, typename DstView>
void impl_median(
SrcView const& src_view,
DstView const& dst_view,
std::size_t kernel_size
)
{
std::size_t half_kernel_size = kernel_size / 2;

//deciding output channel type and creating functor
using src_channel_t = typename channel_type<SrcView>::type;

for (std::ptrdiff_t y = 0; y < src_view.height(); y++)
{
typename DstView::x_iterator dst_it = dst_view.row_begin(y);

for (std::ptrdiff_t x = 0; x < src_view.width(); x++)
{
auto sub_view = subimage_view(
src_view,
x - half_kernel_size, y - half_kernel_size,
kernel_size,
kernel_size
);
std::vector<src_channel_t> values(sub_view.begin(), sub_view.end());

std::nth_element(values.begin(), values.begin() + (values.size() / 2), values.end());
dst_it[x] = values[values.size() / 2];
}
}
}
} // namespace detail

template <typename SrcView, typename DstView>
void median_filter(
SrcView const& src_view,
DstView const& dst_view,
std::size_t kernel_size
)
{
static_assert(color_spaces_are_compatible
<
typename color_space_type<SrcView>::type,
typename color_space_type<DstView>::type
>::value, "Source and destination views must have pixels with the same color space");

std::size_t half_kernel_size = kernel_size / 2;
auto extended_img = extend_boundary(
src_view,
half_kernel_size,
boundary_option::extend_constant
);
auto extended_view = subimage_view(
view(extended_img),
half_kernel_size,
half_kernel_size,
src_view.width(),
src_view.height()
);

for (std::size_t channel = 0; channel < extended_view.num_channels(); channel++)
{
detail::impl_median(
nth_channel_view(extended_view, channel),
nth_channel_view(dst_view, channel),
kernel_size
);
}
}

}} //namespace boost::gil

#endif // !BOOST_GIL_IMAGE_PROCESSING_FILTER_HPP
3 changes: 2 additions & 1 deletion test/core/image_processing/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ foreach(_name
simple_kernels
harris
hessian
box_filter)
box_filter
median_filter)
set(_test t_core_image_processing_${_name})
set(_target test_core_image_processing_${_name})

Expand Down
1 change: 1 addition & 0 deletions test/core/image_processing/Jamfile
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@ run simple_kernels.cpp ;
run harris.cpp ;
run hessian.cpp ;
run box_filter.cpp /boost/test//boost_unit_test_framework : : : <link>shared:<define>BOOST_TEST_DYN_LINK=1 ;
run median_filter.cpp /boost/test//boost_unit_test_framework : : : <link>shared:<define>BOOST_TEST_DYN_LINK=1 ;
65 changes: 65 additions & 0 deletions test/core/image_processing/median_filter.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
//
// Copyright 2019 Miral Shah <[email protected]>
//
// 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)
//

#define BOOST_TEST_MODULE test_image_processing_median_filter
#include "unit_test.hpp"

#include <boost/gil/image_view.hpp>
#include <boost/gil/algorithm.hpp>
#include <boost/gil/gray.hpp>
#include <boost/gil/image_processing/filter.hpp>


namespace gil = boost::gil;

std::uint8_t img[] =
{
183, 128, 181, 86, 34, 55, 134, 164, 15,
90, 59, 94, 158, 202, 0, 106, 120, 255,
65, 48, 4, 21, 21, 38, 50, 37, 228,
27, 245, 254, 164, 135, 192, 17, 241, 19,
56, 165, 253, 169, 24, 200, 249, 70, 199,
59, 84, 41, 96, 70, 58, 24, 20, 218,
235, 180, 12, 168, 224, 204, 166, 153, 1,
181, 213, 232, 178, 165, 253, 93, 214, 72,
171, 50, 20, 65, 67, 133, 249, 157, 105
};

std::uint8_t output[] =
{
128, 128, 128, 94, 55, 55, 120, 134, 120,
90, 90, 86, 86, 38, 50, 55, 120, 164,
65, 65, 94, 135, 135, 50, 50, 106, 228,
56, 65, 165, 135, 135, 50, 70, 70, 199,
59, 84, 165, 135, 135, 70, 70, 70, 199,
84, 84, 165, 96, 168, 166, 153, 153, 153,
181, 180, 168, 165, 168, 165, 153, 93, 72,
181, 180, 168, 165, 168, 166, 166, 153, 105,
171, 171, 65, 67, 133, 133, 157, 157, 105
};

BOOST_AUTO_TEST_SUITE(filter)

BOOST_AUTO_TEST_CASE(median_filter_with_kernel_size_3)
{
gil::gray8c_view_t src_view =
gil::interleaved_view(9, 9, reinterpret_cast<const gil::gray8_pixel_t*>(img), 9);

gil::image<gil::gray8_pixel_t> temp_img(src_view.width(), src_view.height());
typename gil::image<gil::gray8_pixel_t>::view_t temp_view = view(temp_img);
gil::gray8_view_t dst_view(temp_view);

gil::median_filter(src_view, dst_view, 3);

gil::gray8c_view_t out_view =
gil::interleaved_view(9, 9, reinterpret_cast<const gil::gray8_pixel_t*>(output), 9);

BOOST_TEST(gil::equal_pixels(out_view, dst_view));
}

BOOST_AUTO_TEST_SUITE_END()

0 comments on commit f448f2c

Please sign in to comment.