// Copyright (C) 2011 Davis E. King (davis@dlib.net) // License: Boost Software License See LICENSE.txt for the full license. #undef DLIB_LABEL_CONNeCTED_BLOBS_ABSTRACT_H_ #ifdef DLIB_LABEL_CONNeCTED_BLOBS_ABSTRACT_H_ #include "../geometry.h" #include <vector> #include "../image_processing/generic_image.h" namespace dlib { // ---------------------------------------------------------------------------------------- struct neighbors_24 { /*! WHAT THIS OBJECT REPRESENTS This object is a pixel neighborhood generating functor for use with the label_connected_blobs() routine defined below. !*/ void operator() ( const point& p, std::vector<point>& neighbors ) const; /*! ensures - adds the 24 neighboring pixels surrounding p into neighbors !*/ }; struct neighbors_8 { /*! WHAT THIS OBJECT REPRESENTS This object is a pixel neighborhood generating functor for use with the label_connected_blobs() routine defined below. !*/ void operator() ( const point& p, std::vector<point>& neighbors ) const; /*! ensures - adds the 8 neighboring pixels surrounding p into neighbors !*/ }; struct neighbors_4 { /*! WHAT THIS OBJECT REPRESENTS This object is a pixel neighborhood generating functor for use with the label_connected_blobs() routine defined below. !*/ void operator() ( const point& p, std::vector<point>& neighbors ) const; /*! ensures - adds the 4 neighboring pixels of p into neighbors. These are the ones immediately to the left, top, right, and bottom. !*/ }; // ---------------------------------------------------------------------------------------- struct connected_if_both_not_zero { /*! WHAT THIS OBJECT REPRESENTS This object is a pixel connection testing functor for use with the label_connected_blobs() routine defined below. !*/ template <typename image_view_type> bool operator() ( const image_view_type& img, const point& a, const point& b ) const { return (img[a.y()][a.x()] != 0 && img[b.y()][b.x()] != 0); } }; struct connected_if_equal { /*! WHAT THIS OBJECT REPRESENTS This object is a pixel connection testing functor for use with the label_connected_blobs() routine defined below. !*/ template <typename image_view_type> bool operator() ( const image_view_type& img, const point& a, const point& b ) const { return (img[a.y()][a.x()] == img[b.y()][b.x()]); } }; // ---------------------------------------------------------------------------------------- struct zero_pixels_are_background { /*! WHAT THIS OBJECT REPRESENTS This object is a background testing functor for use with the label_connected_blobs() routine defined below. !*/ template <typename image_view_type> bool operator() ( const image_view_type& img, const point& p ) const { return img[p.y()][p.x()] == 0; } }; struct nothing_is_background { /*! WHAT THIS OBJECT REPRESENTS This object is a background testing functor for use with the label_connected_blobs() routine defined below. !*/ template <typename image_view_type> bool operator() ( const image_view_type&, const point& ) const { return false; } }; // ---------------------------------------------------------------------------------------- template < typename image_type, typename label_image_type, typename background_functor_type, typename neighbors_functor_type, typename connected_functor_type > unsigned long label_connected_blobs ( const image_type& img, const background_functor_type& is_background, const neighbors_functor_type& get_neighbors, const connected_functor_type& is_connected, label_image_type& label_img ); /*! requires - image_type == an image object that implements the interface defined in dlib/image_processing/generic_image.h - label_image_type == an image object that implements the interface defined in dlib/image_processing/generic_image.h and it must contain integer pixels. - is_background(img, point(c,r)) is a legal expression that evaluates to a bool. - is_connected(img, point(c,r), point(c2,r2)) is a legal expression that evaluates to a bool. - get_neighbors(point(c,r), neighbors) is a legal expression where neighbors is of type std::vector<point>. - is_same_object(img, label_img) == false ensures - This function labels each of the connected blobs in img with a unique integer label. - An image can be thought of as a graph where pixels A and B are connected if and only if the following two statements are satisfied: - is_connected(img,A,B) == true - get_neighbors(A, neighbors) results in neighbors containing B or get_neighbors(B, neighbors) results in neighbors containing A. Then this function can be understood as labeling all the connected components of this pixel graph such that all pixels in a component get the same label while pixels in different components get different labels. Note that there is a special "background" component determined by is_background(). Any pixels which are "background" always get a blob id of 0 regardless of any other considerations. - #label_img.nr() == img.nr() - #label_img.nc() == img.nc() - for all valid r and c: - #label_img[r][c] == the blob label number for pixel img[r][c]. - #label_img[r][c] >= 0 - if (is_background(img, point(c,r))) then - #label_img[r][c] == 0 - else - #label_img[r][c] != 0 - if (img.size() != 0) then - returns max(mat(#label_img))+1 (i.e. returns a number one greater than the maximum blob id number, this is the number of blobs found.) - else - returns 0 - blob labels are contiguous, therefore, the number returned by this function is the number of blobs in the image (including the background blob). - It is guaranteed that is_connected() and is_background() will never be called with points outside the image. !*/ // ---------------------------------------------------------------------------------------- template < typename in_image_type, typename out_image_type > unsigned long label_connected_blobs_watershed ( const in_image_type& img, out_image_type& labels, typename pixel_traits<typename image_traits<in_image_type>::pixel_type>::basic_pixel_type background_thresh, const double smoothing = 0 ); /*! requires - in_image_type == an image object that implements the interface defined in dlib/image_processing/generic_image.h - out_image_type == an image object that implements the interface defined in dlib/image_processing/generic_image.h - in_image_type must contain a grayscale pixel type. - out_image_type must contain an unsigned integer pixel type. - is_same_object(img, labels) == false - smoothing >= 0 ensures - This routine performs a watershed segmentation of the given input image and labels each resulting flooding region with a unique integer label. It does this by marking the brightest pixels as sources of flooding and then flood fills the image outward from those sources. Each flooded area is labeled with the identity of the source pixel and flooding stops when another flooded area is reached or pixels with values < background_thresh are encountered. - The flooding will also overrun a source pixel if that source pixel has yet to label any neighboring pixels. This behavior helps to mitigate spurious splits of objects due to noise. You can further control this behavior by setting the smoothing parameter. The flooding will take place on an image that has been Gaussian blurred with a sigma==smoothing. So setting smoothing to a larger number will in general cause more regions to be merged together. Note that the smoothing parameter has no effect on the interpretation of background_thresh since the decision of "background or not background" is always made relative to the unsmoothed input image. - #labels.nr() == img.nr() - #labels.nc() == img.nc() - for all valid r and c: - if (img[r][c] < background_thresh) then - #labels[r][c] == 0, (i.e. the pixel is labeled as background) - else - #labels[r][c] == an integer value indicating the identity of the segment containing the pixel img[r][c]. - returns the number of labeled segments, including the background segment. Therefore, the returned number is 1+(the max value in #labels). !*/ template < typename in_image_type, typename out_image_type > unsigned long label_connected_blobs_watershed ( const in_image_type& img, out_image_type& labels ); /*! simply invokes: return label_connected_blobs_watershed(img, labels, partition_pixels(img)); !*/ // ---------------------------------------------------------------------------------------- } #endif // DLIB_LABEL_CONNeCTED_BLOBS_ABSTRACT_H_