Home | History | Annotate | Download | only in MagickCore
      1 /*
      2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      3 %                                                                             %
      4 %                                                                             %
      5 %                                                                             %
      6 %               SSSSS  EEEEE   GGGG  M   M  EEEEE  N   N  TTTTT               %
      7 %               SS     E      G      MM MM  E      NN  N    T                 %
      8 %                SSS   EEE    G GGG  M M M  EEE    N N N    T                 %
      9 %                  SS  E      G   G  M   M  E      N  NN    T                 %
     10 %               SSSSS  EEEEE   GGGG  M   M  EEEEE  N   N    T                 %
     11 %                                                                             %
     12 %                                                                             %
     13 %    MagickCore Methods to Segment an Image with Thresholding Fuzzy c-Means   %
     14 %                                                                             %
     15 %                              Software Design                                %
     16 %                                   Cristy                                    %
     17 %                                April 1993                                   %
     18 %                                                                             %
     19 %                                                                             %
     20 %  Copyright 1999-2016 ImageMagick Studio LLC, a non-profit organization      %
     21 %  dedicated to making software imaging solutions freely available.           %
     22 %                                                                             %
     23 %  You may not use this file except in compliance with the License.  You may  %
     24 %  obtain a copy of the License at                                            %
     25 %                                                                             %
     26 %    http://www.imagemagick.org/script/license.php                            %
     27 %                                                                             %
     28 %  Unless required by applicable law or agreed to in writing, software        %
     29 %  distributed under the License is distributed on an "AS IS" BASIS,          %
     30 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
     31 %  See the License for the specific language governing permissions and        %
     32 %  limitations under the License.                                             %
     33 %                                                                             %
     34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     35 %
     36 %  Segment segments an image by analyzing the histograms of the color
     37 %  components and identifying units that are homogeneous with the fuzzy
     38 %  c-means technique.  The scale-space filter analyzes the histograms of
     39 %  the three color components of the image and identifies a set of
     40 %  classes.  The extents of each class is used to coarsely segment the
     41 %  image with thresholding.  The color associated with each class is
     42 %  determined by the mean color of all pixels within the extents of a
     43 %  particular class.  Finally, any unclassified pixels are assigned to
     44 %  the closest class with the fuzzy c-means technique.
     45 %
     46 %  The fuzzy c-Means algorithm can be summarized as follows:
     47 %
     48 %    o Build a histogram, one for each color component of the image.
     49 %
     50 %    o For each histogram, successively apply the scale-space filter and
     51 %      build an interval tree of zero crossings in the second derivative
     52 %      at each scale.  Analyze this scale-space ''fingerprint'' to
     53 %      determine which peaks and valleys in the histogram are most
     54 %      predominant.
     55 %
     56 %    o The fingerprint defines intervals on the axis of the histogram.
     57 %      Each interval contains either a minima or a maxima in the original
     58 %      signal.  If each color component lies within the maxima interval,
     59 %      that pixel is considered ''classified'' and is assigned an unique
     60 %      class number.
     61 %
     62 %    o Any pixel that fails to be classified in the above thresholding
     63 %      pass is classified using the fuzzy c-Means technique.  It is
     64 %      assigned to one of the classes discovered in the histogram analysis
     65 %      phase.
     66 %
     67 %  The fuzzy c-Means technique attempts to cluster a pixel by finding
     68 %  the local minima of the generalized within group sum of squared error
     69 %  objective function.  A pixel is assigned to the closest class of
     70 %  which the fuzzy membership has a maximum value.
     71 %
     72 %  Segment is strongly based on software written by Andy Gallo,
     73 %  University of Delaware.
     74 %
     75 %  The following reference was used in creating this program:
     76 %
     77 %    Young Won Lim, Sang Uk Lee, "On The Color Image Segmentation
     78 %    Algorithm Based on the Thresholding and the Fuzzy c-Means
     79 %    Techniques", Pattern Recognition, Volume 23, Number 9, pages
     80 %    935-952, 1990.
     81 %
     82 %
     83 */
     84 
     85 #include "MagickCore/studio.h"
     87 #include "MagickCore/cache.h"
     88 #include "MagickCore/color.h"
     89 #include "MagickCore/colormap.h"
     90 #include "MagickCore/colorspace.h"
     91 #include "MagickCore/colorspace-private.h"
     92 #include "MagickCore/exception.h"
     93 #include "MagickCore/exception-private.h"
     94 #include "MagickCore/image.h"
     95 #include "MagickCore/image-private.h"
     96 #include "MagickCore/memory_.h"
     97 #include "MagickCore/monitor.h"
     98 #include "MagickCore/monitor-private.h"
     99 #include "MagickCore/pixel-accessor.h"
    100 #include "MagickCore/pixel-private.h"
    101 #include "MagickCore/quantize.h"
    102 #include "MagickCore/quantum.h"
    103 #include "MagickCore/quantum-private.h"
    104 #include "MagickCore/resource_.h"
    105 #include "MagickCore/segment.h"
    106 #include "MagickCore/string_.h"
    107 #include "MagickCore/thread-private.h"
    108 
    109 /*
    111   Define declarations.
    112 */
    113 #define MaxDimension  3
    114 #define DeltaTau  0.5f
    115 #if defined(FastClassify)
    116 #define WeightingExponent  2.0
    117 #define SegmentPower(ratio) (ratio)
    118 #else
    119 #define WeightingExponent  2.5
    120 #define SegmentPower(ratio) pow(ratio,(double) (1.0/(weighting_exponent-1.0)));
    121 #endif
    122 #define Tau  5.2f
    123 
    124 /*
    126   Typedef declarations.
    127 */
    128 typedef struct _ExtentPacket
    129 {
    130   double
    131     center;
    132 
    133   ssize_t
    134     index,
    135     left,
    136     right;
    137 } ExtentPacket;
    138 
    139 typedef struct _Cluster
    140 {
    141   struct _Cluster
    142     *next;
    143 
    144   ExtentPacket
    145     red,
    146     green,
    147     blue;
    148 
    149   ssize_t
    150     count,
    151     id;
    152 } Cluster;
    153 
    154 typedef struct _IntervalTree
    155 {
    156   double
    157     tau;
    158 
    159   ssize_t
    160     left,
    161     right;
    162 
    163   double
    164     mean_stability,
    165     stability;
    166 
    167   struct _IntervalTree
    168     *sibling,
    169     *child;
    170 } IntervalTree;
    171 
    172 typedef struct _ZeroCrossing
    173 {
    174   double
    175     tau,
    176     histogram[256];
    177 
    178   short
    179     crossings[256];
    180 } ZeroCrossing;
    181 
    182 /*
    184   Constant declarations.
    185 */
    186 static const int
    187   Blue = 2,
    188   Green = 1,
    189   Red = 0,
    190   SafeMargin = 3,
    191   TreeLength = 600;
    192 
    193 /*
    195   Method prototypes.
    196 */
    197 static double
    198   OptimalTau(const ssize_t *,const double,const double,const double,
    199     const double,short *);
    200 
    201 static ssize_t
    202   DefineRegion(const short *,ExtentPacket *);
    203 
    204 static void
    205   InitializeHistogram(const Image *,ssize_t **,ExceptionInfo *),
    206   ScaleSpace(const ssize_t *,const double,double *),
    207   ZeroCrossHistogram(double *,const double,short *);
    208 
    209 /*
    211 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    212 %                                                                             %
    213 %                                                                             %
    214 %                                                                             %
    215 +   C l a s s i f y                                                           %
    216 %                                                                             %
    217 %                                                                             %
    218 %                                                                             %
    219 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    220 %
    221 %  Classify() defines one or more classes.  Each pixel is thresholded to
    222 %  determine which class it belongs to.  If the class is not identified it is
    223 %  assigned to the closest class based on the fuzzy c-Means technique.
    224 %
    225 %  The format of the Classify method is:
    226 %
    227 %      MagickBooleanType Classify(Image *image,short **extrema,
    228 %        const double cluster_threshold,
    229 %        const double weighting_exponent,
    230 %        const MagickBooleanType verbose,ExceptionInfo *exception)
    231 %
    232 %  A description of each parameter follows.
    233 %
    234 %    o image: the image.
    235 %
    236 %    o extrema:  Specifies a pointer to an array of integers.  They
    237 %      represent the peaks and valleys of the histogram for each color
    238 %      component.
    239 %
    240 %    o cluster_threshold:  This double represents the minimum number of
    241 %      pixels contained in a hexahedra before it can be considered valid
    242 %      (expressed as a percentage).
    243 %
    244 %    o weighting_exponent: Specifies the membership weighting exponent.
    245 %
    246 %    o verbose:  A value greater than zero prints detailed information about
    247 %      the identified classes.
    248 %
    249 %    o exception: return any errors or warnings in this structure.
    250 %
    251 */
    252 static MagickBooleanType Classify(Image *image,short **extrema,
    253   const double cluster_threshold,
    254   const double weighting_exponent,const MagickBooleanType verbose,
    255   ExceptionInfo *exception)
    256 {
    257 #define SegmentImageTag  "Segment/Image"
    258 
    259   CacheView
    260     *image_view;
    261 
    262   Cluster
    263     *cluster,
    264     *head,
    265     *last_cluster,
    266     *next_cluster;
    267 
    268   ExtentPacket
    269     blue,
    270     green,
    271     red;
    272 
    273   MagickOffsetType
    274     progress;
    275 
    276   double
    277     *free_squares;
    278 
    279   MagickStatusType
    280     status;
    281 
    282   register ssize_t
    283     i;
    284 
    285   register double
    286     *squares;
    287 
    288   size_t
    289     number_clusters;
    290 
    291   ssize_t
    292     count,
    293     y;
    294 
    295   /*
    296     Form clusters.
    297   */
    298   cluster=(Cluster *) NULL;
    299   head=(Cluster *) NULL;
    300   (void) ResetMagickMemory(&red,0,sizeof(red));
    301   (void) ResetMagickMemory(&green,0,sizeof(green));
    302   (void) ResetMagickMemory(&blue,0,sizeof(blue));
    303   while (DefineRegion(extrema[Red],&red) != 0)
    304   {
    305     green.index=0;
    306     while (DefineRegion(extrema[Green],&green) != 0)
    307     {
    308       blue.index=0;
    309       while (DefineRegion(extrema[Blue],&blue) != 0)
    310       {
    311         /*
    312           Allocate a new class.
    313         */
    314         if (head != (Cluster *) NULL)
    315           {
    316             cluster->next=(Cluster *) AcquireMagickMemory(
    317               sizeof(*cluster->next));
    318             cluster=cluster->next;
    319           }
    320         else
    321           {
    322             cluster=(Cluster *) AcquireMagickMemory(sizeof(*cluster));
    323             head=cluster;
    324           }
    325         if (cluster == (Cluster *) NULL)
    326           ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
    327             image->filename);
    328         /*
    329           Initialize a new class.
    330         */
    331         cluster->count=0;
    332         cluster->red=red;
    333         cluster->green=green;
    334         cluster->blue=blue;
    335         cluster->next=(Cluster *) NULL;
    336       }
    337     }
    338   }
    339   if (head == (Cluster *) NULL)
    340     {
    341       /*
    342         No classes were identified-- create one.
    343       */
    344       cluster=(Cluster *) AcquireMagickMemory(sizeof(*cluster));
    345       if (cluster == (Cluster *) NULL)
    346         ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
    347           image->filename);
    348       /*
    349         Initialize a new class.
    350       */
    351       cluster->count=0;
    352       cluster->red=red;
    353       cluster->green=green;
    354       cluster->blue=blue;
    355       cluster->next=(Cluster *) NULL;
    356       head=cluster;
    357     }
    358   /*
    359     Count the pixels for each cluster.
    360   */
    361   status=MagickTrue;
    362   count=0;
    363   progress=0;
    364   image_view=AcquireVirtualCacheView(image,exception);
    365   for (y=0; y < (ssize_t) image->rows; y++)
    366   {
    367     register const Quantum
    368       *p;
    369 
    370     register ssize_t
    371       x;
    372 
    373     p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
    374     if (p == (const Quantum *) NULL)
    375       break;
    376     for (x=0; x < (ssize_t) image->columns; x++)
    377     {
    378       for (cluster=head; cluster != (Cluster *) NULL; cluster=cluster->next)
    379         if (((ssize_t) ScaleQuantumToChar(GetPixelRed(image,p)) >=
    380              (cluster->red.left-SafeMargin)) &&
    381             ((ssize_t) ScaleQuantumToChar(GetPixelRed(image,p)) <=
    382              (cluster->red.right+SafeMargin)) &&
    383             ((ssize_t) ScaleQuantumToChar(GetPixelGreen(image,p)) >=
    384              (cluster->green.left-SafeMargin)) &&
    385             ((ssize_t) ScaleQuantumToChar(GetPixelGreen(image,p)) <=
    386              (cluster->green.right+SafeMargin)) &&
    387             ((ssize_t) ScaleQuantumToChar(GetPixelBlue(image,p)) >=
    388              (cluster->blue.left-SafeMargin)) &&
    389             ((ssize_t) ScaleQuantumToChar(GetPixelBlue(image,p)) <=
    390              (cluster->blue.right+SafeMargin)))
    391           {
    392             /*
    393               Count this pixel.
    394             */
    395             count++;
    396             cluster->red.center+=(double) ScaleQuantumToChar(
    397               GetPixelRed(image,p));
    398             cluster->green.center+=(double) ScaleQuantumToChar(
    399               GetPixelGreen(image,p));
    400             cluster->blue.center+=(double) ScaleQuantumToChar(
    401               GetPixelBlue(image,p));
    402             cluster->count++;
    403             break;
    404           }
    405       p+=GetPixelChannels(image);
    406     }
    407     if (image->progress_monitor != (MagickProgressMonitor) NULL)
    408       {
    409         MagickBooleanType
    410           proceed;
    411 
    412 #if defined(MAGICKCORE_OPENMP_SUPPORT)
    413         #pragma omp critical (MagickCore_Classify)
    414 #endif
    415         proceed=SetImageProgress(image,SegmentImageTag,progress++,2*
    416           image->rows);
    417         if (proceed == MagickFalse)
    418           status=MagickFalse;
    419       }
    420   }
    421   image_view=DestroyCacheView(image_view);
    422   /*
    423     Remove clusters that do not meet minimum cluster threshold.
    424   */
    425   count=0;
    426   last_cluster=head;
    427   next_cluster=head;
    428   for (cluster=head; cluster != (Cluster *) NULL; cluster=next_cluster)
    429   {
    430     next_cluster=cluster->next;
    431     if ((cluster->count > 0) &&
    432         (cluster->count >= (count*cluster_threshold/100.0)))
    433       {
    434         /*
    435           Initialize cluster.
    436         */
    437         cluster->id=count;
    438         cluster->red.center/=cluster->count;
    439         cluster->green.center/=cluster->count;
    440         cluster->blue.center/=cluster->count;
    441         count++;
    442         last_cluster=cluster;
    443         continue;
    444       }
    445     /*
    446       Delete cluster.
    447     */
    448     if (cluster == head)
    449       head=next_cluster;
    450     else
    451       last_cluster->next=next_cluster;
    452     cluster=(Cluster *) RelinquishMagickMemory(cluster);
    453   }
    454   number_clusters=(size_t) count;
    455   if (verbose != MagickFalse)
    456     {
    457       /*
    458         Print cluster statistics.
    459       */
    460       (void) FormatLocaleFile(stdout,"Fuzzy C-means Statistics\n");
    461       (void) FormatLocaleFile(stdout,"===================\n\n");
    462       (void) FormatLocaleFile(stdout,"\tCluster Threshold = %g\n",(double)
    463         cluster_threshold);
    464       (void) FormatLocaleFile(stdout,"\tWeighting Exponent = %g\n",(double)
    465         weighting_exponent);
    466       (void) FormatLocaleFile(stdout,"\tTotal Number of Clusters = %.20g\n\n",
    467         (double) number_clusters);
    468       /*
    469         Print the total number of points per cluster.
    470       */
    471       (void) FormatLocaleFile(stdout,"\n\nNumber of Vectors Per Cluster\n");
    472       (void) FormatLocaleFile(stdout,"=============================\n\n");
    473       for (cluster=head; cluster != (Cluster *) NULL; cluster=cluster->next)
    474         (void) FormatLocaleFile(stdout,"Cluster #%.20g = %.20g\n",(double)
    475           cluster->id,(double) cluster->count);
    476       /*
    477         Print the cluster extents.
    478       */
    479       (void) FormatLocaleFile(stdout,
    480         "\n\n\nCluster Extents:        (Vector Size: %d)\n",MaxDimension);
    481       (void) FormatLocaleFile(stdout,"================");
    482       for (cluster=head; cluster != (Cluster *) NULL; cluster=cluster->next)
    483       {
    484         (void) FormatLocaleFile(stdout,"\n\nCluster #%.20g\n\n",(double)
    485           cluster->id);
    486         (void) FormatLocaleFile(stdout,
    487           "%.20g-%.20g  %.20g-%.20g  %.20g-%.20g\n",(double)
    488           cluster->red.left,(double) cluster->red.right,(double)
    489           cluster->green.left,(double) cluster->green.right,(double)
    490           cluster->blue.left,(double) cluster->blue.right);
    491       }
    492       /*
    493         Print the cluster center values.
    494       */
    495       (void) FormatLocaleFile(stdout,
    496         "\n\n\nCluster Center Values:        (Vector Size: %d)\n",MaxDimension);
    497       (void) FormatLocaleFile(stdout,"=====================");
    498       for (cluster=head; cluster != (Cluster *) NULL; cluster=cluster->next)
    499       {
    500         (void) FormatLocaleFile(stdout,"\n\nCluster #%.20g\n\n",(double)
    501           cluster->id);
    502         (void) FormatLocaleFile(stdout,"%g  %g  %g\n",(double)
    503           cluster->red.center,(double) cluster->green.center,(double)
    504           cluster->blue.center);
    505       }
    506       (void) FormatLocaleFile(stdout,"\n");
    507     }
    508   if (number_clusters > 256)
    509     ThrowBinaryException(ImageError,"TooManyClusters",image->filename);
    510   /*
    511     Speed up distance calculations.
    512   */
    513   squares=(double *) AcquireQuantumMemory(513UL,sizeof(*squares));
    514   if (squares == (double *) NULL)
    515     ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
    516       image->filename);
    517   squares+=255;
    518   for (i=(-255); i <= 255; i++)
    519     squares[i]=(double) i*(double) i;
    520   /*
    521     Allocate image colormap.
    522   */
    523   if (AcquireImageColormap(image,number_clusters,exception) == MagickFalse)
    524     ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
    525       image->filename);
    526   i=0;
    527   for (cluster=head; cluster != (Cluster *) NULL; cluster=cluster->next)
    528   {
    529     image->colormap[i].red=(double) ScaleCharToQuantum((unsigned char)
    530       (cluster->red.center+0.5));
    531     image->colormap[i].green=(double) ScaleCharToQuantum((unsigned char)
    532       (cluster->green.center+0.5));
    533     image->colormap[i].blue=(double) ScaleCharToQuantum((unsigned char)
    534       (cluster->blue.center+0.5));
    535     i++;
    536   }
    537   /*
    538     Do course grain classes.
    539   */
    540   image_view=AcquireAuthenticCacheView(image,exception);
    541 #if defined(MAGICKCORE_OPENMP_SUPPORT)
    542   #pragma omp parallel for schedule(static,4) shared(progress,status) \
    543     magick_threads(image,image,image->rows,1)
    544 #endif
    545   for (y=0; y < (ssize_t) image->rows; y++)
    546   {
    547     Cluster
    548       *cluster;
    549 
    550     register const PixelInfo
    551       *magick_restrict p;
    552 
    553     register ssize_t
    554       x;
    555 
    556     register Quantum
    557       *magick_restrict q;
    558 
    559     if (status == MagickFalse)
    560       continue;
    561     q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
    562     if (q == (Quantum *) NULL)
    563       {
    564         status=MagickFalse;
    565         continue;
    566       }
    567     for (x=0; x < (ssize_t) image->columns; x++)
    568     {
    569       SetPixelIndex(image,0,q);
    570       for (cluster=head; cluster != (Cluster *) NULL; cluster=cluster->next)
    571       {
    572         if (((ssize_t) ScaleQuantumToChar(GetPixelRed(image,q)) >=
    573              (cluster->red.left-SafeMargin)) &&
    574             ((ssize_t) ScaleQuantumToChar(GetPixelRed(image,q)) <=
    575              (cluster->red.right+SafeMargin)) &&
    576             ((ssize_t) ScaleQuantumToChar(GetPixelGreen(image,q)) >=
    577              (cluster->green.left-SafeMargin)) &&
    578             ((ssize_t) ScaleQuantumToChar(GetPixelGreen(image,q)) <=
    579              (cluster->green.right+SafeMargin)) &&
    580             ((ssize_t) ScaleQuantumToChar(GetPixelBlue(image,q)) >=
    581              (cluster->blue.left-SafeMargin)) &&
    582             ((ssize_t) ScaleQuantumToChar(GetPixelBlue(image,q)) <=
    583              (cluster->blue.right+SafeMargin)))
    584           {
    585             /*
    586               Classify this pixel.
    587             */
    588             SetPixelIndex(image,(Quantum) cluster->id,q);
    589             break;
    590           }
    591       }
    592       if (cluster == (Cluster *) NULL)
    593         {
    594           double
    595             distance_squared,
    596             local_minima,
    597             numerator,
    598             ratio,
    599             sum;
    600 
    601           register ssize_t
    602             j,
    603             k;
    604 
    605           /*
    606             Compute fuzzy membership.
    607           */
    608           local_minima=0.0;
    609           for (j=0; j < (ssize_t) image->colors; j++)
    610           {
    611             sum=0.0;
    612             p=image->colormap+j;
    613             distance_squared=squares[(ssize_t) ScaleQuantumToChar(
    614               GetPixelRed(image,q))-(ssize_t)
    615               ScaleQuantumToChar(ClampToQuantum(p->red))]+squares[(ssize_t)
    616               ScaleQuantumToChar(GetPixelGreen(image,q))-(ssize_t)
    617               ScaleQuantumToChar(ClampToQuantum(p->green))]+squares[(ssize_t)
    618               ScaleQuantumToChar(GetPixelBlue(image,q))-(ssize_t)
    619               ScaleQuantumToChar(ClampToQuantum(p->blue))];
    620             numerator=distance_squared;
    621             for (k=0; k < (ssize_t) image->colors; k++)
    622             {
    623               p=image->colormap+k;
    624                 distance_squared=squares[(ssize_t) ScaleQuantumToChar(
    625                   GetPixelRed(image,q))-(ssize_t)
    626                   ScaleQuantumToChar(ClampToQuantum(p->red))]+squares[
    627                   (ssize_t) ScaleQuantumToChar(GetPixelGreen(image,q))-(ssize_t)
    628                   ScaleQuantumToChar(ClampToQuantum(p->green))]+squares[
    629                   (ssize_t) ScaleQuantumToChar(GetPixelBlue(image,q))-(ssize_t)
    630                   ScaleQuantumToChar(ClampToQuantum(p->blue))];
    631               ratio=numerator/distance_squared;
    632               sum+=SegmentPower(ratio);
    633             }
    634             if ((sum != 0.0) && ((1.0/sum) > local_minima))
    635               {
    636                 /*
    637                   Classify this pixel.
    638                 */
    639                 local_minima=1.0/sum;
    640                 SetPixelIndex(image,(Quantum) j,q);
    641               }
    642           }
    643         }
    644       q+=GetPixelChannels(image);
    645     }
    646     if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
    647       status=MagickFalse;
    648     if (image->progress_monitor != (MagickProgressMonitor) NULL)
    649       {
    650         MagickBooleanType
    651           proceed;
    652 
    653 #if defined(MAGICKCORE_OPENMP_SUPPORT)
    654         #pragma omp critical (MagickCore_Classify)
    655 #endif
    656         proceed=SetImageProgress(image,SegmentImageTag,progress++,
    657           2*image->rows);
    658         if (proceed == MagickFalse)
    659           status=MagickFalse;
    660       }
    661   }
    662   image_view=DestroyCacheView(image_view);
    663   status&=SyncImage(image,exception);
    664   /*
    665     Relinquish resources.
    666   */
    667   for (cluster=head; cluster != (Cluster *) NULL; cluster=next_cluster)
    668   {
    669     next_cluster=cluster->next;
    670     cluster=(Cluster *) RelinquishMagickMemory(cluster);
    671   }
    672   squares-=255;
    673   free_squares=squares;
    674   free_squares=(double *) RelinquishMagickMemory(free_squares);
    675   return(MagickTrue);
    676 }
    677 
    678 /*
    680 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    681 %                                                                             %
    682 %                                                                             %
    683 %                                                                             %
    684 +   C o n s o l i d a t e C r o s s i n g s                                   %
    685 %                                                                             %
    686 %                                                                             %
    687 %                                                                             %
    688 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    689 %
    690 %  ConsolidateCrossings() guarantees that an even number of zero crossings
    691 %  always lie between two crossings.
    692 %
    693 %  The format of the ConsolidateCrossings method is:
    694 %
    695 %      ConsolidateCrossings(ZeroCrossing *zero_crossing,
    696 %        const size_t number_crossings)
    697 %
    698 %  A description of each parameter follows.
    699 %
    700 %    o zero_crossing: Specifies an array of structures of type ZeroCrossing.
    701 %
    702 %    o number_crossings: This size_t specifies the number of elements
    703 %      in the zero_crossing array.
    704 %
    705 */
    706 static void ConsolidateCrossings(ZeroCrossing *zero_crossing,
    707   const size_t number_crossings)
    708 {
    709   register ssize_t
    710     i,
    711     j,
    712     k,
    713     l;
    714 
    715   ssize_t
    716     center,
    717     correct,
    718     count,
    719     left,
    720     right;
    721 
    722   /*
    723     Consolidate zero crossings.
    724   */
    725   for (i=(ssize_t) number_crossings-1; i >= 0; i--)
    726     for (j=0; j <= 255; j++)
    727     {
    728       if (zero_crossing[i].crossings[j] == 0)
    729         continue;
    730       /*
    731         Find the entry that is closest to j and still preserves the
    732         property that there are an even number of crossings between
    733         intervals.
    734       */
    735       for (k=j-1; k > 0; k--)
    736         if (zero_crossing[i+1].crossings[k] != 0)
    737           break;
    738       left=MagickMax(k,0);
    739       center=j;
    740       for (k=j+1; k < 255; k++)
    741         if (zero_crossing[i+1].crossings[k] != 0)
    742           break;
    743       right=MagickMin(k,255);
    744       /*
    745         K is the zero crossing just left of j.
    746       */
    747       for (k=j-1; k > 0; k--)
    748         if (zero_crossing[i].crossings[k] != 0)
    749           break;
    750       if (k < 0)
    751         k=0;
    752       /*
    753         Check center for an even number of crossings between k and j.
    754       */
    755       correct=(-1);
    756       if (zero_crossing[i+1].crossings[j] != 0)
    757         {
    758           count=0;
    759           for (l=k+1; l < center; l++)
    760             if (zero_crossing[i+1].crossings[l] != 0)
    761               count++;
    762           if (((count % 2) == 0) && (center != k))
    763             correct=center;
    764         }
    765       /*
    766         Check left for an even number of crossings between k and j.
    767       */
    768       if (correct == -1)
    769         {
    770           count=0;
    771           for (l=k+1; l < left; l++)
    772             if (zero_crossing[i+1].crossings[l] != 0)
    773               count++;
    774           if (((count % 2) == 0) && (left != k))
    775             correct=left;
    776         }
    777       /*
    778         Check right for an even number of crossings between k and j.
    779       */
    780       if (correct == -1)
    781         {
    782           count=0;
    783           for (l=k+1; l < right; l++)
    784             if (zero_crossing[i+1].crossings[l] != 0)
    785               count++;
    786           if (((count % 2) == 0) && (right != k))
    787             correct=right;
    788         }
    789       l=(ssize_t) zero_crossing[i].crossings[j];
    790       zero_crossing[i].crossings[j]=0;
    791       if (correct != -1)
    792         zero_crossing[i].crossings[correct]=(short) l;
    793     }
    794 }
    795 
    796 /*
    798 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    799 %                                                                             %
    800 %                                                                             %
    801 %                                                                             %
    802 +   D e f i n e R e g i o n                                                   %
    803 %                                                                             %
    804 %                                                                             %
    805 %                                                                             %
    806 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    807 %
    808 %  DefineRegion() defines the left and right boundaries of a peak region.
    809 %
    810 %  The format of the DefineRegion method is:
    811 %
    812 %      ssize_t DefineRegion(const short *extrema,ExtentPacket *extents)
    813 %
    814 %  A description of each parameter follows.
    815 %
    816 %    o extrema:  Specifies a pointer to an array of integers.  They
    817 %      represent the peaks and valleys of the histogram for each color
    818 %      component.
    819 %
    820 %    o extents:  This pointer to an ExtentPacket represent the extends
    821 %      of a particular peak or valley of a color component.
    822 %
    823 */
    824 static ssize_t DefineRegion(const short *extrema,ExtentPacket *extents)
    825 {
    826   /*
    827     Initialize to default values.
    828   */
    829   extents->left=0;
    830   extents->center=0.0;
    831   extents->right=255;
    832   /*
    833     Find the left side (maxima).
    834   */
    835   for ( ; extents->index <= 255; extents->index++)
    836     if (extrema[extents->index] > 0)
    837       break;
    838   if (extents->index > 255)
    839     return(MagickFalse);  /* no left side - no region exists */
    840   extents->left=extents->index;
    841   /*
    842     Find the right side (minima).
    843   */
    844   for ( ; extents->index <= 255; extents->index++)
    845     if (extrema[extents->index] < 0)
    846       break;
    847   extents->right=extents->index-1;
    848   return(MagickTrue);
    849 }
    850 
    851 /*
    853 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    854 %                                                                             %
    855 %                                                                             %
    856 %                                                                             %
    857 +   D e r i v a t i v e H i s t o g r a m                                     %
    858 %                                                                             %
    859 %                                                                             %
    860 %                                                                             %
    861 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    862 %
    863 %  DerivativeHistogram() determines the derivative of the histogram using
    864 %  central differencing.
    865 %
    866 %  The format of the DerivativeHistogram method is:
    867 %
    868 %      DerivativeHistogram(const double *histogram,
    869 %        double *derivative)
    870 %
    871 %  A description of each parameter follows.
    872 %
    873 %    o histogram: Specifies an array of doubles representing the number
    874 %      of pixels for each intensity of a particular color component.
    875 %
    876 %    o derivative: This array of doubles is initialized by
    877 %      DerivativeHistogram to the derivative of the histogram using central
    878 %      differencing.
    879 %
    880 */
    881 static void DerivativeHistogram(const double *histogram,
    882   double *derivative)
    883 {
    884   register ssize_t
    885     i,
    886     n;
    887 
    888   /*
    889     Compute endpoints using second order polynomial interpolation.
    890   */
    891   n=255;
    892   derivative[0]=(-1.5*histogram[0]+2.0*histogram[1]-0.5*histogram[2]);
    893   derivative[n]=(0.5*histogram[n-2]-2.0*histogram[n-1]+1.5*histogram[n]);
    894   /*
    895     Compute derivative using central differencing.
    896   */
    897   for (i=1; i < n; i++)
    898     derivative[i]=(histogram[i+1]-histogram[i-1])/2.0;
    899   return;
    900 }
    901 
    902 /*
    904 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    905 %                                                                             %
    906 %                                                                             %
    907 %                                                                             %
    908 +  G e t I m a g e D y n a m i c T h r e s h o l d                            %
    909 %                                                                             %
    910 %                                                                             %
    911 %                                                                             %
    912 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    913 %
    914 %  GetImageDynamicThreshold() returns the dynamic threshold for an image.
    915 %
    916 %  The format of the GetImageDynamicThreshold method is:
    917 %
    918 %      MagickBooleanType GetImageDynamicThreshold(const Image *image,
    919 %        const double cluster_threshold,const double smooth_threshold,
    920 %        PixelInfo *pixel,ExceptionInfo *exception)
    921 %
    922 %  A description of each parameter follows.
    923 %
    924 %    o image: the image.
    925 %
    926 %    o cluster_threshold:  This double represents the minimum number of
    927 %      pixels contained in a hexahedra before it can be considered valid
    928 %      (expressed as a percentage).
    929 %
    930 %    o smooth_threshold: the smoothing threshold eliminates noise in the second
    931 %      derivative of the histogram.  As the value is increased, you can expect a
    932 %      smoother second derivative.
    933 %
    934 %    o pixel: return the dynamic threshold here.
    935 %
    936 %    o exception: return any errors or warnings in this structure.
    937 %
    938 */
    939 MagickExport MagickBooleanType GetImageDynamicThreshold(const Image *image,
    940   const double cluster_threshold,const double smooth_threshold,
    941   PixelInfo *pixel,ExceptionInfo *exception)
    942 {
    943   Cluster
    944     *background,
    945     *cluster,
    946     *object,
    947     *head,
    948     *last_cluster,
    949     *next_cluster;
    950 
    951   ExtentPacket
    952     blue,
    953     green,
    954     red;
    955 
    956   MagickBooleanType
    957     proceed;
    958 
    959   double
    960     threshold;
    961 
    962   register const Quantum
    963     *p;
    964 
    965   register ssize_t
    966     i,
    967     x;
    968 
    969   short
    970     *extrema[MaxDimension];
    971 
    972   ssize_t
    973     count,
    974     *histogram[MaxDimension],
    975     y;
    976 
    977   /*
    978     Allocate histogram and extrema.
    979   */
    980   assert(image != (Image *) NULL);
    981   assert(image->signature == MagickCoreSignature);
    982   if (image->debug != MagickFalse)
    983     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
    984   GetPixelInfo(image,pixel);
    985   for (i=0; i < MaxDimension; i++)
    986   {
    987     histogram[i]=(ssize_t *) AcquireQuantumMemory(256UL,sizeof(**histogram));
    988     extrema[i]=(short *) AcquireQuantumMemory(256UL,sizeof(**histogram));
    989     if ((histogram[i] == (ssize_t *) NULL) || (extrema[i] == (short *) NULL))
    990       {
    991         for (i-- ; i >= 0; i--)
    992         {
    993           extrema[i]=(short *) RelinquishMagickMemory(extrema[i]);
    994           histogram[i]=(ssize_t *) RelinquishMagickMemory(histogram[i]);
    995         }
    996         (void) ThrowMagickException(exception,GetMagickModule(),
    997           ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
    998         return(MagickFalse);
    999       }
   1000   }
   1001   /*
   1002     Initialize histogram.
   1003   */
   1004   InitializeHistogram(image,histogram,exception);
   1005   (void) OptimalTau(histogram[Red],Tau,0.2f,DeltaTau,
   1006     (smooth_threshold == 0.0f ? 1.0f : smooth_threshold),extrema[Red]);
   1007   (void) OptimalTau(histogram[Green],Tau,0.2f,DeltaTau,
   1008     (smooth_threshold == 0.0f ? 1.0f : smooth_threshold),extrema[Green]);
   1009   (void) OptimalTau(histogram[Blue],Tau,0.2f,DeltaTau,
   1010     (smooth_threshold == 0.0f ? 1.0f : smooth_threshold),extrema[Blue]);
   1011   /*
   1012     Form clusters.
   1013   */
   1014   cluster=(Cluster *) NULL;
   1015   head=(Cluster *) NULL;
   1016   (void) ResetMagickMemory(&red,0,sizeof(red));
   1017   (void) ResetMagickMemory(&green,0,sizeof(green));
   1018   (void) ResetMagickMemory(&blue,0,sizeof(blue));
   1019   while (DefineRegion(extrema[Red],&red) != 0)
   1020   {
   1021     green.index=0;
   1022     while (DefineRegion(extrema[Green],&green) != 0)
   1023     {
   1024       blue.index=0;
   1025       while (DefineRegion(extrema[Blue],&blue) != 0)
   1026       {
   1027         /*
   1028           Allocate a new class.
   1029         */
   1030         if (head != (Cluster *) NULL)
   1031           {
   1032             cluster->next=(Cluster *) AcquireMagickMemory(
   1033               sizeof(*cluster->next));
   1034             cluster=cluster->next;
   1035           }
   1036         else
   1037           {
   1038             cluster=(Cluster *) AcquireMagickMemory(sizeof(*cluster));
   1039             head=cluster;
   1040           }
   1041         if (cluster == (Cluster *) NULL)
   1042           {
   1043             (void) ThrowMagickException(exception,GetMagickModule(),
   1044               ResourceLimitError,"MemoryAllocationFailed","`%s'",
   1045               image->filename);
   1046             return(MagickFalse);
   1047           }
   1048         /*
   1049           Initialize a new class.
   1050         */
   1051         cluster->count=0;
   1052         cluster->red=red;
   1053         cluster->green=green;
   1054         cluster->blue=blue;
   1055         cluster->next=(Cluster *) NULL;
   1056       }
   1057     }
   1058   }
   1059   if (head == (Cluster *) NULL)
   1060     {
   1061       /*
   1062         No classes were identified-- create one.
   1063       */
   1064       cluster=(Cluster *) AcquireMagickMemory(sizeof(*cluster));
   1065       if (cluster == (Cluster *) NULL)
   1066         {
   1067           (void) ThrowMagickException(exception,GetMagickModule(),
   1068             ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
   1069           return(MagickFalse);
   1070         }
   1071       /*
   1072         Initialize a new class.
   1073       */
   1074       cluster->count=0;
   1075       cluster->red=red;
   1076       cluster->green=green;
   1077       cluster->blue=blue;
   1078       cluster->next=(Cluster *) NULL;
   1079       head=cluster;
   1080     }
   1081   /*
   1082     Count the pixels for each cluster.
   1083   */
   1084   count=0;
   1085   for (y=0; y < (ssize_t) image->rows; y++)
   1086   {
   1087     p=GetVirtualPixels(image,0,y,image->columns,1,exception);
   1088     if (p == (const Quantum *) NULL)
   1089       break;
   1090     for (x=0; x < (ssize_t) image->columns; x++)
   1091     {
   1092       for (cluster=head; cluster != (Cluster *) NULL; cluster=cluster->next)
   1093         if (((ssize_t) ScaleQuantumToChar(GetPixelRed(image,p)) >=
   1094              (cluster->red.left-SafeMargin)) &&
   1095             ((ssize_t) ScaleQuantumToChar(GetPixelRed(image,p)) <=
   1096              (cluster->red.right+SafeMargin)) &&
   1097             ((ssize_t) ScaleQuantumToChar(GetPixelGreen(image,p)) >=
   1098              (cluster->green.left-SafeMargin)) &&
   1099             ((ssize_t) ScaleQuantumToChar(GetPixelGreen(image,p)) <=
   1100              (cluster->green.right+SafeMargin)) &&
   1101             ((ssize_t) ScaleQuantumToChar(GetPixelBlue(image,p)) >=
   1102              (cluster->blue.left-SafeMargin)) &&
   1103             ((ssize_t) ScaleQuantumToChar(GetPixelBlue(image,p)) <=
   1104              (cluster->blue.right+SafeMargin)))
   1105           {
   1106             /*
   1107               Count this pixel.
   1108             */
   1109             count++;
   1110             cluster->red.center+=(double) ScaleQuantumToChar(
   1111               GetPixelRed(image,p));
   1112             cluster->green.center+=(double) ScaleQuantumToChar(
   1113               GetPixelGreen(image,p));
   1114             cluster->blue.center+=(double) ScaleQuantumToChar(
   1115               GetPixelBlue(image,p));
   1116             cluster->count++;
   1117             break;
   1118           }
   1119       p+=GetPixelChannels(image);
   1120     }
   1121     proceed=SetImageProgress(image,SegmentImageTag,(MagickOffsetType) y,
   1122       2*image->rows);
   1123     if (proceed == MagickFalse)
   1124       break;
   1125   }
   1126   /*
   1127     Remove clusters that do not meet minimum cluster threshold.
   1128   */
   1129   count=0;
   1130   last_cluster=head;
   1131   next_cluster=head;
   1132   for (cluster=head; cluster != (Cluster *) NULL; cluster=next_cluster)
   1133   {
   1134     next_cluster=cluster->next;
   1135     if ((cluster->count > 0) &&
   1136         (cluster->count >= (count*cluster_threshold/100.0)))
   1137       {
   1138         /*
   1139           Initialize cluster.
   1140         */
   1141         cluster->id=count;
   1142         cluster->red.center/=cluster->count;
   1143         cluster->green.center/=cluster->count;
   1144         cluster->blue.center/=cluster->count;
   1145         count++;
   1146         last_cluster=cluster;
   1147         continue;
   1148       }
   1149     /*
   1150       Delete cluster.
   1151     */
   1152     if (cluster == head)
   1153       head=next_cluster;
   1154     else
   1155       last_cluster->next=next_cluster;
   1156     cluster=(Cluster *) RelinquishMagickMemory(cluster);
   1157   }
   1158   object=head;
   1159   background=head;
   1160   if (count > 1)
   1161     {
   1162       object=head->next;
   1163       for (cluster=object; cluster->next != (Cluster *) NULL; )
   1164       {
   1165         if (cluster->count < object->count)
   1166           object=cluster;
   1167         cluster=cluster->next;
   1168       }
   1169       background=head->next;
   1170       for (cluster=background; cluster->next != (Cluster *) NULL; )
   1171       {
   1172         if (cluster->count > background->count)
   1173           background=cluster;
   1174         cluster=cluster->next;
   1175       }
   1176     }
   1177   if (background != (Cluster *) NULL)
   1178     {
   1179       threshold=(background->red.center+object->red.center)/2.0;
   1180       pixel->red=(double) ScaleCharToQuantum((unsigned char)
   1181         (threshold+0.5));
   1182       threshold=(background->green.center+object->green.center)/2.0;
   1183       pixel->green=(double) ScaleCharToQuantum((unsigned char)
   1184         (threshold+0.5));
   1185       threshold=(background->blue.center+object->blue.center)/2.0;
   1186       pixel->blue=(double) ScaleCharToQuantum((unsigned char)
   1187         (threshold+0.5));
   1188     }
   1189   /*
   1190     Relinquish resources.
   1191   */
   1192   for (cluster=head; cluster != (Cluster *) NULL; cluster=next_cluster)
   1193   {
   1194     next_cluster=cluster->next;
   1195     cluster=(Cluster *) RelinquishMagickMemory(cluster);
   1196   }
   1197   for (i=0; i < MaxDimension; i++)
   1198   {
   1199     extrema[i]=(short *) RelinquishMagickMemory(extrema[i]);
   1200     histogram[i]=(ssize_t *) RelinquishMagickMemory(histogram[i]);
   1201   }
   1202   return(MagickTrue);
   1203 }
   1204 
   1205 /*
   1207 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1208 %                                                                             %
   1209 %                                                                             %
   1210 %                                                                             %
   1211 +  I n i t i a l i z e H i s t o g r a m                                      %
   1212 %                                                                             %
   1213 %                                                                             %
   1214 %                                                                             %
   1215 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1216 %
   1217 %  InitializeHistogram() computes the histogram for an image.
   1218 %
   1219 %  The format of the InitializeHistogram method is:
   1220 %
   1221 %      InitializeHistogram(const Image *image,ssize_t **histogram)
   1222 %
   1223 %  A description of each parameter follows.
   1224 %
   1225 %    o image: Specifies a pointer to an Image structure;  returned from
   1226 %      ReadImage.
   1227 %
   1228 %    o histogram: Specifies an array of integers representing the number
   1229 %      of pixels for each intensity of a particular color component.
   1230 %
   1231 */
   1232 static void InitializeHistogram(const Image *image,ssize_t **histogram,
   1233   ExceptionInfo *exception)
   1234 {
   1235   register const Quantum
   1236     *p;
   1237 
   1238   register ssize_t
   1239     i,
   1240     x;
   1241 
   1242   ssize_t
   1243     y;
   1244 
   1245   /*
   1246     Initialize histogram.
   1247   */
   1248   for (i=0; i <= 255; i++)
   1249   {
   1250     histogram[Red][i]=0;
   1251     histogram[Green][i]=0;
   1252     histogram[Blue][i]=0;
   1253   }
   1254   for (y=0; y < (ssize_t) image->rows; y++)
   1255   {
   1256     p=GetVirtualPixels(image,0,y,image->columns,1,exception);
   1257     if (p == (const Quantum *) NULL)
   1258       break;
   1259     for (x=0; x < (ssize_t) image->columns; x++)
   1260     {
   1261       histogram[Red][(ssize_t) ScaleQuantumToChar(GetPixelRed(image,p))]++;
   1262       histogram[Green][(ssize_t) ScaleQuantumToChar(GetPixelGreen(image,p))]++;
   1263       histogram[Blue][(ssize_t) ScaleQuantumToChar(GetPixelBlue(image,p))]++;
   1264       p+=GetPixelChannels(image);
   1265     }
   1266   }
   1267 }
   1268 
   1269 /*
   1271 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1272 %                                                                             %
   1273 %                                                                             %
   1274 %                                                                             %
   1275 +   I n i t i a l i z e I n t e r v a l T r e e                               %
   1276 %                                                                             %
   1277 %                                                                             %
   1278 %                                                                             %
   1279 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1280 %
   1281 %  InitializeIntervalTree() initializes an interval tree from the lists of
   1282 %  zero crossings.
   1283 %
   1284 %  The format of the InitializeIntervalTree method is:
   1285 %
   1286 %      InitializeIntervalTree(IntervalTree **list,ssize_t *number_nodes,
   1287 %        IntervalTree *node)
   1288 %
   1289 %  A description of each parameter follows.
   1290 %
   1291 %    o zero_crossing: Specifies an array of structures of type ZeroCrossing.
   1292 %
   1293 %    o number_crossings: This size_t specifies the number of elements
   1294 %      in the zero_crossing array.
   1295 %
   1296 */
   1297 
   1298 static void InitializeList(IntervalTree **list,ssize_t *number_nodes,
   1299   IntervalTree *node)
   1300 {
   1301   if (node == (IntervalTree *) NULL)
   1302     return;
   1303   if (node->child == (IntervalTree *) NULL)
   1304     list[(*number_nodes)++]=node;
   1305   InitializeList(list,number_nodes,node->sibling);
   1306   InitializeList(list,number_nodes,node->child);
   1307 }
   1308 
   1309 static void MeanStability(IntervalTree *node)
   1310 {
   1311   register IntervalTree
   1312     *child;
   1313 
   1314   if (node == (IntervalTree *) NULL)
   1315     return;
   1316   node->mean_stability=0.0;
   1317   child=node->child;
   1318   if (child != (IntervalTree *) NULL)
   1319     {
   1320       register ssize_t
   1321         count;
   1322 
   1323       register double
   1324         sum;
   1325 
   1326       sum=0.0;
   1327       count=0;
   1328       for ( ; child != (IntervalTree *) NULL; child=child->sibling)
   1329       {
   1330         sum+=child->stability;
   1331         count++;
   1332       }
   1333       node->mean_stability=sum/(double) count;
   1334     }
   1335   MeanStability(node->sibling);
   1336   MeanStability(node->child);
   1337 }
   1338 
   1339 static void Stability(IntervalTree *node)
   1340 {
   1341   if (node == (IntervalTree *) NULL)
   1342     return;
   1343   if (node->child == (IntervalTree *) NULL)
   1344     node->stability=0.0;
   1345   else
   1346     node->stability=node->tau-(node->child)->tau;
   1347   Stability(node->sibling);
   1348   Stability(node->child);
   1349 }
   1350 
   1351 static IntervalTree *InitializeIntervalTree(const ZeroCrossing *zero_crossing,
   1352   const size_t number_crossings)
   1353 {
   1354   IntervalTree
   1355     *head,
   1356     **list,
   1357     *node,
   1358     *root;
   1359 
   1360   register ssize_t
   1361     i;
   1362 
   1363   ssize_t
   1364     j,
   1365     k,
   1366     left,
   1367     number_nodes;
   1368 
   1369   /*
   1370     Allocate interval tree.
   1371   */
   1372   list=(IntervalTree **) AcquireQuantumMemory((size_t) TreeLength,
   1373     sizeof(*list));
   1374   if (list == (IntervalTree **) NULL)
   1375     return((IntervalTree *) NULL);
   1376   /*
   1377     The root is the entire histogram.
   1378   */
   1379   root=(IntervalTree *) AcquireMagickMemory(sizeof(*root));
   1380   root->child=(IntervalTree *) NULL;
   1381   root->sibling=(IntervalTree *) NULL;
   1382   root->tau=0.0;
   1383   root->left=0;
   1384   root->right=255;
   1385   for (i=(-1); i < (ssize_t) number_crossings; i++)
   1386   {
   1387     /*
   1388       Initialize list with all nodes with no children.
   1389     */
   1390     number_nodes=0;
   1391     InitializeList(list,&number_nodes,root);
   1392     /*
   1393       Split list.
   1394     */
   1395     for (j=0; j < number_nodes; j++)
   1396     {
   1397       head=list[j];
   1398       left=head->left;
   1399       node=head;
   1400       for (k=head->left+1; k < head->right; k++)
   1401       {
   1402         if (zero_crossing[i+1].crossings[k] != 0)
   1403           {
   1404             if (node == head)
   1405               {
   1406                 node->child=(IntervalTree *) AcquireMagickMemory(
   1407                   sizeof(*node->child));
   1408                 node=node->child;
   1409               }
   1410             else
   1411               {
   1412                 node->sibling=(IntervalTree *) AcquireMagickMemory(
   1413                   sizeof(*node->sibling));
   1414                 node=node->sibling;
   1415               }
   1416             node->tau=zero_crossing[i+1].tau;
   1417             node->child=(IntervalTree *) NULL;
   1418             node->sibling=(IntervalTree *) NULL;
   1419             node->left=left;
   1420             node->right=k;
   1421             left=k;
   1422           }
   1423         }
   1424       if (left != head->left)
   1425         {
   1426           node->sibling=(IntervalTree *) AcquireMagickMemory(
   1427             sizeof(*node->sibling));
   1428           node=node->sibling;
   1429           node->tau=zero_crossing[i+1].tau;
   1430           node->child=(IntervalTree *) NULL;
   1431           node->sibling=(IntervalTree *) NULL;
   1432           node->left=left;
   1433           node->right=head->right;
   1434         }
   1435     }
   1436   }
   1437   /*
   1438     Determine the stability: difference between a nodes tau and its child.
   1439   */
   1440   Stability(root->child);
   1441   MeanStability(root->child);
   1442   list=(IntervalTree **) RelinquishMagickMemory(list);
   1443   return(root);
   1444 }
   1445 
   1446 /*
   1448 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1449 %                                                                             %
   1450 %                                                                             %
   1451 %                                                                             %
   1452 +   O p t i m a l T a u                                                       %
   1453 %                                                                             %
   1454 %                                                                             %
   1455 %                                                                             %
   1456 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1457 %
   1458 %  OptimalTau() finds the optimal tau for each band of the histogram.
   1459 %
   1460 %  The format of the OptimalTau method is:
   1461 %
   1462 %    double OptimalTau(const ssize_t *histogram,const double max_tau,
   1463 %      const double min_tau,const double delta_tau,
   1464 %      const double smooth_threshold,short *extrema)
   1465 %
   1466 %  A description of each parameter follows.
   1467 %
   1468 %    o histogram: Specifies an array of integers representing the number
   1469 %      of pixels for each intensity of a particular color component.
   1470 %
   1471 %    o extrema:  Specifies a pointer to an array of integers.  They
   1472 %      represent the peaks and valleys of the histogram for each color
   1473 %      component.
   1474 %
   1475 */
   1476 
   1477 static void ActiveNodes(IntervalTree **list,ssize_t *number_nodes,
   1478   IntervalTree *node)
   1479 {
   1480   if (node == (IntervalTree *) NULL)
   1481     return;
   1482   if (node->stability >= node->mean_stability)
   1483     {
   1484       list[(*number_nodes)++]=node;
   1485       ActiveNodes(list,number_nodes,node->sibling);
   1486     }
   1487   else
   1488     {
   1489       ActiveNodes(list,number_nodes,node->sibling);
   1490       ActiveNodes(list,number_nodes,node->child);
   1491     }
   1492 }
   1493 
   1494 static void FreeNodes(IntervalTree *node)
   1495 {
   1496   if (node == (IntervalTree *) NULL)
   1497     return;
   1498   FreeNodes(node->sibling);
   1499   FreeNodes(node->child);
   1500   node=(IntervalTree *) RelinquishMagickMemory(node);
   1501 }
   1502 
   1503 static double OptimalTau(const ssize_t *histogram,const double max_tau,
   1504   const double min_tau,const double delta_tau,const double smooth_threshold,
   1505   short *extrema)
   1506 {
   1507   IntervalTree
   1508     **list,
   1509     *node,
   1510     *root;
   1511 
   1512   MagickBooleanType
   1513     peak;
   1514 
   1515   double
   1516     average_tau,
   1517     *derivative,
   1518     *second_derivative,
   1519     tau,
   1520     value;
   1521 
   1522   register ssize_t
   1523     i,
   1524     x;
   1525 
   1526   size_t
   1527     count,
   1528     number_crossings;
   1529 
   1530   ssize_t
   1531     index,
   1532     j,
   1533     k,
   1534     number_nodes;
   1535 
   1536   ZeroCrossing
   1537     *zero_crossing;
   1538 
   1539   /*
   1540     Allocate interval tree.
   1541   */
   1542   list=(IntervalTree **) AcquireQuantumMemory((size_t) TreeLength,
   1543     sizeof(*list));
   1544   if (list == (IntervalTree **) NULL)
   1545     return(0.0);
   1546   /*
   1547     Allocate zero crossing list.
   1548   */
   1549   count=(size_t) ((max_tau-min_tau)/delta_tau)+2;
   1550   zero_crossing=(ZeroCrossing *) AcquireQuantumMemory((size_t) count,
   1551     sizeof(*zero_crossing));
   1552   if (zero_crossing == (ZeroCrossing *) NULL)
   1553     return(0.0);
   1554   for (i=0; i < (ssize_t) count; i++)
   1555     zero_crossing[i].tau=(-1.0);
   1556   /*
   1557     Initialize zero crossing list.
   1558   */
   1559   derivative=(double *) AcquireQuantumMemory(256,sizeof(*derivative));
   1560   second_derivative=(double *) AcquireQuantumMemory(256,
   1561     sizeof(*second_derivative));
   1562   if ((derivative == (double *) NULL) ||
   1563       (second_derivative == (double *) NULL))
   1564     ThrowFatalException(ResourceLimitFatalError,
   1565       "UnableToAllocateDerivatives");
   1566   i=0;
   1567   for (tau=max_tau; tau >= min_tau; tau-=delta_tau)
   1568   {
   1569     zero_crossing[i].tau=tau;
   1570     ScaleSpace(histogram,tau,zero_crossing[i].histogram);
   1571     DerivativeHistogram(zero_crossing[i].histogram,derivative);
   1572     DerivativeHistogram(derivative,second_derivative);
   1573     ZeroCrossHistogram(second_derivative,smooth_threshold,
   1574       zero_crossing[i].crossings);
   1575     i++;
   1576   }
   1577   /*
   1578     Add an entry for the original histogram.
   1579   */
   1580   zero_crossing[i].tau=0.0;
   1581   for (j=0; j <= 255; j++)
   1582     zero_crossing[i].histogram[j]=(double) histogram[j];
   1583   DerivativeHistogram(zero_crossing[i].histogram,derivative);
   1584   DerivativeHistogram(derivative,second_derivative);
   1585   ZeroCrossHistogram(second_derivative,smooth_threshold,
   1586     zero_crossing[i].crossings);
   1587   number_crossings=(size_t) i;
   1588   derivative=(double *) RelinquishMagickMemory(derivative);
   1589   second_derivative=(double *)
   1590     RelinquishMagickMemory(second_derivative);
   1591   /*
   1592     Ensure the scale-space fingerprints form lines in scale-space, not loops.
   1593   */
   1594   ConsolidateCrossings(zero_crossing,number_crossings);
   1595   /*
   1596     Force endpoints to be included in the interval.
   1597   */
   1598   for (i=0; i <= (ssize_t) number_crossings; i++)
   1599   {
   1600     for (j=0; j < 255; j++)
   1601       if (zero_crossing[i].crossings[j] != 0)
   1602         break;
   1603     zero_crossing[i].crossings[0]=(-zero_crossing[i].crossings[j]);
   1604     for (j=255; j > 0; j--)
   1605       if (zero_crossing[i].crossings[j] != 0)
   1606         break;
   1607     zero_crossing[i].crossings[255]=(-zero_crossing[i].crossings[j]);
   1608   }
   1609   /*
   1610     Initialize interval tree.
   1611   */
   1612   root=InitializeIntervalTree(zero_crossing,number_crossings);
   1613   if (root == (IntervalTree *) NULL)
   1614     return(0.0);
   1615   /*
   1616     Find active nodes:  stability is greater (or equal) to the mean stability of
   1617     its children.
   1618   */
   1619   number_nodes=0;
   1620   ActiveNodes(list,&number_nodes,root->child);
   1621   /*
   1622     Initialize extrema.
   1623   */
   1624   for (i=0; i <= 255; i++)
   1625     extrema[i]=0;
   1626   for (i=0; i < number_nodes; i++)
   1627   {
   1628     /*
   1629       Find this tau in zero crossings list.
   1630     */
   1631     k=0;
   1632     node=list[i];
   1633     for (j=0; j <= (ssize_t) number_crossings; j++)
   1634       if (zero_crossing[j].tau == node->tau)
   1635         k=j;
   1636     /*
   1637       Find the value of the peak.
   1638     */
   1639     peak=zero_crossing[k].crossings[node->right] == -1 ? MagickTrue :
   1640       MagickFalse;
   1641     index=node->left;
   1642     value=zero_crossing[k].histogram[index];
   1643     for (x=node->left; x <= node->right; x++)
   1644     {
   1645       if (peak != MagickFalse)
   1646         {
   1647           if (zero_crossing[k].histogram[x] > value)
   1648             {
   1649               value=zero_crossing[k].histogram[x];
   1650               index=x;
   1651             }
   1652         }
   1653       else
   1654         if (zero_crossing[k].histogram[x] < value)
   1655           {
   1656             value=zero_crossing[k].histogram[x];
   1657             index=x;
   1658           }
   1659     }
   1660     for (x=node->left; x <= node->right; x++)
   1661     {
   1662       if (index == 0)
   1663         index=256;
   1664       if (peak != MagickFalse)
   1665         extrema[x]=(short) index;
   1666       else
   1667         extrema[x]=(short) (-index);
   1668     }
   1669   }
   1670   /*
   1671     Determine the average tau.
   1672   */
   1673   average_tau=0.0;
   1674   for (i=0; i < number_nodes; i++)
   1675     average_tau+=list[i]->tau;
   1676   average_tau/=(double) number_nodes;
   1677   /*
   1678     Relinquish resources.
   1679   */
   1680   FreeNodes(root);
   1681   zero_crossing=(ZeroCrossing *) RelinquishMagickMemory(zero_crossing);
   1682   list=(IntervalTree **) RelinquishMagickMemory(list);
   1683   return(average_tau);
   1684 }
   1685 
   1686 /*
   1688 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1689 %                                                                             %
   1690 %                                                                             %
   1691 %                                                                             %
   1692 +   S c a l e S p a c e                                                       %
   1693 %                                                                             %
   1694 %                                                                             %
   1695 %                                                                             %
   1696 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1697 %
   1698 %  ScaleSpace() performs a scale-space filter on the 1D histogram.
   1699 %
   1700 %  The format of the ScaleSpace method is:
   1701 %
   1702 %      ScaleSpace(const ssize_t *histogram,const double tau,
   1703 %        double *scale_histogram)
   1704 %
   1705 %  A description of each parameter follows.
   1706 %
   1707 %    o histogram: Specifies an array of doubles representing the number
   1708 %      of pixels for each intensity of a particular color component.
   1709 %
   1710 */
   1711 
   1712 static void ScaleSpace(const ssize_t *histogram,const double tau,
   1713   double *scale_histogram)
   1714 {
   1715   double
   1716     alpha,
   1717     beta,
   1718     *gamma,
   1719     sum;
   1720 
   1721   register ssize_t
   1722     u,
   1723     x;
   1724 
   1725   gamma=(double *) AcquireQuantumMemory(256,sizeof(*gamma));
   1726   if (gamma == (double *) NULL)
   1727     ThrowFatalException(ResourceLimitFatalError,
   1728       "UnableToAllocateGammaMap");
   1729   alpha=PerceptibleReciprocal(tau*sqrt(2.0*MagickPI));
   1730   beta=(-1.0*PerceptibleReciprocal(2.0*tau*tau));
   1731   for (x=0; x <= 255; x++)
   1732     gamma[x]=0.0;
   1733   for (x=0; x <= 255; x++)
   1734   {
   1735     gamma[x]=exp((double) beta*x*x);
   1736     if (gamma[x] < MagickEpsilon)
   1737       break;
   1738   }
   1739   for (x=0; x <= 255; x++)
   1740   {
   1741     sum=0.0;
   1742     for (u=0; u <= 255; u++)
   1743       sum+=(double) histogram[u]*gamma[MagickAbsoluteValue(x-u)];
   1744     scale_histogram[x]=alpha*sum;
   1745   }
   1746   gamma=(double *) RelinquishMagickMemory(gamma);
   1747 }
   1748 
   1749 /*
   1751 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1752 %                                                                             %
   1753 %                                                                             %
   1754 %                                                                             %
   1755 %  S e g m e n t I m a g e                                                    %
   1756 %                                                                             %
   1757 %                                                                             %
   1758 %                                                                             %
   1759 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1760 %
   1761 %  SegmentImage() segment an image by analyzing the histograms of the color
   1762 %  components and identifying units that are homogeneous with the fuzzy
   1763 %  C-means technique.
   1764 %
   1765 %  The format of the SegmentImage method is:
   1766 %
   1767 %      MagickBooleanType SegmentImage(Image *image,
   1768 %        const ColorspaceType colorspace,const MagickBooleanType verbose,
   1769 %        const double cluster_threshold,const double smooth_threshold,
   1770 %        ExceptionInfo *exception)
   1771 %
   1772 %  A description of each parameter follows.
   1773 %
   1774 %    o image: the image.
   1775 %
   1776 %    o colorspace: Indicate the colorspace.
   1777 %
   1778 %    o verbose:  Set to MagickTrue to print detailed information about the
   1779 %      identified classes.
   1780 %
   1781 %    o cluster_threshold:  This represents the minimum number of pixels
   1782 %      contained in a hexahedra before it can be considered valid (expressed
   1783 %      as a percentage).
   1784 %
   1785 %    o smooth_threshold: the smoothing threshold eliminates noise in the second
   1786 %      derivative of the histogram.  As the value is increased, you can expect a
   1787 %      smoother second derivative.
   1788 %
   1789 %    o exception: return any errors or warnings in this structure.
   1790 %
   1791 */
   1792 MagickExport MagickBooleanType SegmentImage(Image *image,
   1793   const ColorspaceType colorspace,const MagickBooleanType verbose,
   1794   const double cluster_threshold,const double smooth_threshold,
   1795   ExceptionInfo *exception)
   1796 {
   1797   ColorspaceType
   1798     previous_colorspace;
   1799 
   1800   MagickBooleanType
   1801     status;
   1802 
   1803   register ssize_t
   1804     i;
   1805 
   1806   short
   1807     *extrema[MaxDimension];
   1808 
   1809   ssize_t
   1810     *histogram[MaxDimension];
   1811 
   1812   /*
   1813     Allocate histogram and extrema.
   1814   */
   1815   assert(image != (Image *) NULL);
   1816   assert(image->signature == MagickCoreSignature);
   1817   if (image->debug != MagickFalse)
   1818     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   1819   for (i=0; i < MaxDimension; i++)
   1820   {
   1821     histogram[i]=(ssize_t *) AcquireQuantumMemory(256,sizeof(**histogram));
   1822     extrema[i]=(short *) AcquireQuantumMemory(256,sizeof(**extrema));
   1823     if ((histogram[i] == (ssize_t *) NULL) || (extrema[i] == (short *) NULL))
   1824       {
   1825         for (i-- ; i >= 0; i--)
   1826         {
   1827           extrema[i]=(short *) RelinquishMagickMemory(extrema[i]);
   1828           histogram[i]=(ssize_t *) RelinquishMagickMemory(histogram[i]);
   1829         }
   1830         ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
   1831           image->filename)
   1832       }
   1833   }
   1834   /*
   1835     Initialize histogram.
   1836   */
   1837   previous_colorspace=image->colorspace;
   1838   (void) TransformImageColorspace(image,colorspace,exception);
   1839   InitializeHistogram(image,histogram,exception);
   1840   (void) OptimalTau(histogram[Red],Tau,0.2,DeltaTau,
   1841     smooth_threshold == 0.0 ? 1.0 : smooth_threshold,extrema[Red]);
   1842   (void) OptimalTau(histogram[Green],Tau,0.2,DeltaTau,
   1843     smooth_threshold == 0.0 ? 1.0 : smooth_threshold,extrema[Green]);
   1844   (void) OptimalTau(histogram[Blue],Tau,0.2,DeltaTau,
   1845     smooth_threshold == 0.0 ? 1.0 : smooth_threshold,extrema[Blue]);
   1846   /*
   1847     Classify using the fuzzy c-Means technique.
   1848   */
   1849   status=Classify(image,extrema,cluster_threshold,WeightingExponent,verbose,
   1850     exception);
   1851   (void) TransformImageColorspace(image,previous_colorspace,exception);
   1852   /*
   1853     Relinquish resources.
   1854   */
   1855   for (i=0; i < MaxDimension; i++)
   1856   {
   1857     extrema[i]=(short *) RelinquishMagickMemory(extrema[i]);
   1858     histogram[i]=(ssize_t *) RelinquishMagickMemory(histogram[i]);
   1859   }
   1860   return(status);
   1861 }
   1862 
   1863 /*
   1865 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1866 %                                                                             %
   1867 %                                                                             %
   1868 %                                                                             %
   1869 +   Z e r o C r o s s H i s t o g r a m                                       %
   1870 %                                                                             %
   1871 %                                                                             %
   1872 %                                                                             %
   1873 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1874 %
   1875 %  ZeroCrossHistogram() find the zero crossings in a histogram and marks
   1876 %  directions as:  1 is negative to positive; 0 is zero crossing; and -1
   1877 %  is positive to negative.
   1878 %
   1879 %  The format of the ZeroCrossHistogram method is:
   1880 %
   1881 %      ZeroCrossHistogram(double *second_derivative,
   1882 %        const double smooth_threshold,short *crossings)
   1883 %
   1884 %  A description of each parameter follows.
   1885 %
   1886 %    o second_derivative: Specifies an array of doubles representing the
   1887 %      second derivative of the histogram of a particular color component.
   1888 %
   1889 %    o crossings:  This array of integers is initialized with
   1890 %      -1, 0, or 1 representing the slope of the first derivative of the
   1891 %      of a particular color component.
   1892 %
   1893 */
   1894 static void ZeroCrossHistogram(double *second_derivative,
   1895   const double smooth_threshold,short *crossings)
   1896 {
   1897   register ssize_t
   1898     i;
   1899 
   1900   ssize_t
   1901     parity;
   1902 
   1903   /*
   1904     Merge low numbers to zero to help prevent noise.
   1905   */
   1906   for (i=0; i <= 255; i++)
   1907     if ((second_derivative[i] < smooth_threshold) &&
   1908         (second_derivative[i] >= -smooth_threshold))
   1909       second_derivative[i]=0.0;
   1910   /*
   1911     Mark zero crossings.
   1912   */
   1913   parity=0;
   1914   for (i=0; i <= 255; i++)
   1915   {
   1916     crossings[i]=0;
   1917     if (second_derivative[i] < 0.0)
   1918       {
   1919         if (parity > 0)
   1920           crossings[i]=(-1);
   1921         parity=1;
   1922       }
   1923     else
   1924       if (second_derivative[i] > 0.0)
   1925         {
   1926           if (parity < 0)
   1927             crossings[i]=1;
   1928           parity=(-1);
   1929         }
   1930   }
   1931 }
   1932