2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6 % FFFFF EEEEE AAA TTTTT U U RRRR EEEEE %
7 % F E A A T U U R R E %
8 % FFF EEE AAAAA T U U RRRR EEE %
9 % F E A A T U U R R E %
10 % F EEEEE A A T UUU R R EEEEE %
13 % MagickCore Image Feature Methods %
20 % Copyright 1999-2014 ImageMagick Studio LLC, a non-profit organization %
21 % dedicated to making software imaging solutions freely available. %
23 % You may not use this file except in compliance with the License. You may %
24 % obtain a copy of the License at %
26 % http://www.imagemagick.org/script/license.php %
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. %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
43 #include "MagickCore/studio.h"
44 #include "MagickCore/property.h"
45 #include "MagickCore/animate.h"
46 #include "MagickCore/blob.h"
47 #include "MagickCore/blob-private.h"
48 #include "MagickCore/cache.h"
49 #include "MagickCore/cache-private.h"
50 #include "MagickCore/cache-view.h"
51 #include "MagickCore/client.h"
52 #include "MagickCore/color.h"
53 #include "MagickCore/color-private.h"
54 #include "MagickCore/colorspace.h"
55 #include "MagickCore/colorspace-private.h"
56 #include "MagickCore/composite.h"
57 #include "MagickCore/composite-private.h"
58 #include "MagickCore/compress.h"
59 #include "MagickCore/constitute.h"
60 #include "MagickCore/display.h"
61 #include "MagickCore/draw.h"
62 #include "MagickCore/enhance.h"
63 #include "MagickCore/exception.h"
64 #include "MagickCore/exception-private.h"
65 #include "MagickCore/feature.h"
66 #include "MagickCore/gem.h"
67 #include "MagickCore/geometry.h"
68 #include "MagickCore/list.h"
69 #include "MagickCore/image-private.h"
70 #include "MagickCore/magic.h"
71 #include "MagickCore/magick.h"
72 #include "MagickCore/memory_.h"
73 #include "MagickCore/module.h"
74 #include "MagickCore/monitor.h"
75 #include "MagickCore/monitor-private.h"
76 #include "MagickCore/option.h"
77 #include "MagickCore/paint.h"
78 #include "MagickCore/pixel-accessor.h"
79 #include "MagickCore/profile.h"
80 #include "MagickCore/quantize.h"
81 #include "MagickCore/quantum-private.h"
82 #include "MagickCore/random_.h"
83 #include "MagickCore/resource_.h"
84 #include "MagickCore/segment.h"
85 #include "MagickCore/semaphore.h"
86 #include "MagickCore/signature-private.h"
87 #include "MagickCore/string_.h"
88 #include "MagickCore/thread-private.h"
89 #include "MagickCore/timer.h"
90 #include "MagickCore/utility.h"
91 #include "MagickCore/version.h"
94 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
98 % G e t I m a g e F e a t u r e s %
102 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
104 % GetImageFeatures() returns features for each channel in the image in
105 % each of four directions (horizontal, vertical, left and right diagonals)
106 % for the specified distance. The features include the angular second
107 % moment, contrast, correlation, sum of squares: variance, inverse difference
108 % moment, sum average, sum varience, sum entropy, entropy, difference variance,% difference entropy, information measures of correlation 1, information
109 % measures of correlation 2, and maximum correlation coefficient. You can
110 % access the red channel contrast, for example, like this:
112 % channel_features=GetImageFeatures(image,1,exception);
113 % contrast=channel_features[RedPixelChannel].contrast[0];
115 % Use MagickRelinquishMemory() to free the features buffer.
117 % The format of the GetImageFeatures method is:
119 % ChannelFeatures *GetImageFeatures(const Image *image,
120 % const size_t distance,ExceptionInfo *exception)
122 % A description of each parameter follows:
124 % o image: the image.
126 % o distance: the distance.
128 % o exception: return any errors or warnings in this structure.
132 static inline ssize_t MagickAbsoluteValue(const ssize_t x)
139 static inline double MagickLog10(const double x)
141 if (fabs(x) < MagickMinimumValue)
142 return(log10(MagickMinimumValue));
143 return(log10(fabs(x)));
146 MagickExport ChannelFeatures *GetImageFeatures(const Image *image,
147 const size_t distance,ExceptionInfo *exception)
149 typedef struct _ChannelStatistics
152 direction[4]; /* horizontal, vertical, left and right diagonals */
197 assert(image != (Image *) NULL);
198 assert(image->signature == MagickSignature);
199 if (image->debug != MagickFalse)
200 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
201 if ((image->columns < (distance+1)) || (image->rows < (distance+1)))
202 return((ChannelFeatures *) NULL);
203 length=CompositeChannels+1UL;
204 channel_features=(ChannelFeatures *) AcquireQuantumMemory(length,
205 sizeof(*channel_features));
206 if (channel_features == (ChannelFeatures *) NULL)
207 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
208 (void) ResetMagickMemory(channel_features,0,length*
209 sizeof(*channel_features));
213 grays=(PixelPacket *) AcquireQuantumMemory(MaxMap+1UL,sizeof(*grays));
214 if (grays == (PixelPacket *) NULL)
216 channel_features=(ChannelFeatures *) RelinquishMagickMemory(
218 (void) ThrowMagickException(exception,GetMagickModule(),
219 ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
220 return(channel_features);
222 for (i=0; i <= (ssize_t) MaxMap; i++)
225 grays[i].green=(~0U);
227 grays[i].alpha=(~0U);
228 grays[i].black=(~0U);
231 image_view=AcquireVirtualCacheView(image,exception);
232 #if defined(MAGICKCORE_OPENMP_SUPPORT)
233 #pragma omp parallel for schedule(static,4) shared(status) \
234 magick_threads(image,image,image->rows,1)
236 for (y=0; y < (ssize_t) image->rows; y++)
238 register const Quantum
244 if (status == MagickFalse)
246 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
247 if (p == (const Quantum *) NULL)
252 for (x=0; x < (ssize_t) image->columns; x++)
254 grays[ScaleQuantumToMap(GetPixelRed(image,p))].red=
255 ScaleQuantumToMap(GetPixelRed(image,p));
256 grays[ScaleQuantumToMap(GetPixelGreen(image,p))].green=
257 ScaleQuantumToMap(GetPixelGreen(image,p));
258 grays[ScaleQuantumToMap(GetPixelBlue(image,p))].blue=
259 ScaleQuantumToMap(GetPixelBlue(image,p));
260 if (image->colorspace == CMYKColorspace)
261 grays[ScaleQuantumToMap(GetPixelBlack(image,p))].black=
262 ScaleQuantumToMap(GetPixelBlack(image,p));
263 if (image->alpha_trait == BlendPixelTrait)
264 grays[ScaleQuantumToMap(GetPixelAlpha(image,p))].alpha=
265 ScaleQuantumToMap(GetPixelAlpha(image,p));
266 p+=GetPixelChannels(image);
269 image_view=DestroyCacheView(image_view);
270 if (status == MagickFalse)
272 grays=(PixelPacket *) RelinquishMagickMemory(grays);
273 channel_features=(ChannelFeatures *) RelinquishMagickMemory(
275 return(channel_features);
277 (void) ResetMagickMemory(&gray,0,sizeof(gray));
278 for (i=0; i <= (ssize_t) MaxMap; i++)
280 if (grays[i].red != ~0U)
281 grays[gray.red++].red=grays[i].red;
282 if (grays[i].green != ~0U)
283 grays[gray.green++].green=grays[i].green;
284 if (grays[i].blue != ~0U)
285 grays[gray.blue++].blue=grays[i].blue;
286 if (image->colorspace == CMYKColorspace)
287 if (grays[i].black != ~0U)
288 grays[gray.black++].black=grays[i].black;
289 if (image->alpha_trait == BlendPixelTrait)
290 if (grays[i].alpha != ~0U)
291 grays[gray.alpha++].alpha=grays[i].alpha;
294 Allocate spatial dependence matrix.
296 number_grays=gray.red;
297 if (gray.green > number_grays)
298 number_grays=gray.green;
299 if (gray.blue > number_grays)
300 number_grays=gray.blue;
301 if (image->colorspace == CMYKColorspace)
302 if (gray.black > number_grays)
303 number_grays=gray.black;
304 if (image->alpha_trait == BlendPixelTrait)
305 if (gray.alpha > number_grays)
306 number_grays=gray.alpha;
307 cooccurrence=(ChannelStatistics **) AcquireQuantumMemory(number_grays,
308 sizeof(*cooccurrence));
309 density_x=(ChannelStatistics *) AcquireQuantumMemory(2*(number_grays+1),
311 density_xy=(ChannelStatistics *) AcquireQuantumMemory(2*(number_grays+1),
312 sizeof(*density_xy));
313 density_y=(ChannelStatistics *) AcquireQuantumMemory(2*(number_grays+1),
315 Q=(ChannelStatistics **) AcquireQuantumMemory(number_grays,sizeof(*Q));
316 sum=(ChannelStatistics *) AcquireQuantumMemory(number_grays,sizeof(*sum));
317 if ((cooccurrence == (ChannelStatistics **) NULL) ||
318 (density_x == (ChannelStatistics *) NULL) ||
319 (density_xy == (ChannelStatistics *) NULL) ||
320 (density_y == (ChannelStatistics *) NULL) ||
321 (Q == (ChannelStatistics **) NULL) ||
322 (sum == (ChannelStatistics *) NULL))
324 if (Q != (ChannelStatistics **) NULL)
326 for (i=0; i < (ssize_t) number_grays; i++)
327 Q[i]=(ChannelStatistics *) RelinquishMagickMemory(Q[i]);
328 Q=(ChannelStatistics **) RelinquishMagickMemory(Q);
330 if (sum != (ChannelStatistics *) NULL)
331 sum=(ChannelStatistics *) RelinquishMagickMemory(sum);
332 if (density_y != (ChannelStatistics *) NULL)
333 density_y=(ChannelStatistics *) RelinquishMagickMemory(density_y);
334 if (density_xy != (ChannelStatistics *) NULL)
335 density_xy=(ChannelStatistics *) RelinquishMagickMemory(density_xy);
336 if (density_x != (ChannelStatistics *) NULL)
337 density_x=(ChannelStatistics *) RelinquishMagickMemory(density_x);
338 if (cooccurrence != (ChannelStatistics **) NULL)
340 for (i=0; i < (ssize_t) number_grays; i++)
341 cooccurrence[i]=(ChannelStatistics *)
342 RelinquishMagickMemory(cooccurrence[i]);
343 cooccurrence=(ChannelStatistics **) RelinquishMagickMemory(
346 grays=(PixelPacket *) RelinquishMagickMemory(grays);
347 channel_features=(ChannelFeatures *) RelinquishMagickMemory(
349 (void) ThrowMagickException(exception,GetMagickModule(),
350 ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
351 return(channel_features);
353 (void) ResetMagickMemory(&correlation,0,sizeof(correlation));
354 (void) ResetMagickMemory(density_x,0,2*(number_grays+1)*sizeof(*density_x));
355 (void) ResetMagickMemory(density_xy,0,2*(number_grays+1)*sizeof(*density_xy));
356 (void) ResetMagickMemory(density_y,0,2*(number_grays+1)*sizeof(*density_y));
357 (void) ResetMagickMemory(&mean,0,sizeof(mean));
358 (void) ResetMagickMemory(sum,0,number_grays*sizeof(*sum));
359 (void) ResetMagickMemory(&sum_squares,0,sizeof(sum_squares));
360 (void) ResetMagickMemory(density_xy,0,2*number_grays*sizeof(*density_xy));
361 (void) ResetMagickMemory(&entropy_x,0,sizeof(entropy_x));
362 (void) ResetMagickMemory(&entropy_xy,0,sizeof(entropy_xy));
363 (void) ResetMagickMemory(&entropy_xy1,0,sizeof(entropy_xy1));
364 (void) ResetMagickMemory(&entropy_xy2,0,sizeof(entropy_xy2));
365 (void) ResetMagickMemory(&entropy_y,0,sizeof(entropy_y));
366 (void) ResetMagickMemory(&variance,0,sizeof(variance));
367 for (i=0; i < (ssize_t) number_grays; i++)
369 cooccurrence[i]=(ChannelStatistics *) AcquireQuantumMemory(number_grays,
370 sizeof(**cooccurrence));
371 Q[i]=(ChannelStatistics *) AcquireQuantumMemory(number_grays,sizeof(**Q));
372 if ((cooccurrence[i] == (ChannelStatistics *) NULL) ||
373 (Q[i] == (ChannelStatistics *) NULL))
375 (void) ResetMagickMemory(cooccurrence[i],0,number_grays*
376 sizeof(**cooccurrence));
377 (void) ResetMagickMemory(Q[i],0,number_grays*sizeof(**Q));
379 if (i < (ssize_t) number_grays)
381 for (i--; i >= 0; i--)
383 if (Q[i] != (ChannelStatistics *) NULL)
384 Q[i]=(ChannelStatistics *) RelinquishMagickMemory(Q[i]);
385 if (cooccurrence[i] != (ChannelStatistics *) NULL)
386 cooccurrence[i]=(ChannelStatistics *)
387 RelinquishMagickMemory(cooccurrence[i]);
389 Q=(ChannelStatistics **) RelinquishMagickMemory(Q);
390 cooccurrence=(ChannelStatistics **) RelinquishMagickMemory(cooccurrence);
391 sum=(ChannelStatistics *) RelinquishMagickMemory(sum);
392 density_y=(ChannelStatistics *) RelinquishMagickMemory(density_y);
393 density_xy=(ChannelStatistics *) RelinquishMagickMemory(density_xy);
394 density_x=(ChannelStatistics *) RelinquishMagickMemory(density_x);
395 grays=(PixelPacket *) RelinquishMagickMemory(grays);
396 channel_features=(ChannelFeatures *) RelinquishMagickMemory(
398 (void) ThrowMagickException(exception,GetMagickModule(),
399 ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
400 return(channel_features);
403 Initialize spatial dependence matrix.
406 image_view=AcquireVirtualCacheView(image,exception);
407 for (y=0; y < (ssize_t) image->rows; y++)
409 register const Quantum
421 if (status == MagickFalse)
423 p=GetCacheViewVirtualPixels(image_view,-(ssize_t) distance,y,image->columns+
424 2*distance,distance+2,exception);
425 if (p == (const Quantum *) NULL)
430 p+=distance*GetPixelChannels(image);;
431 for (x=0; x < (ssize_t) image->columns; x++)
433 for (i=0; i < 4; i++)
441 Horizontal adjacency.
443 offset=(ssize_t) distance;
451 offset=(ssize_t) (image->columns+2*distance);
457 Right diagonal adjacency.
459 offset=(ssize_t) ((image->columns+2*distance)-distance);
465 Left diagonal adjacency.
467 offset=(ssize_t) ((image->columns+2*distance)+distance);
473 while (grays[u].red != ScaleQuantumToMap(GetPixelRed(image,p)))
475 while (grays[v].red != ScaleQuantumToMap(GetPixelRed(image,p+offset*GetPixelChannels(image))))
477 cooccurrence[u][v].direction[i].red++;
478 cooccurrence[v][u].direction[i].red++;
481 while (grays[u].green != ScaleQuantumToMap(GetPixelGreen(image,p)))
483 while (grays[v].green != ScaleQuantumToMap(GetPixelGreen(image,p+offset*GetPixelChannels(image))))
485 cooccurrence[u][v].direction[i].green++;
486 cooccurrence[v][u].direction[i].green++;
489 while (grays[u].blue != ScaleQuantumToMap(GetPixelBlue(image,p)))
491 while (grays[v].blue != ScaleQuantumToMap(GetPixelBlue(image,p+offset*GetPixelChannels(image))))
493 cooccurrence[u][v].direction[i].blue++;
494 cooccurrence[v][u].direction[i].blue++;
495 if (image->colorspace == CMYKColorspace)
499 while (grays[u].black != ScaleQuantumToMap(GetPixelBlack(image,p)))
501 while (grays[v].black != ScaleQuantumToMap(GetPixelBlack(image,p+offset*GetPixelChannels(image))))
503 cooccurrence[u][v].direction[i].black++;
504 cooccurrence[v][u].direction[i].black++;
506 if (image->alpha_trait == BlendPixelTrait)
510 while (grays[u].alpha != ScaleQuantumToMap(GetPixelAlpha(image,p)))
512 while (grays[v].alpha != ScaleQuantumToMap(GetPixelAlpha(image,p+offset*GetPixelChannels(image))))
514 cooccurrence[u][v].direction[i].alpha++;
515 cooccurrence[v][u].direction[i].alpha++;
518 p+=GetPixelChannels(image);
521 grays=(PixelPacket *) RelinquishMagickMemory(grays);
522 image_view=DestroyCacheView(image_view);
523 if (status == MagickFalse)
525 for (i=0; i < (ssize_t) number_grays; i++)
526 cooccurrence[i]=(ChannelStatistics *)
527 RelinquishMagickMemory(cooccurrence[i]);
528 cooccurrence=(ChannelStatistics **) RelinquishMagickMemory(cooccurrence);
529 channel_features=(ChannelFeatures *) RelinquishMagickMemory(
531 (void) ThrowMagickException(exception,GetMagickModule(),
532 ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
533 return(channel_features);
536 Normalize spatial dependence matrix.
538 for (i=0; i < 4; i++)
552 Horizontal adjacency.
554 normalize=2.0*image->rows*(image->columns-distance);
562 normalize=2.0*(image->rows-distance)*image->columns;
568 Right diagonal adjacency.
570 normalize=2.0*(image->rows-distance)*(image->columns-distance);
576 Left diagonal adjacency.
578 normalize=2.0*(image->rows-distance)*(image->columns-distance);
582 normalize=PerceptibleReciprocal(normalize);
583 for (y=0; y < (ssize_t) number_grays; y++)
588 for (x=0; x < (ssize_t) number_grays; x++)
590 cooccurrence[x][y].direction[i].red*=normalize;
591 cooccurrence[x][y].direction[i].green*=normalize;
592 cooccurrence[x][y].direction[i].blue*=normalize;
593 if (image->colorspace == CMYKColorspace)
594 cooccurrence[x][y].direction[i].black*=normalize;
595 if (image->alpha_trait == BlendPixelTrait)
596 cooccurrence[x][y].direction[i].alpha*=normalize;
601 Compute texture features.
603 #if defined(MAGICKCORE_OPENMP_SUPPORT)
604 #pragma omp parallel for schedule(static,4) shared(status) \
605 magick_threads(image,image,number_grays,1)
607 for (i=0; i < 4; i++)
612 for (y=0; y < (ssize_t) number_grays; y++)
617 for (x=0; x < (ssize_t) number_grays; x++)
620 Angular second moment: measure of homogeneity of the image.
622 channel_features[RedPixelChannel].angular_second_moment[i]+=
623 cooccurrence[x][y].direction[i].red*
624 cooccurrence[x][y].direction[i].red;
625 channel_features[GreenPixelChannel].angular_second_moment[i]+=
626 cooccurrence[x][y].direction[i].green*
627 cooccurrence[x][y].direction[i].green;
628 channel_features[BluePixelChannel].angular_second_moment[i]+=
629 cooccurrence[x][y].direction[i].blue*
630 cooccurrence[x][y].direction[i].blue;
631 if (image->colorspace == CMYKColorspace)
632 channel_features[BlackPixelChannel].angular_second_moment[i]+=
633 cooccurrence[x][y].direction[i].black*
634 cooccurrence[x][y].direction[i].black;
635 if (image->alpha_trait == BlendPixelTrait)
636 channel_features[AlphaPixelChannel].angular_second_moment[i]+=
637 cooccurrence[x][y].direction[i].alpha*
638 cooccurrence[x][y].direction[i].alpha;
640 Correlation: measure of linear-dependencies in the image.
642 sum[y].direction[i].red+=cooccurrence[x][y].direction[i].red;
643 sum[y].direction[i].green+=cooccurrence[x][y].direction[i].green;
644 sum[y].direction[i].blue+=cooccurrence[x][y].direction[i].blue;
645 if (image->colorspace == CMYKColorspace)
646 sum[y].direction[i].black+=cooccurrence[x][y].direction[i].black;
647 if (image->alpha_trait == BlendPixelTrait)
648 sum[y].direction[i].alpha+=cooccurrence[x][y].direction[i].alpha;
649 correlation.direction[i].red+=x*y*cooccurrence[x][y].direction[i].red;
650 correlation.direction[i].green+=x*y*
651 cooccurrence[x][y].direction[i].green;
652 correlation.direction[i].blue+=x*y*
653 cooccurrence[x][y].direction[i].blue;
654 if (image->colorspace == CMYKColorspace)
655 correlation.direction[i].black+=x*y*
656 cooccurrence[x][y].direction[i].black;
657 if (image->alpha_trait == BlendPixelTrait)
658 correlation.direction[i].alpha+=x*y*
659 cooccurrence[x][y].direction[i].alpha;
661 Inverse Difference Moment.
663 channel_features[RedPixelChannel].inverse_difference_moment[i]+=
664 cooccurrence[x][y].direction[i].red/((y-x)*(y-x)+1);
665 channel_features[GreenPixelChannel].inverse_difference_moment[i]+=
666 cooccurrence[x][y].direction[i].green/((y-x)*(y-x)+1);
667 channel_features[BluePixelChannel].inverse_difference_moment[i]+=
668 cooccurrence[x][y].direction[i].blue/((y-x)*(y-x)+1);
669 if (image->colorspace == CMYKColorspace)
670 channel_features[BlackPixelChannel].inverse_difference_moment[i]+=
671 cooccurrence[x][y].direction[i].black/((y-x)*(y-x)+1);
672 if (image->alpha_trait == BlendPixelTrait)
673 channel_features[AlphaPixelChannel].inverse_difference_moment[i]+=
674 cooccurrence[x][y].direction[i].alpha/((y-x)*(y-x)+1);
678 density_xy[y+x+2].direction[i].red+=
679 cooccurrence[x][y].direction[i].red;
680 density_xy[y+x+2].direction[i].green+=
681 cooccurrence[x][y].direction[i].green;
682 density_xy[y+x+2].direction[i].blue+=
683 cooccurrence[x][y].direction[i].blue;
684 if (image->colorspace == CMYKColorspace)
685 density_xy[y+x+2].direction[i].black+=
686 cooccurrence[x][y].direction[i].black;
687 if (image->alpha_trait == BlendPixelTrait)
688 density_xy[y+x+2].direction[i].alpha+=
689 cooccurrence[x][y].direction[i].alpha;
693 channel_features[RedPixelChannel].entropy[i]-=
694 cooccurrence[x][y].direction[i].red*
695 MagickLog10(cooccurrence[x][y].direction[i].red);
696 channel_features[GreenPixelChannel].entropy[i]-=
697 cooccurrence[x][y].direction[i].green*
698 MagickLog10(cooccurrence[x][y].direction[i].green);
699 channel_features[BluePixelChannel].entropy[i]-=
700 cooccurrence[x][y].direction[i].blue*
701 MagickLog10(cooccurrence[x][y].direction[i].blue);
702 if (image->colorspace == CMYKColorspace)
703 channel_features[BlackPixelChannel].entropy[i]-=
704 cooccurrence[x][y].direction[i].black*
705 MagickLog10(cooccurrence[x][y].direction[i].black);
706 if (image->alpha_trait == BlendPixelTrait)
707 channel_features[AlphaPixelChannel].entropy[i]-=
708 cooccurrence[x][y].direction[i].alpha*
709 MagickLog10(cooccurrence[x][y].direction[i].alpha);
711 Information Measures of Correlation.
713 density_x[x].direction[i].red+=cooccurrence[x][y].direction[i].red;
714 density_x[x].direction[i].green+=cooccurrence[x][y].direction[i].green;
715 density_x[x].direction[i].blue+=cooccurrence[x][y].direction[i].blue;
716 if (image->alpha_trait == BlendPixelTrait)
717 density_x[x].direction[i].alpha+=
718 cooccurrence[x][y].direction[i].alpha;
719 if (image->colorspace == CMYKColorspace)
720 density_x[x].direction[i].black+=
721 cooccurrence[x][y].direction[i].black;
722 density_y[y].direction[i].red+=cooccurrence[x][y].direction[i].red;
723 density_y[y].direction[i].green+=cooccurrence[x][y].direction[i].green;
724 density_y[y].direction[i].blue+=cooccurrence[x][y].direction[i].blue;
725 if (image->colorspace == CMYKColorspace)
726 density_y[y].direction[i].black+=
727 cooccurrence[x][y].direction[i].black;
728 if (image->alpha_trait == BlendPixelTrait)
729 density_y[y].direction[i].alpha+=
730 cooccurrence[x][y].direction[i].alpha;
732 mean.direction[i].red+=y*sum[y].direction[i].red;
733 sum_squares.direction[i].red+=y*y*sum[y].direction[i].red;
734 mean.direction[i].green+=y*sum[y].direction[i].green;
735 sum_squares.direction[i].green+=y*y*sum[y].direction[i].green;
736 mean.direction[i].blue+=y*sum[y].direction[i].blue;
737 sum_squares.direction[i].blue+=y*y*sum[y].direction[i].blue;
738 if (image->colorspace == CMYKColorspace)
740 mean.direction[i].black+=y*sum[y].direction[i].black;
741 sum_squares.direction[i].black+=y*y*sum[y].direction[i].black;
743 if (image->alpha_trait == BlendPixelTrait)
745 mean.direction[i].alpha+=y*sum[y].direction[i].alpha;
746 sum_squares.direction[i].alpha+=y*y*sum[y].direction[i].alpha;
750 Correlation: measure of linear-dependencies in the image.
752 channel_features[RedPixelChannel].correlation[i]=
753 (correlation.direction[i].red-mean.direction[i].red*
754 mean.direction[i].red)/(sqrt(sum_squares.direction[i].red-
755 (mean.direction[i].red*mean.direction[i].red))*sqrt(
756 sum_squares.direction[i].red-(mean.direction[i].red*
757 mean.direction[i].red)));
758 channel_features[GreenPixelChannel].correlation[i]=
759 (correlation.direction[i].green-mean.direction[i].green*
760 mean.direction[i].green)/(sqrt(sum_squares.direction[i].green-
761 (mean.direction[i].green*mean.direction[i].green))*sqrt(
762 sum_squares.direction[i].green-(mean.direction[i].green*
763 mean.direction[i].green)));
764 channel_features[BluePixelChannel].correlation[i]=
765 (correlation.direction[i].blue-mean.direction[i].blue*
766 mean.direction[i].blue)/(sqrt(sum_squares.direction[i].blue-
767 (mean.direction[i].blue*mean.direction[i].blue))*sqrt(
768 sum_squares.direction[i].blue-(mean.direction[i].blue*
769 mean.direction[i].blue)));
770 if (image->colorspace == CMYKColorspace)
771 channel_features[BlackPixelChannel].correlation[i]=
772 (correlation.direction[i].black-mean.direction[i].black*
773 mean.direction[i].black)/(sqrt(sum_squares.direction[i].black-
774 (mean.direction[i].black*mean.direction[i].black))*sqrt(
775 sum_squares.direction[i].black-(mean.direction[i].black*
776 mean.direction[i].black)));
777 if (image->alpha_trait == BlendPixelTrait)
778 channel_features[AlphaPixelChannel].correlation[i]=
779 (correlation.direction[i].alpha-mean.direction[i].alpha*
780 mean.direction[i].alpha)/(sqrt(sum_squares.direction[i].alpha-
781 (mean.direction[i].alpha*mean.direction[i].alpha))*sqrt(
782 sum_squares.direction[i].alpha-(mean.direction[i].alpha*
783 mean.direction[i].alpha)));
786 Compute more texture features.
788 #if defined(MAGICKCORE_OPENMP_SUPPORT)
789 #pragma omp parallel for schedule(static,4) shared(status) \
790 magick_threads(image,image,number_grays,1)
792 for (i=0; i < 4; i++)
797 for (x=2; x < (ssize_t) (2*number_grays); x++)
802 channel_features[RedPixelChannel].sum_average[i]+=
803 x*density_xy[x].direction[i].red;
804 channel_features[GreenPixelChannel].sum_average[i]+=
805 x*density_xy[x].direction[i].green;
806 channel_features[BluePixelChannel].sum_average[i]+=
807 x*density_xy[x].direction[i].blue;
808 if (image->colorspace == CMYKColorspace)
809 channel_features[BlackPixelChannel].sum_average[i]+=
810 x*density_xy[x].direction[i].black;
811 if (image->alpha_trait == BlendPixelTrait)
812 channel_features[AlphaPixelChannel].sum_average[i]+=
813 x*density_xy[x].direction[i].alpha;
817 channel_features[RedPixelChannel].sum_entropy[i]-=
818 density_xy[x].direction[i].red*
819 MagickLog10(density_xy[x].direction[i].red);
820 channel_features[GreenPixelChannel].sum_entropy[i]-=
821 density_xy[x].direction[i].green*
822 MagickLog10(density_xy[x].direction[i].green);
823 channel_features[BluePixelChannel].sum_entropy[i]-=
824 density_xy[x].direction[i].blue*
825 MagickLog10(density_xy[x].direction[i].blue);
826 if (image->colorspace == CMYKColorspace)
827 channel_features[BlackPixelChannel].sum_entropy[i]-=
828 density_xy[x].direction[i].black*
829 MagickLog10(density_xy[x].direction[i].black);
830 if (image->alpha_trait == BlendPixelTrait)
831 channel_features[AlphaPixelChannel].sum_entropy[i]-=
832 density_xy[x].direction[i].alpha*
833 MagickLog10(density_xy[x].direction[i].alpha);
837 channel_features[RedPixelChannel].sum_variance[i]+=
838 (x-channel_features[RedPixelChannel].sum_entropy[i])*
839 (x-channel_features[RedPixelChannel].sum_entropy[i])*
840 density_xy[x].direction[i].red;
841 channel_features[GreenPixelChannel].sum_variance[i]+=
842 (x-channel_features[GreenPixelChannel].sum_entropy[i])*
843 (x-channel_features[GreenPixelChannel].sum_entropy[i])*
844 density_xy[x].direction[i].green;
845 channel_features[BluePixelChannel].sum_variance[i]+=
846 (x-channel_features[BluePixelChannel].sum_entropy[i])*
847 (x-channel_features[BluePixelChannel].sum_entropy[i])*
848 density_xy[x].direction[i].blue;
849 if (image->colorspace == CMYKColorspace)
850 channel_features[BlackPixelChannel].sum_variance[i]+=
851 (x-channel_features[BlackPixelChannel].sum_entropy[i])*
852 (x-channel_features[BlackPixelChannel].sum_entropy[i])*
853 density_xy[x].direction[i].black;
854 if (image->alpha_trait == BlendPixelTrait)
855 channel_features[AlphaPixelChannel].sum_variance[i]+=
856 (x-channel_features[AlphaPixelChannel].sum_entropy[i])*
857 (x-channel_features[AlphaPixelChannel].sum_entropy[i])*
858 density_xy[x].direction[i].alpha;
862 Compute more texture features.
864 #if defined(MAGICKCORE_OPENMP_SUPPORT)
865 #pragma omp parallel for schedule(static,4) shared(status) \
866 magick_threads(image,image,number_grays,1)
868 for (i=0; i < 4; i++)
873 for (y=0; y < (ssize_t) number_grays; y++)
878 for (x=0; x < (ssize_t) number_grays; x++)
881 Sum of Squares: Variance
883 variance.direction[i].red+=(y-mean.direction[i].red+1)*
884 (y-mean.direction[i].red+1)*cooccurrence[x][y].direction[i].red;
885 variance.direction[i].green+=(y-mean.direction[i].green+1)*
886 (y-mean.direction[i].green+1)*cooccurrence[x][y].direction[i].green;
887 variance.direction[i].blue+=(y-mean.direction[i].blue+1)*
888 (y-mean.direction[i].blue+1)*cooccurrence[x][y].direction[i].blue;
889 if (image->colorspace == CMYKColorspace)
890 variance.direction[i].black+=(y-mean.direction[i].black+1)*
891 (y-mean.direction[i].black+1)*cooccurrence[x][y].direction[i].black;
892 if (image->alpha_trait == BlendPixelTrait)
893 variance.direction[i].alpha+=(y-mean.direction[i].alpha+1)*
894 (y-mean.direction[i].alpha+1)*
895 cooccurrence[x][y].direction[i].alpha;
897 Sum average / Difference Variance.
899 density_xy[MagickAbsoluteValue(y-x)].direction[i].red+=
900 cooccurrence[x][y].direction[i].red;
901 density_xy[MagickAbsoluteValue(y-x)].direction[i].green+=
902 cooccurrence[x][y].direction[i].green;
903 density_xy[MagickAbsoluteValue(y-x)].direction[i].blue+=
904 cooccurrence[x][y].direction[i].blue;
905 if (image->colorspace == CMYKColorspace)
906 density_xy[MagickAbsoluteValue(y-x)].direction[i].black+=
907 cooccurrence[x][y].direction[i].black;
908 if (image->alpha_trait == BlendPixelTrait)
909 density_xy[MagickAbsoluteValue(y-x)].direction[i].alpha+=
910 cooccurrence[x][y].direction[i].alpha;
912 Information Measures of Correlation.
914 entropy_xy.direction[i].red-=cooccurrence[x][y].direction[i].red*
915 MagickLog10(cooccurrence[x][y].direction[i].red);
916 entropy_xy.direction[i].green-=cooccurrence[x][y].direction[i].green*
917 MagickLog10(cooccurrence[x][y].direction[i].green);
918 entropy_xy.direction[i].blue-=cooccurrence[x][y].direction[i].blue*
919 MagickLog10(cooccurrence[x][y].direction[i].blue);
920 if (image->colorspace == CMYKColorspace)
921 entropy_xy.direction[i].black-=cooccurrence[x][y].direction[i].black*
922 MagickLog10(cooccurrence[x][y].direction[i].black);
923 if (image->alpha_trait == BlendPixelTrait)
924 entropy_xy.direction[i].alpha-=
925 cooccurrence[x][y].direction[i].alpha*MagickLog10(
926 cooccurrence[x][y].direction[i].alpha);
927 entropy_xy1.direction[i].red-=(cooccurrence[x][y].direction[i].red*
928 MagickLog10(density_x[x].direction[i].red*density_y[y].direction[i].red));
929 entropy_xy1.direction[i].green-=(cooccurrence[x][y].direction[i].green*
930 MagickLog10(density_x[x].direction[i].green*
931 density_y[y].direction[i].green));
932 entropy_xy1.direction[i].blue-=(cooccurrence[x][y].direction[i].blue*
933 MagickLog10(density_x[x].direction[i].blue*density_y[y].direction[i].blue));
934 if (image->colorspace == CMYKColorspace)
935 entropy_xy1.direction[i].black-=(
936 cooccurrence[x][y].direction[i].black*MagickLog10(
937 density_x[x].direction[i].black*density_y[y].direction[i].black));
938 if (image->alpha_trait == BlendPixelTrait)
939 entropy_xy1.direction[i].alpha-=(
940 cooccurrence[x][y].direction[i].alpha*MagickLog10(
941 density_x[x].direction[i].alpha*density_y[y].direction[i].alpha));
942 entropy_xy2.direction[i].red-=(density_x[x].direction[i].red*
943 density_y[y].direction[i].red*MagickLog10(density_x[x].direction[i].red*
944 density_y[y].direction[i].red));
945 entropy_xy2.direction[i].green-=(density_x[x].direction[i].green*
946 density_y[y].direction[i].green*MagickLog10(density_x[x].direction[i].green*
947 density_y[y].direction[i].green));
948 entropy_xy2.direction[i].blue-=(density_x[x].direction[i].blue*
949 density_y[y].direction[i].blue*MagickLog10(density_x[x].direction[i].blue*
950 density_y[y].direction[i].blue));
951 if (image->colorspace == CMYKColorspace)
952 entropy_xy2.direction[i].black-=(density_x[x].direction[i].black*
953 density_y[y].direction[i].black*MagickLog10(
954 density_x[x].direction[i].black*density_y[y].direction[i].black));
955 if (image->alpha_trait == BlendPixelTrait)
956 entropy_xy2.direction[i].alpha-=(density_x[x].direction[i].alpha*
957 density_y[y].direction[i].alpha*MagickLog10(
958 density_x[x].direction[i].alpha*density_y[y].direction[i].alpha));
961 channel_features[RedPixelChannel].variance_sum_of_squares[i]=
962 variance.direction[i].red;
963 channel_features[GreenPixelChannel].variance_sum_of_squares[i]=
964 variance.direction[i].green;
965 channel_features[BluePixelChannel].variance_sum_of_squares[i]=
966 variance.direction[i].blue;
967 if (image->colorspace == CMYKColorspace)
968 channel_features[BlackPixelChannel].variance_sum_of_squares[i]=
969 variance.direction[i].black;
970 if (image->alpha_trait == BlendPixelTrait)
971 channel_features[AlphaPixelChannel].variance_sum_of_squares[i]=
972 variance.direction[i].alpha;
975 Compute more texture features.
977 (void) ResetMagickMemory(&variance,0,sizeof(variance));
978 (void) ResetMagickMemory(&sum_squares,0,sizeof(sum_squares));
979 #if defined(MAGICKCORE_OPENMP_SUPPORT)
980 #pragma omp parallel for schedule(static,4) shared(status) \
981 magick_threads(image,image,number_grays,1)
983 for (i=0; i < 4; i++)
988 for (x=0; x < (ssize_t) number_grays; x++)
993 variance.direction[i].red+=density_xy[x].direction[i].red;
994 variance.direction[i].green+=density_xy[x].direction[i].green;
995 variance.direction[i].blue+=density_xy[x].direction[i].blue;
996 if (image->colorspace == CMYKColorspace)
997 variance.direction[i].black+=density_xy[x].direction[i].black;
998 if (image->alpha_trait == BlendPixelTrait)
999 variance.direction[i].alpha+=density_xy[x].direction[i].alpha;
1000 sum_squares.direction[i].red+=density_xy[x].direction[i].red*
1001 density_xy[x].direction[i].red;
1002 sum_squares.direction[i].green+=density_xy[x].direction[i].green*
1003 density_xy[x].direction[i].green;
1004 sum_squares.direction[i].blue+=density_xy[x].direction[i].blue*
1005 density_xy[x].direction[i].blue;
1006 if (image->colorspace == CMYKColorspace)
1007 sum_squares.direction[i].black+=density_xy[x].direction[i].black*
1008 density_xy[x].direction[i].black;
1009 if (image->alpha_trait == BlendPixelTrait)
1010 sum_squares.direction[i].alpha+=density_xy[x].direction[i].alpha*
1011 density_xy[x].direction[i].alpha;
1015 channel_features[RedPixelChannel].difference_entropy[i]-=
1016 density_xy[x].direction[i].red*
1017 MagickLog10(density_xy[x].direction[i].red);
1018 channel_features[GreenPixelChannel].difference_entropy[i]-=
1019 density_xy[x].direction[i].green*
1020 MagickLog10(density_xy[x].direction[i].green);
1021 channel_features[BluePixelChannel].difference_entropy[i]-=
1022 density_xy[x].direction[i].blue*
1023 MagickLog10(density_xy[x].direction[i].blue);
1024 if (image->colorspace == CMYKColorspace)
1025 channel_features[BlackPixelChannel].difference_entropy[i]-=
1026 density_xy[x].direction[i].black*
1027 MagickLog10(density_xy[x].direction[i].black);
1028 if (image->alpha_trait == BlendPixelTrait)
1029 channel_features[AlphaPixelChannel].difference_entropy[i]-=
1030 density_xy[x].direction[i].alpha*
1031 MagickLog10(density_xy[x].direction[i].alpha);
1033 Information Measures of Correlation.
1035 entropy_x.direction[i].red-=(density_x[x].direction[i].red*
1036 MagickLog10(density_x[x].direction[i].red));
1037 entropy_x.direction[i].green-=(density_x[x].direction[i].green*
1038 MagickLog10(density_x[x].direction[i].green));
1039 entropy_x.direction[i].blue-=(density_x[x].direction[i].blue*
1040 MagickLog10(density_x[x].direction[i].blue));
1041 if (image->colorspace == CMYKColorspace)
1042 entropy_x.direction[i].black-=(density_x[x].direction[i].black*
1043 MagickLog10(density_x[x].direction[i].black));
1044 if (image->alpha_trait == BlendPixelTrait)
1045 entropy_x.direction[i].alpha-=(density_x[x].direction[i].alpha*
1046 MagickLog10(density_x[x].direction[i].alpha));
1047 entropy_y.direction[i].red-=(density_y[x].direction[i].red*
1048 MagickLog10(density_y[x].direction[i].red));
1049 entropy_y.direction[i].green-=(density_y[x].direction[i].green*
1050 MagickLog10(density_y[x].direction[i].green));
1051 entropy_y.direction[i].blue-=(density_y[x].direction[i].blue*
1052 MagickLog10(density_y[x].direction[i].blue));
1053 if (image->colorspace == CMYKColorspace)
1054 entropy_y.direction[i].black-=(density_y[x].direction[i].black*
1055 MagickLog10(density_y[x].direction[i].black));
1056 if (image->alpha_trait == BlendPixelTrait)
1057 entropy_y.direction[i].alpha-=(density_y[x].direction[i].alpha*
1058 MagickLog10(density_y[x].direction[i].alpha));
1061 Difference variance.
1063 channel_features[RedPixelChannel].difference_variance[i]=
1064 (((double) number_grays*number_grays*sum_squares.direction[i].red)-
1065 (variance.direction[i].red*variance.direction[i].red))/
1066 ((double) number_grays*number_grays*number_grays*number_grays);
1067 channel_features[GreenPixelChannel].difference_variance[i]=
1068 (((double) number_grays*number_grays*sum_squares.direction[i].green)-
1069 (variance.direction[i].green*variance.direction[i].green))/
1070 ((double) number_grays*number_grays*number_grays*number_grays);
1071 channel_features[BluePixelChannel].difference_variance[i]=
1072 (((double) number_grays*number_grays*sum_squares.direction[i].blue)-
1073 (variance.direction[i].blue*variance.direction[i].blue))/
1074 ((double) number_grays*number_grays*number_grays*number_grays);
1075 if (image->colorspace == CMYKColorspace)
1076 channel_features[BlackPixelChannel].difference_variance[i]=
1077 (((double) number_grays*number_grays*sum_squares.direction[i].black)-
1078 (variance.direction[i].black*variance.direction[i].black))/
1079 ((double) number_grays*number_grays*number_grays*number_grays);
1080 if (image->alpha_trait == BlendPixelTrait)
1081 channel_features[AlphaPixelChannel].difference_variance[i]=
1082 (((double) number_grays*number_grays*sum_squares.direction[i].alpha)-
1083 (variance.direction[i].alpha*variance.direction[i].alpha))/
1084 ((double) number_grays*number_grays*number_grays*number_grays);
1086 Information Measures of Correlation.
1088 channel_features[RedPixelChannel].measure_of_correlation_1[i]=
1089 (entropy_xy.direction[i].red-entropy_xy1.direction[i].red)/
1090 (entropy_x.direction[i].red > entropy_y.direction[i].red ?
1091 entropy_x.direction[i].red : entropy_y.direction[i].red);
1092 channel_features[GreenPixelChannel].measure_of_correlation_1[i]=
1093 (entropy_xy.direction[i].green-entropy_xy1.direction[i].green)/
1094 (entropy_x.direction[i].green > entropy_y.direction[i].green ?
1095 entropy_x.direction[i].green : entropy_y.direction[i].green);
1096 channel_features[BluePixelChannel].measure_of_correlation_1[i]=
1097 (entropy_xy.direction[i].blue-entropy_xy1.direction[i].blue)/
1098 (entropy_x.direction[i].blue > entropy_y.direction[i].blue ?
1099 entropy_x.direction[i].blue : entropy_y.direction[i].blue);
1100 if (image->colorspace == CMYKColorspace)
1101 channel_features[BlackPixelChannel].measure_of_correlation_1[i]=
1102 (entropy_xy.direction[i].black-entropy_xy1.direction[i].black)/
1103 (entropy_x.direction[i].black > entropy_y.direction[i].black ?
1104 entropy_x.direction[i].black : entropy_y.direction[i].black);
1105 if (image->alpha_trait == BlendPixelTrait)
1106 channel_features[AlphaPixelChannel].measure_of_correlation_1[i]=
1107 (entropy_xy.direction[i].alpha-entropy_xy1.direction[i].alpha)/
1108 (entropy_x.direction[i].alpha > entropy_y.direction[i].alpha ?
1109 entropy_x.direction[i].alpha : entropy_y.direction[i].alpha);
1110 channel_features[RedPixelChannel].measure_of_correlation_2[i]=
1111 (sqrt(fabs(1.0-exp(-2.0*(entropy_xy2.direction[i].red-
1112 entropy_xy.direction[i].red)))));
1113 channel_features[GreenPixelChannel].measure_of_correlation_2[i]=
1114 (sqrt(fabs(1.0-exp(-2.0*(entropy_xy2.direction[i].green-
1115 entropy_xy.direction[i].green)))));
1116 channel_features[BluePixelChannel].measure_of_correlation_2[i]=
1117 (sqrt(fabs(1.0-exp(-2.0*(entropy_xy2.direction[i].blue-
1118 entropy_xy.direction[i].blue)))));
1119 if (image->colorspace == CMYKColorspace)
1120 channel_features[BlackPixelChannel].measure_of_correlation_2[i]=
1121 (sqrt(fabs(1.0-exp(-2.0*(entropy_xy2.direction[i].black-
1122 entropy_xy.direction[i].black)))));
1123 if (image->alpha_trait == BlendPixelTrait)
1124 channel_features[AlphaPixelChannel].measure_of_correlation_2[i]=
1125 (sqrt(fabs(1.0-exp(-2.0*(entropy_xy2.direction[i].alpha-
1126 entropy_xy.direction[i].alpha)))));
1129 Compute more texture features.
1131 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1132 #pragma omp parallel for schedule(static,4) shared(status) \
1133 magick_threads(image,image,number_grays,1)
1135 for (i=0; i < 4; i++)
1140 for (z=0; z < (ssize_t) number_grays; z++)
1148 (void) ResetMagickMemory(&pixel,0,sizeof(pixel));
1149 for (y=0; y < (ssize_t) number_grays; y++)
1154 for (x=0; x < (ssize_t) number_grays; x++)
1157 Contrast: amount of local variations present in an image.
1159 if (((y-x) == z) || ((x-y) == z))
1161 pixel.direction[i].red+=cooccurrence[x][y].direction[i].red;
1162 pixel.direction[i].green+=cooccurrence[x][y].direction[i].green;
1163 pixel.direction[i].blue+=cooccurrence[x][y].direction[i].blue;
1164 if (image->colorspace == CMYKColorspace)
1165 pixel.direction[i].black+=cooccurrence[x][y].direction[i].black;
1166 if (image->alpha_trait == BlendPixelTrait)
1167 pixel.direction[i].alpha+=
1168 cooccurrence[x][y].direction[i].alpha;
1171 Maximum Correlation Coefficient.
1173 Q[z][y].direction[i].red+=cooccurrence[z][x].direction[i].red*
1174 cooccurrence[y][x].direction[i].red/density_x[z].direction[i].red/
1175 density_y[x].direction[i].red;
1176 Q[z][y].direction[i].green+=cooccurrence[z][x].direction[i].green*
1177 cooccurrence[y][x].direction[i].green/
1178 density_x[z].direction[i].green/density_y[x].direction[i].red;
1179 Q[z][y].direction[i].blue+=cooccurrence[z][x].direction[i].blue*
1180 cooccurrence[y][x].direction[i].blue/density_x[z].direction[i].blue/
1181 density_y[x].direction[i].blue;
1182 if (image->colorspace == CMYKColorspace)
1183 Q[z][y].direction[i].black+=cooccurrence[z][x].direction[i].black*
1184 cooccurrence[y][x].direction[i].black/
1185 density_x[z].direction[i].black/density_y[x].direction[i].black;
1186 if (image->alpha_trait == BlendPixelTrait)
1187 Q[z][y].direction[i].alpha+=
1188 cooccurrence[z][x].direction[i].alpha*
1189 cooccurrence[y][x].direction[i].alpha/
1190 density_x[z].direction[i].alpha/
1191 density_y[x].direction[i].alpha;
1194 channel_features[RedPixelChannel].contrast[i]+=z*z*
1195 pixel.direction[i].red;
1196 channel_features[GreenPixelChannel].contrast[i]+=z*z*
1197 pixel.direction[i].green;
1198 channel_features[BluePixelChannel].contrast[i]+=z*z*
1199 pixel.direction[i].blue;
1200 if (image->colorspace == CMYKColorspace)
1201 channel_features[BlackPixelChannel].contrast[i]+=z*z*
1202 pixel.direction[i].black;
1203 if (image->alpha_trait == BlendPixelTrait)
1204 channel_features[AlphaPixelChannel].contrast[i]+=z*z*
1205 pixel.direction[i].alpha;
1208 Maximum Correlation Coefficient.
1209 Future: return second largest eigenvalue of Q.
1211 channel_features[RedPixelChannel].maximum_correlation_coefficient[i]=
1212 sqrt((double) -1.0);
1213 channel_features[GreenPixelChannel].maximum_correlation_coefficient[i]=
1214 sqrt((double) -1.0);
1215 channel_features[BluePixelChannel].maximum_correlation_coefficient[i]=
1216 sqrt((double) -1.0);
1217 if (image->colorspace == CMYKColorspace)
1218 channel_features[BlackPixelChannel].maximum_correlation_coefficient[i]=
1219 sqrt((double) -1.0);
1220 if (image->alpha_trait == BlendPixelTrait)
1221 channel_features[AlphaPixelChannel].maximum_correlation_coefficient[i]=
1222 sqrt((double) -1.0);
1225 Relinquish resources.
1227 sum=(ChannelStatistics *) RelinquishMagickMemory(sum);
1228 for (i=0; i < (ssize_t) number_grays; i++)
1229 Q[i]=(ChannelStatistics *) RelinquishMagickMemory(Q[i]);
1230 Q=(ChannelStatistics **) RelinquishMagickMemory(Q);
1231 density_y=(ChannelStatistics *) RelinquishMagickMemory(density_y);
1232 density_xy=(ChannelStatistics *) RelinquishMagickMemory(density_xy);
1233 density_x=(ChannelStatistics *) RelinquishMagickMemory(density_x);
1234 for (i=0; i < (ssize_t) number_grays; i++)
1235 cooccurrence[i]=(ChannelStatistics *)
1236 RelinquishMagickMemory(cooccurrence[i]);
1237 cooccurrence=(ChannelStatistics **) RelinquishMagickMemory(cooccurrence);
1238 return(channel_features);