// // Copyright 2019 Miral Shah // // 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) // #ifndef BOOST_GIL_IMAGE_PROCESSING_FILTER_HPP #define BOOST_GIL_IMAGE_PROCESSING_FILTER_HPP #include #include #include #include #include #include #include namespace boost { namespace gil { template void box_filter( SrcView const& src_view, DstView const& dst_view, std::size_t kernel_size, long int anchor = -1, bool normalize=true, boundary_option option = boundary_option::extend_zero ) { gil_function_requires>(); gil_function_requires>(); static_assert(color_spaces_are_compatible < typename color_space_type::type, typename color_space_type::type >::value, "Source and destination views must have pixels with the same color space"); std::vector kernel_values; if (normalize) { kernel_values.resize(kernel_size, 1.0f / float(kernel_size)); } else { kernel_values.resize(kernel_size, 1.0f); } if (anchor == -1) anchor = static_cast(kernel_size / 2); kernel_1d kernel(kernel_values.begin(), kernel_size, anchor); detail::convolve_1d < pixel >(src_view, kernel, dst_view, option); } template void blur( SrcView const& src_view, DstView const& dst_view, std::size_t kernel_size, long int anchor = -1, boundary_option option = boundary_option::extend_zero ) { box_filter(src_view, dst_view, kernel_size, anchor, true, option); } namespace detail { template void filter_median_impl(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::type; std::vector values; values.reserve(kernel_size * kernel_size); 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 ); values.assign(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 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::type, typename color_space_type::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::filter_median_impl( nth_channel_view(extended_view, channel), nth_channel_view(dst_view, channel), kernel_size ); } } }} //namespace boost::gil #endif // !BOOST_GIL_IMAGE_PROCESSING_FILTER_HPP