Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-16 09:51:52

0001 //
0002 // Copyright 2021 Prathamesh Tagore <prathameshtagore@gmail.com>
0003 //
0004 // Use, modification and distribution are subject to the Boost Software License,
0005 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
0006 // http://www.boost.org/LICENSE_1_0.txt)
0007 //
0008 
0009 #ifndef BOOST_GIL_IMAGE_PROCESSING_MORPHOLOGY_HPP
0010 #define BOOST_GIL_IMAGE_PROCESSING_MORPHOLOGY_HPP
0011 
0012 #include <boost/gil/image_processing/kernel.hpp>
0013 #include <boost/gil/gray.hpp>
0014 #include <boost/gil/image_processing/threshold.hpp>
0015 
0016 namespace boost { namespace gil { namespace detail {
0017 
0018 enum class morphological_operation
0019 {
0020     dilation,
0021     erosion,
0022 };
0023 
0024 /// \addtogroup ImageProcessing
0025 /// @{
0026 
0027 /// \brief Implements morphological operations at pixel level.This function
0028 /// compares neighbouring pixel values according to the kernel and choose
0029 /// minimum/mamximum neighbouring pixel value and assigns it to the pixel under
0030 /// consideration.
0031 /// \param src_view - Source/Input image view.
0032 /// \param dst_view - View which stores the final result of operations performed by this function.
0033 /// \param kernel - Kernel matrix/structuring element containing 0's and 1's
0034 /// which will be used for applying the required morphological operation.
0035 /// \param identifier - Indicates the type of morphological operation to be applied.
0036 /// \tparam SrcView type of source image.
0037 /// \tparam DstView type of output image.
0038 /// \tparam Kernel type of structuring element.
0039 template <typename SrcView, typename DstView, typename Kernel>
0040 void morph_impl(SrcView const& src_view, DstView const& dst_view, Kernel const& kernel,
0041                 morphological_operation identifier)
0042 {
0043     std::ptrdiff_t flip_ker_row, flip_ker_col, row_boundary, col_boundary;
0044     typename channel_type<typename SrcView::value_type>::type target_element;
0045     for (std::ptrdiff_t view_row = 0; view_row < src_view.height(); ++view_row)
0046     {
0047         for (std::ptrdiff_t view_col = 0; view_col < src_view.width(); ++view_col)
0048         {
0049             target_element = src_view(view_col, view_row);
0050             for (std::size_t kernel_row = 0; kernel_row < kernel.size(); ++kernel_row)
0051             {
0052                 flip_ker_row = kernel.size() - 1 - kernel_row; // row index of flipped kernel
0053 
0054                 for (std::size_t kernel_col = 0; kernel_col < kernel.size(); ++kernel_col)
0055                 {
0056                     flip_ker_col = kernel.size() - 1 - kernel_col; // column index of flipped kernel
0057 
0058                     // We ensure that we consider only those pixels which are overlapped
0059                     // on a non-zero kernel_element as
0060                     if (kernel.at(flip_ker_row, flip_ker_col) == 0)
0061                     {
0062                         continue;
0063                     }
0064                     // index of input signal, used for checking boundary
0065                     row_boundary = view_row + (kernel.center_y() - flip_ker_row);
0066                     col_boundary = view_col + (kernel.center_x() - flip_ker_col);
0067 
0068                     // ignore input samples which are out of bound
0069                     if (row_boundary >= 0 && row_boundary < src_view.height() &&
0070                         col_boundary >= 0 && col_boundary < src_view.width())
0071                     {
0072 
0073                         if (identifier == morphological_operation::dilation)
0074                         {
0075                             target_element =
0076                                 (std::max)(src_view(col_boundary, row_boundary)[0], target_element);
0077                         }
0078                         else if (identifier == morphological_operation::erosion)
0079                         {
0080                             target_element =
0081                                 (std::min)(src_view(col_boundary, row_boundary)[0], target_element);
0082                         }
0083                     }
0084                 }
0085             }
0086             dst_view(view_col, view_row) = target_element;
0087         }
0088     }
0089 }
0090 
0091 /// \brief Checks feasibility of the desired operation and passes parameter
0092 /// values to the function morph_impl alongwith individual channel views of the
0093 /// input image.
0094 /// \param src_view - Source/Input image view.
0095 /// \param dst_view - View which stores the final result of operations performed by this function.
0096 /// \param kernel - Kernel matrix/structuring element containing 0's and 1's
0097 /// which will be used for applying the required morphological operation.
0098 /// \param identifier - Indicates the type of morphological operation to be applied.
0099 /// \tparam SrcView type of source image.
0100 /// \tparam DstView type of output image.
0101 /// \tparam Kernel type of structuring element.
0102 template <typename SrcView, typename DstView, typename Kernel>
0103 void morph(SrcView const& src_view, DstView const& dst_view, Kernel const& ker_mat,
0104            morphological_operation identifier)
0105 {
0106     BOOST_ASSERT(ker_mat.size() != 0 && src_view.dimensions() == dst_view.dimensions());
0107     gil_function_requires<ImageViewConcept<SrcView>>();
0108     gil_function_requires<MutableImageViewConcept<DstView>>();
0109 
0110     gil_function_requires<ColorSpacesCompatibleConcept<typename color_space_type<SrcView>::type,
0111                                                        typename color_space_type<DstView>::type>>();
0112 
0113     gil::image<typename DstView::value_type> intermediate_img(src_view.dimensions());
0114 
0115     for (std::size_t i = 0; i < src_view.num_channels(); i++)
0116     {
0117         morph_impl(nth_channel_view(src_view, i), nth_channel_view(view(intermediate_img), i),
0118                    ker_mat, identifier);
0119     }
0120     copy_pixels(view(intermediate_img), dst_view);
0121 }
0122 
0123 /// \brief Calculates the difference between pixel values of first image_view
0124 /// and second image_view.
0125 /// \param src_view1 - First parameter for subtraction of views.
0126 /// \param src_view2 - Second parameter for subtraction of views.
0127 /// \param diff_view - View containing result of the subtraction of second view from
0128 /// the first view.
0129 /// \tparam SrcView type of source/Input images used for subtraction.
0130 /// \tparam DiffView type of image view containing the result of subtraction.
0131 template <typename SrcView, typename DiffView>
0132 void difference_impl(SrcView const& src_view1, SrcView const& src_view2, DiffView const& diff_view)
0133 {
0134     for (std::ptrdiff_t view_row = 0; view_row < src_view1.height(); ++view_row)
0135         for (std::ptrdiff_t view_col = 0; view_col < src_view1.width(); ++view_col)
0136             diff_view(view_col, view_row) =
0137                 src_view1(view_col, view_row) - src_view2(view_col, view_row);
0138 }
0139 
0140 /// \brief Passes parameter values to the function 'difference_impl' alongwith
0141 /// individual channel views of input images.
0142 /// \param src_view1 - First parameter for subtraction of views.
0143 /// \param src_view2 - Second parameter for subtraction of views.
0144 /// \param diff_view - View containing result of the subtraction of second view from the first view.
0145 /// \tparam SrcView type of source/Input images used for subtraction.
0146 /// \tparam DiffView type of image view containing the result of subtraction.
0147 template <typename SrcView, typename DiffView>
0148 void difference(SrcView const& src_view1, SrcView const& src_view2, DiffView const& diff_view)
0149 {
0150     gil_function_requires<ImageViewConcept<SrcView>>();
0151     gil_function_requires<MutableImageViewConcept<DiffView>>();
0152 
0153     gil_function_requires<ColorSpacesCompatibleConcept<
0154         typename color_space_type<SrcView>::type, typename color_space_type<DiffView>::type>>();
0155 
0156     for (std::size_t i = 0; i < src_view1.num_channels(); i++)
0157     {
0158         difference_impl(nth_channel_view(src_view1, i), nth_channel_view(src_view2, i),
0159                         nth_channel_view(diff_view, i));
0160     }
0161 }
0162 } // namespace detail
0163 
0164 /// \brief Applies morphological dilation on the input image view using given
0165 /// structuring element. It gives the maximum overlapped value to the pixel
0166 /// overlapping with the center element of structuring element. \param src_view
0167 /// - Source/input image view.
0168 /// \param int_op_view - view for writing output and performing intermediate operations.
0169 /// \param ker_mat - Kernel matrix/structuring element containing 0's and 1's which will be used for
0170 /// applying dilation.
0171 /// \param iterations - Specifies the number of times dilation is to be applied on the input image
0172 /// view.
0173 /// \tparam SrcView type of source image, models gil::ImageViewConcept.
0174 /// \tparam IntOpView type of output image, models gil::MutableImageViewConcept.
0175 /// \tparam Kernel type of structuring element.
0176 template <typename SrcView, typename IntOpView, typename Kernel>
0177 void dilate(SrcView const& src_view, IntOpView const& int_op_view, Kernel const& ker_mat,
0178             int iterations)
0179 {
0180     copy_pixels(src_view, int_op_view);
0181     for (int i = 0; i < iterations; ++i)
0182         morph(int_op_view, int_op_view, ker_mat, detail::morphological_operation::dilation);
0183 }
0184 
0185 /// \brief Applies morphological erosion on the input image view using given
0186 /// structuring element. It gives the minimum overlapped value to the pixel
0187 /// overlapping with the center element of structuring element.
0188 /// \param src_view - Source/input image view.
0189 /// \param int_op_view - view for writing output and performing intermediate operations.
0190 /// \param ker_mat - Kernel matrix/structuring element containing 0's and 1's which will be used for
0191 /// applying erosion.
0192 /// \param iterations - Specifies the number of times erosion is to be applied on the input
0193 /// image view.
0194 /// \tparam SrcView type of source image, models gil::ImageViewConcept.
0195 /// \tparam IntOpView type of output image, models gil::MutableImageViewConcept.
0196 /// \tparam Kernel type of structuring element.
0197 template <typename SrcView, typename IntOpView, typename Kernel>
0198 void erode(SrcView const& src_view, IntOpView const& int_op_view, Kernel const& ker_mat,
0199            int iterations)
0200 {
0201     copy_pixels(src_view, int_op_view);
0202     for (int i = 0; i < iterations; ++i)
0203         morph(int_op_view, int_op_view, ker_mat, detail::morphological_operation::erosion);
0204 }
0205 
0206 /// \brief Performs erosion and then dilation on the input image view . This
0207 /// operation is utilized for removing noise from images.
0208 /// \param src_view - Source/input image view.
0209 /// \param int_op_view - view for writing output and performing intermediate operations.
0210 /// \param ker_mat - Kernel matrix/structuring element containing 0's and 1's which will be used for
0211 /// applying the opening operation.
0212 /// \tparam SrcView type of source image, models gil::ImageViewConcept.
0213 /// \tparam IntOpView type of output image, models gil::MutableImageViewConcept.
0214 /// \tparam Kernel type of structuring element.
0215 template <typename SrcView, typename IntOpView, typename Kernel>
0216 void opening(SrcView const& src_view, IntOpView const& int_op_view, Kernel const& ker_mat)
0217 {
0218     erode(src_view, int_op_view, ker_mat, 1);
0219     dilate(int_op_view, int_op_view, ker_mat, 1);
0220 }
0221 
0222 /// \brief Performs dilation and then erosion on the input image view which is
0223 /// exactly opposite to the opening operation . Closing operation can be
0224 /// utilized for closing small holes inside foreground objects.
0225 /// \param src_view - Source/input image view.
0226 /// \param int_op_view - view for writing output and performing intermediate operations.
0227 /// \param ker_mat - Kernel matrix/structuring element containing 0's and 1's which will be used for
0228 /// applying the closing operation.
0229 /// \tparam SrcView type of source image, models gil::ImageViewConcept.
0230 /// \tparam IntOpView type of output image, models gil::MutableImageViewConcept.
0231 /// \tparam Kernel type of structuring element.
0232 template <typename SrcView, typename IntOpView, typename Kernel>
0233 void closing(SrcView const& src_view, IntOpView const& int_op_view, Kernel const& ker_mat)
0234 {
0235     dilate(src_view, int_op_view, ker_mat, 1);
0236     erode(int_op_view, int_op_view, ker_mat, 1);
0237 }
0238 
0239 /// \brief Calculates the difference between image views generated after
0240 /// applying dilation dilation and erosion on an image . The resultant image
0241 /// will look like the outline of the object(s) present in the image.
0242 /// \param src_view - Source/input image view.
0243 /// \param dst_view - Destination view which will store the final result of morphological
0244 /// gradient operation.
0245 /// \param ker_mat - Kernel matrix/structuring element containing 0's and 1's which
0246 /// will be used for applying the morphological gradient operation.
0247 /// \tparam SrcView type of source image, models gil::ImageViewConcept.
0248 /// \tparam DstView type of output image, models gil::MutableImageViewConcept.
0249 /// \tparam Kernel type of structuring element.
0250 template <typename SrcView, typename DstView, typename Kernel>
0251 void morphological_gradient(SrcView const& src_view, DstView const& dst_view, Kernel const& ker_mat)
0252 {
0253     using namespace boost::gil;
0254     gil::image<typename DstView::value_type> int_dilate(src_view.dimensions()),
0255         int_erode(src_view.dimensions());
0256     dilate(src_view, view(int_dilate), ker_mat, 1);
0257     erode(src_view, view(int_erode), ker_mat, 1);
0258     difference(view(int_dilate), view(int_erode), dst_view);
0259 }
0260 
0261 /// \brief Calculates the difference between input image view and the view
0262 /// generated by opening operation on the input image view.
0263 /// \param src_view - Source/input image view.
0264 /// \param dst_view - Destination view which will store the final result of top hat operation.
0265 /// \param ker_mat - Kernel matrix/structuring element containing 0's and 1's which will be used for
0266 /// applying the top hat operation.
0267 /// \tparam SrcView type of source image, models gil::ImageViewConcept.
0268 /// \tparam DstView type of output image, models gil::MutableImageViewConcept.
0269 /// \tparam Kernel type of structuring element.
0270 template <typename SrcView, typename DstView, typename Kernel>
0271 void top_hat(SrcView const& src_view, DstView const& dst_view, Kernel const& ker_mat)
0272 {
0273     using namespace boost::gil;
0274     gil::image<typename DstView::value_type> int_opening(src_view.dimensions());
0275     opening(src_view, view(int_opening), ker_mat);
0276     difference(src_view, view(int_opening), dst_view);
0277 }
0278 
0279 /// \brief Calculates the difference between closing of the input image and
0280 /// input image.
0281 /// \param src_view - Source/input image view.
0282 /// \param dst_view - Destination view which will store the final result of black hat operation.
0283 /// \param ker_mat - Kernel matrix/structuring element containing 0's and 1's
0284 /// which will be used for applying the black hat operation.
0285 /// \tparam SrcView type of source image, models gil::ImageViewConcept.
0286 /// \tparam DstView type of output image, models gil::MutableImageViewConcept.
0287 /// \tparam Kernel type of structuring element.
0288 template <typename SrcView, typename DstView, typename Kernel>
0289 void black_hat(SrcView const& src_view, DstView const& dst_view, Kernel const& ker_mat)
0290 {
0291     using namespace boost::gil;
0292     gil::image<typename DstView::value_type> int_closing(src_view.dimensions());
0293     closing(src_view, view(int_closing), ker_mat);
0294     difference(view(int_closing), src_view, dst_view);
0295 }
0296 /// @}
0297 }}     // namespace boost::gil
0298 #endif // BOOST_GIL_IMAGE_PROCESSING_MORPHOLOGY_HPP