112 #define MaxDimension 3 113 #define DeltaTau 0.5f 114 #if defined(FastClassify) 115 #define WeightingExponent 2.0 116 #define SegmentPower(ratio) (ratio) 118 #define WeightingExponent 2.5 119 #define SegmentPower(ratio) pow(ratio,(double) (1.0/(weighting_exponent-1.0))); 194 OptimalTau(
const ssize_t *,
const double,
const double,
const double,
195 const double,
short *);
203 ScaleSpace(
const ssize_t *,
const double,
double *),
248 const double cluster_threshold,
const double weighting_exponent,
251 #define SegmentImageTag "Segment/Image" 252 #define ThrowClassifyException(severity,tag,label) \ 254 for (cluster=head; cluster != (Cluster *) NULL; cluster=next_cluster) \ 256 next_cluster=cluster->next; \ 257 cluster=(Cluster *) RelinquishMagickMemory(cluster); \ 259 if (squares != (double *) NULL) \ 262 free_squares=squares; \ 263 free_squares=(double *) RelinquishMagickMemory(free_squares); \ 265 ThrowBinaryException(severity,tag,label); \ 309 squares=(
double *) NULL;
310 (void) memset(&red,0,
sizeof(red));
311 (void) memset(&green,0,
sizeof(green));
312 (void) memset(&blue,0,
sizeof(blue));
327 sizeof(*cluster->
next));
328 cluster=cluster->
next;
335 if (cluster == (
Cluster *) NULL)
341 (void) memset(cluster,0,
sizeof(*cluster));
343 cluster->
green=green;
354 if (cluster == (
Cluster *) NULL)
360 (void) memset(cluster,0,
sizeof(*cluster));
362 cluster->
green=green;
373 for (y=0; y < (ssize_t) image->
rows; y++)
382 if (p == (
const Quantum *) NULL)
384 for (x=0; x < (ssize_t) image->
columns; x++)
392 for (cluster=head; cluster != (
Cluster *) NULL; cluster=cluster->
next)
417 #if defined(MAGICKCORE_OPENMP_SUPPORT) 433 for (cluster=head; cluster != (
Cluster *) NULL; cluster=next_cluster)
435 next_cluster=cluster->
next;
436 if ((cluster->
count > 0) &&
437 (cluster->
count >= (count*cluster_threshold/100.0)))
447 last_cluster=cluster;
456 last_cluster->
next=next_cluster;
459 number_clusters=(size_t) count;
472 (
double) number_clusters);
478 for (cluster=head; cluster != (
Cluster *) NULL; cluster=cluster->
next)
480 cluster->
id,(
double) cluster->
count);
485 "\n\n\nCluster Extents: (Vector Size: %d)\n",
MaxDimension);
487 for (cluster=head; cluster != (
Cluster *) NULL; cluster=cluster->
next)
492 "%.20g-%.20g %.20g-%.20g %.20g-%.20g\n",(
double)
501 "\n\n\nCluster Center Values: (Vector Size: %d)\n",
MaxDimension);
503 for (cluster=head; cluster != (
Cluster *) NULL; cluster=cluster->
next)
513 if (number_clusters > 256)
519 if (squares == (
double *) NULL)
523 for (i=(-255); i <= 255; i++)
524 squares[i]=(
double) i*(double) i;
532 for (cluster=head; cluster != (
Cluster *) NULL; cluster=cluster->
next)
534 image->
colormap[i].
red=(double) ScaleCharToQuantum((
unsigned char)
536 image->
colormap[i].
green=(double) ScaleCharToQuantum((
unsigned char)
538 image->
colormap[i].
blue=(double) ScaleCharToQuantum((
unsigned char)
546 #if defined(MAGICKCORE_OPENMP_SUPPORT) 547 #pragma omp parallel for schedule(static) shared(progress,status) \ 548 magick_number_threads(image,image,image->rows,1) 550 for (y=0; y < (ssize_t) image->
rows; y++)
572 for (x=0; x < (ssize_t) image->
columns; x++)
581 for (cluster=head; cluster != (
Cluster *) NULL; cluster=cluster->
next)
597 if (cluster == (
Cluster *) NULL)
614 for (j=0; j < (ssize_t) image->
colors; j++)
619 squares[(ssize_t) (pixel.
red-ScaleQuantumToChar(p->red))]+
620 squares[(ssize_t) (pixel.
green-ScaleQuantumToChar(p->green))]+
621 squares[(ssize_t) (pixel.
blue-ScaleQuantumToChar(p->blue))];
622 numerator=distance_squared;
623 for (k=0; k < (ssize_t) image->
colors; k++)
627 squares[(ssize_t) (pixel.
red-ScaleQuantumToChar(p->red))]+
628 squares[(ssize_t) (pixel.
green-ScaleQuantumToChar(p->green))]+
629 squares[(ssize_t) (pixel.
blue-ScaleQuantumToChar(p->blue))];
630 ratio=numerator/distance_squared;
633 if ((sum != 0.0) && ((1.0/sum) > local_minima))
638 local_minima=1.0/sum;
652 #if defined(MAGICKCORE_OPENMP_SUPPORT) 666 for (cluster=head; cluster != (
Cluster *) NULL; cluster=next_cluster)
668 next_cluster=cluster->
next;
672 free_squares=squares;
705 const size_t number_crossings)
723 for (i=(ssize_t) number_crossings-1; i >= 0; i--)
724 for (j=0; j <= 255; j++)
726 if (zero_crossing[i].crossings[j] == 0)
733 for (k=j-1; k > 0; k--)
734 if (zero_crossing[i+1].crossings[k] != 0)
738 for (k=j+1; k < 255; k++)
739 if (zero_crossing[i+1].crossings[k] != 0)
745 for (k=j-1; k > 0; k--)
746 if (zero_crossing[i].crossings[k] != 0)
754 if (zero_crossing[i+1].crossings[j] != 0)
757 for (l=k+1; l < center; l++)
758 if (zero_crossing[i+1].crossings[l] != 0)
760 if (((count % 2) == 0) && (center != k))
769 for (l=k+1; l < left; l++)
770 if (zero_crossing[i+1].crossings[l] != 0)
772 if (((count % 2) == 0) && (left != k))
781 for (l=k+1; l < right; l++)
782 if (zero_crossing[i+1].crossings[l] != 0)
784 if (((count % 2) == 0) && (right != k))
787 l=(ssize_t) zero_crossing[i].crossings[j];
790 zero_crossing[i].
crossings[correct]=(short) l;
832 for ( ; extents->
index <= 255; extents->
index++)
833 if (extrema[extents->
index] > 0)
835 if (extents->
index > 255)
841 for ( ; extents->
index <= 255; extents->
index++)
842 if (extrema[extents->
index] < 0)
888 derivative[0]=(-1.5*histogram[0]+2.0*histogram[1]-0.5*histogram[2]);
889 derivative[n]=(0.5*histogram[n-2]-2.0*histogram[n-1]+1.5*histogram[n]);
893 for (i=1; i < n; i++)
894 derivative[i]=(histogram[i+1]-histogram[i-1])/2.0;
935 const double cluster_threshold,
const double smooth_threshold,
975 assert(image != (
Image *) NULL);
984 if ((histogram[i] == (ssize_t *) NULL) || (extrema[i] == (
short *) NULL))
986 for (i-- ; i >= 0; i--)
1001 (smooth_threshold == 0.0f ? 1.0f : smooth_threshold),extrema[
Red]);
1003 (smooth_threshold == 0.0f ? 1.0f : smooth_threshold),extrema[
Green]);
1005 (smooth_threshold == 0.0f ? 1.0f : smooth_threshold),extrema[
Blue]);
1011 (void) memset(&red,0,
sizeof(red));
1012 (void) memset(&green,0,
sizeof(green));
1013 (void) memset(&blue,0,
sizeof(blue));
1028 sizeof(*cluster->
next));
1029 cluster=cluster->
next;
1036 if (cluster == (
Cluster *) NULL)
1048 cluster->
green=green;
1060 if (cluster == (
Cluster *) NULL)
1071 cluster->
green=green;
1080 for (y=0; y < (ssize_t) image->
rows; y++)
1083 if (p == (
const Quantum *) NULL)
1085 for (x=0; x < (ssize_t) image->
columns; x++)
1093 for (cluster=head; cluster != (
Cluster *) NULL; cluster=cluster->
next)
1124 for (cluster=head; cluster != (
Cluster *) NULL; cluster=next_cluster)
1126 next_cluster=cluster->
next;
1127 if ((cluster->
count > 0) &&
1128 (cluster->
count >= (count*cluster_threshold/100.0)))
1138 last_cluster=cluster;
1144 if (cluster == head)
1147 last_cluster->
next=next_cluster;
1155 for (cluster=
object; cluster->
next != (
Cluster *) NULL; )
1159 cluster=cluster->
next;
1161 background=head->
next;
1162 for (cluster=background; cluster->
next != (
Cluster *) NULL; )
1166 cluster=cluster->
next;
1169 if (background != (
Cluster *) NULL)
1171 threshold=(background->
red.
center+
object->red.center)/2.0;
1172 pixel->
red=(double) ScaleCharToQuantum((
unsigned char)
1174 threshold=(background->
green.
center+
object->green.center)/2.0;
1175 pixel->
green=(double) ScaleCharToQuantum((
unsigned char)
1177 threshold=(background->
blue.
center+
object->blue.center)/2.0;
1178 pixel->
blue=(double) ScaleCharToQuantum((
unsigned char)
1184 for (cluster=head; cluster != (
Cluster *) NULL; cluster=next_cluster)
1186 next_cluster=cluster->
next;
1239 for (i=0; i <= 255; i++)
1241 histogram[
Red][i]=0;
1242 histogram[
Green][i]=0;
1243 histogram[
Blue][i]=0;
1245 for (y=0; y < (ssize_t) image->
rows; y++)
1248 if (p == (
const Quantum *) NULL)
1250 for (x=0; x < (ssize_t) image->
columns; x++)
1252 histogram[
Red][(ssize_t) ScaleQuantumToChar(
GetPixelRed(image,p))]++;
1294 list[(*number_nodes)++]=node;
1342 const size_t number_crossings)
1377 (void) memset(list,0,
TreeLength*
sizeof(*list));
1378 for (i=(-1); i < (ssize_t) number_crossings; i++)
1388 for (j=0; j < number_nodes; j++)
1393 for (k=head->
left+1; k < head->right; k++)
1395 if (zero_crossing[i+1].crossings[k] != 0)
1400 sizeof(*node->
child));
1415 node->
tau=zero_crossing[i+1].
tau;
1423 if (left != head->
left)
1434 node->
tau=zero_crossing[i+1].
tau;
1488 list[(*number_nodes)++]=node;
1507 static double OptimalTau(
const ssize_t *histogram,
const double max_tau,
1508 const double min_tau,
const double delta_tau,
const double smooth_threshold,
1553 count=(size_t) ((max_tau-min_tau)/delta_tau)+2;
1555 sizeof(*zero_crossing));
1561 for (i=0; i < (ssize_t) count; i++)
1562 zero_crossing[i].tau=(-1.0);
1568 sizeof(*second_derivative));
1570 for (tau=max_tau; tau >= min_tau; tau-=delta_tau)
1572 zero_crossing[i].
tau=tau;
1573 ScaleSpace(histogram,tau,zero_crossing[i].histogram);
1577 zero_crossing[i].crossings);
1583 zero_crossing[i].
tau=0.0;
1584 for (j=0; j <= 255; j++)
1585 zero_crossing[i].histogram[j]=(
double) histogram[j];
1589 zero_crossing[i].crossings);
1590 number_crossings=(size_t) i;
1600 for (i=0; i <= (ssize_t) number_crossings; i++)
1602 for (j=0; j < 255; j++)
1603 if (zero_crossing[i].crossings[j] != 0)
1606 for (j=255; j > 0; j--)
1607 if (zero_crossing[i].crossings[j] != 0)
1630 for (i=0; i <= 255; i++)
1632 for (i=0; i < number_nodes; i++)
1639 for (j=0; j <= (ssize_t) number_crossings; j++)
1640 if (zero_crossing[j].tau == node->
tau)
1648 value=zero_crossing[k].
histogram[index];
1649 for (x=node->
left; x <= node->right; x++)
1653 if (zero_crossing[k].histogram[x] > value)
1660 if (zero_crossing[k].histogram[x] < value)
1666 for (x=node->
left; x <= node->right; x++)
1671 extrema[x]=(short) index;
1673 extrema[x]=(short) (-index);
1680 for (i=0; i < number_nodes; i++)
1681 average_tau+=list[i]->tau;
1689 return(average_tau);
1716 static void ScaleSpace(
const ssize_t *histogram,
const double tau,
1717 double *scale_histogram)
1730 if (gamma == (
double *) NULL)
1734 for (x=0; x <= 255; x++)
1736 for (x=0; x <= 255; x++)
1738 gamma[x]=exp((
double) beta*x*x);
1742 for (x=0; x <= 255; x++)
1745 for (u=0; u <= 255; u++)
1747 scale_histogram[x]=alpha*sum;
1796 const double cluster_threshold,
const double smooth_threshold,
1800 previous_colorspace;
1817 assert(image != (
Image *) NULL);
1825 if ((histogram[i] == (ssize_t *) NULL) || (extrema[i] == (
short *) NULL))
1827 for (i-- ; i >= 0; i--)
1843 1.0 : smooth_threshold,extrema[
Red]);
1845 1.0 : smooth_threshold,extrema[
Green]);
1847 1.0 : smooth_threshold,extrema[
Blue]);
1896 const double smooth_threshold,
short *crossings)
1907 for (i=0; i <= 255; i++)
1908 if ((second_derivative[i] < smooth_threshold) &&
1909 (second_derivative[i] >= -smooth_threshold))
1910 second_derivative[i]=0.0;
1915 for (i=0; i <= 255; i++)
1918 if (second_derivative[i] < 0.0)
1925 if (second_derivative[i] > 0.0)
struct _IntervalTree IntervalTree
MagickExport CacheView * DestroyCacheView(CacheView *cache_view)
static void ConsolidateCrossings(ZeroCrossing *zero_crossing, const size_t number_crossings)
struct _ExtentPacket ExtentPacket
MagickProgressMonitor progress_monitor
struct _IntervalTree * sibling
MagickExport MagickBooleanType SyncImage(Image *image, ExceptionInfo *exception)
MagickExport MagickBooleanType TransformImageColorspace(Image *image, const ColorspaceType colorspace, ExceptionInfo *exception)
static Quantum GetPixelRed(const Image *magick_restrict image, const Quantum *magick_restrict pixel)
#define ThrowFatalException(severity, tag)
#define WeightingExponent
#define MagickAbsoluteValue(x)
MagickExport const Quantum * GetCacheViewVirtualPixels(const CacheView *cache_view, const ssize_t x, const ssize_t y, const size_t columns, const size_t rows, ExceptionInfo *exception)
static void Stability(IntervalTree *node)
#define ThrowBinaryException(severity, tag, context)
MagickExport void GetPixelInfo(const Image *image, PixelInfo *pixel)
static void ScaleSpace(const ssize_t *, const double, double *)
static IntervalTree * InitializeIntervalTree(const ZeroCrossing *zero_crossing, const size_t number_crossings)
MagickExport MagickBooleanType GetImageDynamicThreshold(const Image *image, const double cluster_threshold, const double smooth_threshold, PixelInfo *pixel, ExceptionInfo *exception)
#define MagickCoreSignature
MagickExport Quantum * GetCacheViewAuthenticPixels(CacheView *cache_view, const ssize_t x, const ssize_t y, const size_t columns, const size_t rows, ExceptionInfo *exception)
static void MeanStability(IntervalTree *node)
static void InitializeList(IntervalTree **list, ssize_t *number_nodes, IntervalTree *node)
MagickExport ssize_t FormatLocaleFile(FILE *file, const char *magick_restrict format,...)
unsigned int MagickStatusType
static double PerceptibleReciprocal(const double x)
MagickExport void * AcquireCriticalMemory(const size_t size)
struct _ZeroCrossing ZeroCrossing
MagickExport MagickBooleanType SegmentImage(Image *image, const ColorspaceType colorspace, const MagickBooleanType verbose, const double cluster_threshold, const double smooth_threshold, ExceptionInfo *exception)
MagickExport const Quantum * GetVirtualPixels(const Image *image, const ssize_t x, const ssize_t y, const size_t columns, const size_t rows, ExceptionInfo *exception)
MagickExport void * AcquireQuantumMemory(const size_t count, const size_t quantum)
static Quantum GetPixelGreen(const Image *magick_restrict image, const Quantum *magick_restrict pixel)
static void ActiveNodes(IntervalTree **list, ssize_t *number_nodes, IntervalTree *node)
MagickExport MagickBooleanType ThrowMagickException(ExceptionInfo *exception, const char *module, const char *function, const size_t line, const ExceptionType severity, const char *tag, const char *format,...)
MagickExport MagickBooleanType LogMagickEvent(const LogEventType type, const char *module, const char *function, const size_t line, const char *format,...)
static double OptimalTau(const ssize_t *, const double, const double, const double, const double, short *)
MagickBooleanType(* MagickProgressMonitor)(const char *, const MagickOffsetType, const MagickSizeType, void *)
static void ZeroCrossHistogram(double *, const double, short *)
static ssize_t DefineRegion(const short *, ExtentPacket *)
static MagickBooleanType Classify(Image *image, short **extrema, const double cluster_threshold, const double weighting_exponent, const MagickBooleanType verbose, ExceptionInfo *exception)
static const int SafeMargin
static size_t GetPixelChannels(const Image *magick_restrict image)
MagickExport MagickBooleanType AcquireImageColormap(Image *image, const size_t colors, ExceptionInfo *exception)
char filename[MagickPathExtent]
#define SegmentPower(ratio)
#define GetMagickModule()
MagickExport CacheView * AcquireVirtualCacheView(const Image *image, ExceptionInfo *exception)
static void DerivativeHistogram(const double *histogram, double *derivative)
static void FreeNodes(IntervalTree *)
static const int TreeLength
static void SetPixelIndex(const Image *magick_restrict image, const Quantum index, Quantum *magick_restrict pixel)
#define ThrowClassifyException(severity, tag, label)
MagickExport void * RelinquishMagickMemory(void *memory)
MagickExport MagickBooleanType SyncCacheViewAuthenticPixels(CacheView *magick_restrict cache_view, ExceptionInfo *exception)
MagickExport CacheView * AcquireAuthenticCacheView(const Image *image, ExceptionInfo *exception)
static void InitializeHistogram(const Image *, ssize_t **, ExceptionInfo *)
static Quantum GetPixelBlue(const Image *magick_restrict image, const Quantum *magick_restrict pixel)
struct _IntervalTree * child
ColorspaceType colorspace
MagickExport MagickBooleanType SetImageProgress(const Image *image, const char *tag, const MagickOffsetType offset, const MagickSizeType extent)