123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298 |
- #ifndef BOOST_GIL_IMAGE_PROCESSING_MORPHOLOGY_HPP
- #define BOOST_GIL_IMAGE_PROCESSING_MORPHOLOGY_HPP
- #include <boost/gil/image_processing/kernel.hpp>
- #include <boost/gil/gray.hpp>
- #include <boost/gil/image_processing/threshold.hpp>
- namespace boost { namespace gil { namespace detail {
- enum class morphological_operation
- {
- dilation,
- erosion,
- };
- template <typename SrcView, typename DstView, typename Kernel>
- void morph_impl(SrcView const& src_view, DstView const& dst_view, Kernel const& kernel,
- morphological_operation identifier)
- {
- std::ptrdiff_t flip_ker_row, flip_ker_col, row_boundary, col_boundary;
- typename channel_type<typename SrcView::value_type>::type target_element;
- for (std::ptrdiff_t view_row = 0; view_row < src_view.height(); ++view_row)
- {
- for (std::ptrdiff_t view_col = 0; view_col < src_view.width(); ++view_col)
- {
- target_element = src_view(view_col, view_row);
- for (std::size_t kernel_row = 0; kernel_row < kernel.size(); ++kernel_row)
- {
- flip_ker_row = kernel.size() - 1 - kernel_row;
- for (std::size_t kernel_col = 0; kernel_col < kernel.size(); ++kernel_col)
- {
- flip_ker_col = kernel.size() - 1 - kernel_col;
-
-
- if (kernel.at(flip_ker_row, flip_ker_col) == 0)
- {
- continue;
- }
-
- row_boundary = view_row + (kernel.center_y() - flip_ker_row);
- col_boundary = view_col + (kernel.center_x() - flip_ker_col);
-
- if (row_boundary >= 0 && row_boundary < src_view.height() &&
- col_boundary >= 0 && col_boundary < src_view.width())
- {
- if (identifier == morphological_operation::dilation)
- {
- target_element =
- (std::max)(src_view(col_boundary, row_boundary)[0], target_element);
- }
- else if (identifier == morphological_operation::erosion)
- {
- target_element =
- (std::min)(src_view(col_boundary, row_boundary)[0], target_element);
- }
- }
- }
- }
- dst_view(view_col, view_row) = target_element;
- }
- }
- }
- template <typename SrcView, typename DstView, typename Kernel>
- void morph(SrcView const& src_view, DstView const& dst_view, Kernel const& ker_mat,
- morphological_operation identifier)
- {
- BOOST_ASSERT(ker_mat.size() != 0 && src_view.dimensions() == dst_view.dimensions());
- gil_function_requires<ImageViewConcept<SrcView>>();
- gil_function_requires<MutableImageViewConcept<DstView>>();
- gil_function_requires<ColorSpacesCompatibleConcept<typename color_space_type<SrcView>::type,
- typename color_space_type<DstView>::type>>();
- gil::image<typename DstView::value_type> intermediate_img(src_view.dimensions());
- for (std::size_t i = 0; i < src_view.num_channels(); i++)
- {
- morph_impl(nth_channel_view(src_view, i), nth_channel_view(view(intermediate_img), i),
- ker_mat, identifier);
- }
- copy_pixels(view(intermediate_img), dst_view);
- }
- template <typename SrcView, typename DiffView>
- void difference_impl(SrcView const& src_view1, SrcView const& src_view2, DiffView const& diff_view)
- {
- for (std::ptrdiff_t view_row = 0; view_row < src_view1.height(); ++view_row)
- for (std::ptrdiff_t view_col = 0; view_col < src_view1.width(); ++view_col)
- diff_view(view_col, view_row) =
- src_view1(view_col, view_row) - src_view2(view_col, view_row);
- }
- template <typename SrcView, typename DiffView>
- void difference(SrcView const& src_view1, SrcView const& src_view2, DiffView const& diff_view)
- {
- gil_function_requires<ImageViewConcept<SrcView>>();
- gil_function_requires<MutableImageViewConcept<DiffView>>();
- gil_function_requires<ColorSpacesCompatibleConcept<
- typename color_space_type<SrcView>::type, typename color_space_type<DiffView>::type>>();
- for (std::size_t i = 0; i < src_view1.num_channels(); i++)
- {
- difference_impl(nth_channel_view(src_view1, i), nth_channel_view(src_view2, i),
- nth_channel_view(diff_view, i));
- }
- }
- }
- template <typename SrcView, typename IntOpView, typename Kernel>
- void dilate(SrcView const& src_view, IntOpView const& int_op_view, Kernel const& ker_mat,
- int iterations)
- {
- copy_pixels(src_view, int_op_view);
- for (int i = 0; i < iterations; ++i)
- morph(int_op_view, int_op_view, ker_mat, detail::morphological_operation::dilation);
- }
- template <typename SrcView, typename IntOpView, typename Kernel>
- void erode(SrcView const& src_view, IntOpView const& int_op_view, Kernel const& ker_mat,
- int iterations)
- {
- copy_pixels(src_view, int_op_view);
- for (int i = 0; i < iterations; ++i)
- morph(int_op_view, int_op_view, ker_mat, detail::morphological_operation::erosion);
- }
- template <typename SrcView, typename IntOpView, typename Kernel>
- void opening(SrcView const& src_view, IntOpView const& int_op_view, Kernel const& ker_mat)
- {
- erode(src_view, int_op_view, ker_mat, 1);
- dilate(int_op_view, int_op_view, ker_mat, 1);
- }
- template <typename SrcView, typename IntOpView, typename Kernel>
- void closing(SrcView const& src_view, IntOpView const& int_op_view, Kernel const& ker_mat)
- {
- dilate(src_view, int_op_view, ker_mat, 1);
- erode(int_op_view, int_op_view, ker_mat, 1);
- }
- template <typename SrcView, typename DstView, typename Kernel>
- void morphological_gradient(SrcView const& src_view, DstView const& dst_view, Kernel const& ker_mat)
- {
- using namespace boost::gil;
- gil::image<typename DstView::value_type> int_dilate(src_view.dimensions()),
- int_erode(src_view.dimensions());
- dilate(src_view, view(int_dilate), ker_mat, 1);
- erode(src_view, view(int_erode), ker_mat, 1);
- difference(view(int_dilate), view(int_erode), dst_view);
- }
- template <typename SrcView, typename DstView, typename Kernel>
- void top_hat(SrcView const& src_view, DstView const& dst_view, Kernel const& ker_mat)
- {
- using namespace boost::gil;
- gil::image<typename DstView::value_type> int_opening(src_view.dimensions());
- opening(src_view, view(int_opening), ker_mat);
- difference(src_view, view(int_opening), dst_view);
- }
- template <typename SrcView, typename DstView, typename Kernel>
- void black_hat(SrcView const& src_view, DstView const& dst_view, Kernel const& ker_mat)
- {
- using namespace boost::gil;
- gil::image<typename DstView::value_type> int_closing(src_view.dimensions());
- closing(src_view, view(int_closing), ker_mat);
- difference(view(int_closing), src_view, dst_view);
- }
- }}
- #endif
|