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