    // Copyright (C) 2006  Davis E. King (davis@dlib.net)
    // License: Boost Software License   See LICENSE.txt for the full license.
    #undef DLIB_THRESHOLDINg_ABSTRACT_
    #ifdef DLIB_THRESHOLDINg_ABSTRACT_

    #include "../pixel.h"

    namespace dlib
    {

    // ----------------------------------------------------------------------------------------

        const unsigned char on_pixel = 255;
        const unsigned char off_pixel = 0;

    // ----------------------------------------------------------------------------------------

        template <
            typename image_type
            >
        typename pixel_traits<typename image_traits<image_type>::pixel_type>::basic_pixel_type
        partition_pixels (
            const image_type& img
        );
        /*!
            requires
                - image_type == an image object that implements the interface defined in
                  dlib/image_processing/generic_image.h
                - pixel_traits<typename image_traits<image_type>::pixel_type>::has_alpha == false
            ensures
                - Finds a threshold value that would be reasonable to use with
                  threshold_image(img, threshold).  It does this by finding the threshold that
                  partitions the pixels in img into two groups such that the sum of absolute
                  deviations between each pixel and the mean of its group is minimized.
        !*/

        template <
            typename image_type,
            typename ...T
            >
        void partition_pixels (
            const image_type& img,
            typename pixel_traits<typename image_traits<image_type>::pixel_type>::basic_pixel_type& pix_thresh,
            T&& ...more_thresholds
        );
        /*!
            requires
                - image_type == an image object that implements the interface defined in
                  dlib/image_processing/generic_image.h
                - pixel_traits<typename image_traits<image_type>::pixel_type>::has_alpha == false
                - more_thresholds == a bunch of parameters of the same type as pix_thresh.
            ensures
                - This version of partition_pixels() finds multiple partitions rather than just
                  one partition.  It does this by first partitioning the pixels just as the
                  above partition_pixels(img) does.  Then it forms a new image with only pixels
                  >= that first partition value and recursively partitions this new image.
                  However, the recursion is implemented in an efficient way which is faster than
                  explicitly forming these images and calling partition_pixels(), but the
                  output is the same as if you did.  For example, suppose you called
                  partition_pixels(img, t1, t2, t3).  Then we would have:
                    - t1 == partition_pixels(img)
                    - t2 == partition_pixels(an image with only pixels with values >= t1 in it)
                    - t3 == partition_pixels(an image with only pixels with values >= t2 in it)
        !*/

    // ----------------------------------------------------------------------------------------

        template <
            typename in_image_type,
            typename out_image_type
            >
        void threshold_image (
            const in_image_type& in_img,
            out_image_type& out_img,
            typename pixel_traits<typename image_traits<in_image_type>::pixel_type>::basic_pixel_type thresh
        );
        /*!
            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
                - pixel_traits<typename image_traits<out_image_type>::pixel_type>::grayscale == true
                - pixel_traits<typename image_traits<in_image_type>::pixel_type>::has_alpha == false
                - pixel_traits<typename image_traits<out_image_type>::pixel_type>::has_alpha == false
            ensures
                - #out_img == the thresholded version of in_img (in_img is converted to a grayscale
                  intensity image if it is color).  Pixels in in_img with grayscale values >= thresh
                  have an output value of on_pixel and all others have a value of off_pixel.
                - #out_img.nc() == in_img.nc()
                - #out_img.nr() == in_img.nr()
        !*/

        template <
            typename image_type
            >
        void threshold_image (
            image_type& img,
            typename pixel_traits<typename image_traits<image_type>::pixel_type>::basic_pixel_type thresh
        );
        /*!
            requires
                - it is valid to call threshold_image(img,img,thresh);
            ensures
                - calls threshold_image(img,img,thresh);
        !*/

        template <
            typename in_image_type,
            typename out_image_type
            >
        void threshold_image (
            const in_image_type& in_img,
            out_image_type& out_img
        );
        /*!
            requires
                - it is valid to call threshold_image(in_img,out_img,partition_pixels(in_img));
            ensures
                - calls threshold_image(in_img,out_img,partition_pixels(in_img));
        !*/

        template <
            typename image_type
            >
        void threshold_image (
            image_type& img
        );
        /*!
            requires
                - it is valid to call threshold_image(img,img,partition_pixels(img));
            ensures
                - calls threshold_image(img,img,partition_pixels(img));
        !*/

    // ----------------------------------------------------------------------------------------

        template <
            typename in_image_type,
            typename out_image_type
            >
        void hysteresis_threshold (
            const in_image_type& in_img,
            out_image_type& out_img,
            typename pixel_traits<typename image_traits<in_image_type>::pixel_type>::basic_pixel_type lower_thresh,
            typename pixel_traits<typename image_traits<in_image_type>::pixel_type>::basic_pixel_type upper_thresh
        );
        /*!
            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
                - pixel_traits<typename image_traits<out_image_type>::pixel_type>::grayscale == true
                - pixel_traits<typename image_traits<in_image_type>::pixel_type>::has_alpha == false
                - pixel_traits<typename image_traits<out_image_type>::pixel_type>::has_alpha == false
                - is_same_object(in_img, out_img) == false
            ensures
                - #out_img == the hysteresis thresholded version of in_img (in_img is converted to a
                  grayscale intensity image if it is color). Pixels in in_img with grayscale
                  values >= upper_thresh have an output value of on_pixel and all others have a
                  value of off_pixel unless they are >= lower_thresh and are connected to a pixel
                  with a value >= upper_thresh, in which case they have a value of on_pixel.  Here
                  pixels are connected if there is a path between them composed of pixels that
                  would receive an output of on_pixel.
                - #out_img.nc() == in_img.nc()
                - #out_img.nr() == in_img.nr()
        !*/

        template <
            typename in_image_type,
            typename out_image_type
            >
        void hysteresis_threshold (
            const in_image_type& in_img,
            out_image_type& out_img
        );
        /*!
            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
                - pixel_traits<typename image_traits<out_image_type>::pixel_type>::grayscale == true
                - pixel_traits<typename image_traits<in_image_type>::pixel_type>::has_alpha == false
                - pixel_traits<typename image_traits<out_image_type>::pixel_type>::has_alpha == false
                - is_same_object(in_img, out_img) == false
            ensures
                - performs: hysteresis_threshold(in_img, out_img, t1, t2) where the thresholds
                  are first obtained by calling partition_pixels(in_img, t1, t2).
        !*/

    // ----------------------------------------------------------------------------------------

    }

    #endif // DLIB_THRESHOLDINg_ABSTRACT_