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-2012 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/segment.h"
84 #include "MagickCore/semaphore.h"
85 #include "MagickCore/signature-private.h"
86 #include "MagickCore/string_.h"
87 #include "MagickCore/thread-private.h"
88 #include "MagickCore/timer.h"
89 #include "MagickCore/utility.h"
90 #include "MagickCore/version.h"
93 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
97 % G e t I m a g e F e a t u r e s %
101 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
103 % GetImageFeatures() returns features for each channel in the image in
104 % each of four directions (horizontal, vertical, left and right diagonals)
105 % for the specified distance. The features include the angular second
106 % moment, contrast, correlation, sum of squares: variance, inverse difference
107 % moment, sum average, sum varience, sum entropy, entropy, difference variance,% difference entropy, information measures of correlation 1, information
108 % measures of correlation 2, and maximum correlation coefficient. You can
109 % access the red channel contrast, for example, like this:
111 % channel_features=GetImageFeatures(image,1,exception);
112 % contrast=channel_features[RedPixelChannel].contrast[0];
114 % Use MagickRelinquishMemory() to free the features buffer.
116 % The format of the GetImageFeatures method is:
118 % ChannelFeatures *GetImageFeatures(const Image *image,
119 % const size_t distance,ExceptionInfo *exception)
121 % A description of each parameter follows:
123 % o image: the image.
125 % o distance: the distance.
127 % o exception: return any errors or warnings in this structure.
131 static inline ssize_t MagickAbsoluteValue(const ssize_t x)
138 MagickExport ChannelFeatures *GetImageFeatures(const Image *image,
139 const size_t distance,ExceptionInfo *exception)
141 typedef struct _ChannelStatistics
144 direction[4]; /* horizontal, vertical, left and right diagonals */
190 assert(image != (Image *) NULL);
191 assert(image->signature == MagickSignature);
192 if (image->debug != MagickFalse)
193 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
194 if ((image->columns < (distance+1)) || (image->rows < (distance+1)))
195 return((ChannelFeatures *) NULL);
196 length=CompositeChannels+1UL;
197 channel_features=(ChannelFeatures *) AcquireQuantumMemory(length,
198 sizeof(*channel_features));
199 if (channel_features == (ChannelFeatures *) NULL)
200 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
201 (void) ResetMagickMemory(channel_features,0,length*
202 sizeof(*channel_features));
206 grays=(PixelPacket *) AcquireQuantumMemory(MaxMap+1UL,sizeof(*grays));
207 if (grays == (PixelPacket *) NULL)
209 channel_features=(ChannelFeatures *) RelinquishMagickMemory(
211 (void) ThrowMagickException(exception,GetMagickModule(),
212 ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
213 return(channel_features);
215 for (i=0; i <= (ssize_t) MaxMap; i++)
218 grays[i].green=(~0U);
220 grays[i].alpha=(~0U);
221 grays[i].black=(~0U);
224 image_view=AcquireCacheView(image);
225 #if defined(MAGICKCORE_OPENMP_SUPPORT)
226 #pragma omp parallel for schedule(static,4) shared(status)
228 for (y=0; y < (ssize_t) image->rows; y++)
230 register const Quantum
236 if (status == MagickFalse)
238 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
239 if (p == (const Quantum *) NULL)
244 for (x=0; x < (ssize_t) image->columns; x++)
246 grays[ScaleQuantumToMap(GetPixelRed(image,p))].red=
247 ScaleQuantumToMap(GetPixelRed(image,p));
248 grays[ScaleQuantumToMap(GetPixelGreen(image,p))].green=
249 ScaleQuantumToMap(GetPixelGreen(image,p));
250 grays[ScaleQuantumToMap(GetPixelBlue(image,p))].blue=
251 ScaleQuantumToMap(GetPixelBlue(image,p));
252 if (image->colorspace == CMYKColorspace)
253 grays[ScaleQuantumToMap(GetPixelBlack(image,p))].black=
254 ScaleQuantumToMap(GetPixelBlack(image,p));
255 if (image->matte != MagickFalse)
256 grays[ScaleQuantumToMap(GetPixelAlpha(image,p))].alpha=
257 ScaleQuantumToMap(GetPixelAlpha(image,p));
258 p+=GetPixelChannels(image);
261 image_view=DestroyCacheView(image_view);
262 if (status == MagickFalse)
264 grays=(PixelPacket *) RelinquishMagickMemory(grays);
265 channel_features=(ChannelFeatures *) RelinquishMagickMemory(
267 return(channel_features);
269 (void) ResetMagickMemory(&gray,0,sizeof(gray));
270 for (i=0; i <= (ssize_t) MaxMap; i++)
272 if (grays[i].red != ~0U)
273 grays[gray.red++].red=grays[i].red;
274 if (grays[i].green != ~0U)
275 grays[gray.green++].green=grays[i].green;
276 if (grays[i].blue != ~0U)
277 grays[gray.blue++].blue=grays[i].blue;
278 if (image->colorspace == CMYKColorspace)
279 if (grays[i].black != ~0U)
280 grays[gray.black++].black=grays[i].black;
281 if (image->matte != MagickFalse)
282 if (grays[i].alpha != ~0U)
283 grays[gray.alpha++].alpha=grays[i].alpha;
286 Allocate spatial dependence matrix.
288 number_grays=gray.red;
289 if (gray.green > number_grays)
290 number_grays=gray.green;
291 if (gray.blue > number_grays)
292 number_grays=gray.blue;
293 if (image->colorspace == CMYKColorspace)
294 if (gray.black > number_grays)
295 number_grays=gray.black;
296 if (image->matte != MagickFalse)
297 if (gray.alpha > number_grays)
298 number_grays=gray.alpha;
299 cooccurrence=(ChannelStatistics **) AcquireQuantumMemory(number_grays,
300 sizeof(*cooccurrence));
301 density_x=(ChannelStatistics *) AcquireQuantumMemory(2*(number_grays+1),
303 density_xy=(ChannelStatistics *) AcquireQuantumMemory(2*(number_grays+1),
304 sizeof(*density_xy));
305 density_y=(ChannelStatistics *) AcquireQuantumMemory(2*(number_grays+1),
307 Q=(ChannelStatistics **) AcquireQuantumMemory(number_grays,sizeof(*Q));
308 sum=(ChannelStatistics *) AcquireQuantumMemory(number_grays,sizeof(*sum));
309 if ((cooccurrence == (ChannelStatistics **) NULL) ||
310 (density_x == (ChannelStatistics *) NULL) ||
311 (density_xy == (ChannelStatistics *) NULL) ||
312 (density_y == (ChannelStatistics *) NULL) ||
313 (Q == (ChannelStatistics **) NULL) ||
314 (sum == (ChannelStatistics *) NULL))
316 if (Q != (ChannelStatistics **) NULL)
318 for (i=0; i < (ssize_t) number_grays; i++)
319 Q[i]=(ChannelStatistics *) RelinquishMagickMemory(Q[i]);
320 Q=(ChannelStatistics **) RelinquishMagickMemory(Q);
322 if (sum != (ChannelStatistics *) NULL)
323 sum=(ChannelStatistics *) RelinquishMagickMemory(sum);
324 if (density_y != (ChannelStatistics *) NULL)
325 density_y=(ChannelStatistics *) RelinquishMagickMemory(density_y);
326 if (density_xy != (ChannelStatistics *) NULL)
327 density_xy=(ChannelStatistics *) RelinquishMagickMemory(density_xy);
328 if (density_x != (ChannelStatistics *) NULL)
329 density_x=(ChannelStatistics *) RelinquishMagickMemory(density_x);
330 if (cooccurrence != (ChannelStatistics **) NULL)
332 for (i=0; i < (ssize_t) number_grays; i++)
333 cooccurrence[i]=(ChannelStatistics *)
334 RelinquishMagickMemory(cooccurrence[i]);
335 cooccurrence=(ChannelStatistics **) RelinquishMagickMemory(
338 grays=(PixelPacket *) RelinquishMagickMemory(grays);
339 channel_features=(ChannelFeatures *) RelinquishMagickMemory(
341 (void) ThrowMagickException(exception,GetMagickModule(),
342 ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
343 return(channel_features);
345 (void) ResetMagickMemory(&correlation,0,sizeof(correlation));
346 (void) ResetMagickMemory(density_x,0,2*(number_grays+1)*sizeof(*density_x));
347 (void) ResetMagickMemory(density_xy,0,2*(number_grays+1)*sizeof(*density_xy));
348 (void) ResetMagickMemory(density_y,0,2*(number_grays+1)*sizeof(*density_y));
349 (void) ResetMagickMemory(&mean,0,sizeof(mean));
350 (void) ResetMagickMemory(sum,0,number_grays*sizeof(*sum));
351 (void) ResetMagickMemory(&sum_squares,0,sizeof(sum_squares));
352 (void) ResetMagickMemory(density_xy,0,2*number_grays*sizeof(*density_xy));
353 (void) ResetMagickMemory(&entropy_x,0,sizeof(entropy_x));
354 (void) ResetMagickMemory(&entropy_xy,0,sizeof(entropy_xy));
355 (void) ResetMagickMemory(&entropy_xy1,0,sizeof(entropy_xy1));
356 (void) ResetMagickMemory(&entropy_xy2,0,sizeof(entropy_xy2));
357 (void) ResetMagickMemory(&entropy_y,0,sizeof(entropy_y));
358 (void) ResetMagickMemory(&variance,0,sizeof(variance));
359 for (i=0; i < (ssize_t) number_grays; i++)
361 cooccurrence[i]=(ChannelStatistics *) AcquireQuantumMemory(number_grays,
362 sizeof(**cooccurrence));
363 Q[i]=(ChannelStatistics *) AcquireQuantumMemory(number_grays,sizeof(**Q));
364 if ((cooccurrence[i] == (ChannelStatistics *) NULL) ||
365 (Q[i] == (ChannelStatistics *) NULL))
367 (void) ResetMagickMemory(cooccurrence[i],0,number_grays*
368 sizeof(**cooccurrence));
369 (void) ResetMagickMemory(Q[i],0,number_grays*sizeof(**Q));
371 if (i < (ssize_t) number_grays)
373 for (i--; i >= 0; i--)
375 if (Q[i] != (ChannelStatistics *) NULL)
376 Q[i]=(ChannelStatistics *) RelinquishMagickMemory(Q[i]);
377 if (cooccurrence[i] != (ChannelStatistics *) NULL)
378 cooccurrence[i]=(ChannelStatistics *)
379 RelinquishMagickMemory(cooccurrence[i]);
381 Q=(ChannelStatistics **) RelinquishMagickMemory(Q);
382 cooccurrence=(ChannelStatistics **) RelinquishMagickMemory(cooccurrence);
383 sum=(ChannelStatistics *) RelinquishMagickMemory(sum);
384 density_y=(ChannelStatistics *) RelinquishMagickMemory(density_y);
385 density_xy=(ChannelStatistics *) RelinquishMagickMemory(density_xy);
386 density_x=(ChannelStatistics *) RelinquishMagickMemory(density_x);
387 grays=(PixelPacket *) RelinquishMagickMemory(grays);
388 channel_features=(ChannelFeatures *) RelinquishMagickMemory(
390 (void) ThrowMagickException(exception,GetMagickModule(),
391 ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
392 return(channel_features);
395 Initialize spatial dependence matrix.
398 image_view=AcquireCacheView(image);
399 for (y=0; y < (ssize_t) image->rows; y++)
401 register const Quantum
413 if (status == MagickFalse)
415 p=GetCacheViewVirtualPixels(image_view,-(ssize_t) distance,y,image->columns+
416 2*distance,distance+2,exception);
417 if (p == (const Quantum *) NULL)
422 p+=distance*GetPixelChannels(image);;
423 for (x=0; x < (ssize_t) image->columns; x++)
425 for (i=0; i < 4; i++)
433 Horizontal adjacency.
435 offset=(ssize_t) distance;
443 offset=(ssize_t) (image->columns+2*distance);
449 Right diagonal adjacency.
451 offset=(ssize_t) ((image->columns+2*distance)-distance);
457 Left diagonal adjacency.
459 offset=(ssize_t) ((image->columns+2*distance)+distance);
465 while (grays[u].red != ScaleQuantumToMap(GetPixelRed(image,p)))
467 while (grays[v].red != ScaleQuantumToMap(GetPixelRed(image,p+offset*GetPixelChannels(image))))
469 cooccurrence[u][v].direction[i].red++;
470 cooccurrence[v][u].direction[i].red++;
473 while (grays[u].green != ScaleQuantumToMap(GetPixelGreen(image,p)))
475 while (grays[v].green != ScaleQuantumToMap(GetPixelGreen(image,p+offset*GetPixelChannels(image))))
477 cooccurrence[u][v].direction[i].green++;
478 cooccurrence[v][u].direction[i].green++;
481 while (grays[u].blue != ScaleQuantumToMap(GetPixelBlue(image,p)))
483 while (grays[v].blue != ScaleQuantumToMap(GetPixelBlue(image,p+offset*GetPixelChannels(image))))
485 cooccurrence[u][v].direction[i].blue++;
486 cooccurrence[v][u].direction[i].blue++;
487 if (image->colorspace == CMYKColorspace)
491 while (grays[u].black != ScaleQuantumToMap(GetPixelBlack(image,p)))
493 while (grays[v].black != ScaleQuantumToMap(GetPixelBlack(image,p+offset*GetPixelChannels(image))))
495 cooccurrence[u][v].direction[i].black++;
496 cooccurrence[v][u].direction[i].black++;
498 if (image->matte != MagickFalse)
502 while (grays[u].alpha != ScaleQuantumToMap(GetPixelAlpha(image,p)))
504 while (grays[v].alpha != ScaleQuantumToMap(GetPixelAlpha(image,p+offset*GetPixelChannels(image))))
506 cooccurrence[u][v].direction[i].alpha++;
507 cooccurrence[v][u].direction[i].alpha++;
510 p+=GetPixelChannels(image);
513 grays=(PixelPacket *) RelinquishMagickMemory(grays);
514 image_view=DestroyCacheView(image_view);
515 if (status == MagickFalse)
517 for (i=0; i < (ssize_t) number_grays; i++)
518 cooccurrence[i]=(ChannelStatistics *)
519 RelinquishMagickMemory(cooccurrence[i]);
520 cooccurrence=(ChannelStatistics **) RelinquishMagickMemory(cooccurrence);
521 channel_features=(ChannelFeatures *) RelinquishMagickMemory(
523 (void) ThrowMagickException(exception,GetMagickModule(),
524 ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
525 return(channel_features);
528 Normalize spatial dependence matrix.
530 for (i=0; i < 4; i++)
544 Horizontal adjacency.
546 normalize=2.0*image->rows*(image->columns-distance);
554 normalize=2.0*(image->rows-distance)*image->columns;
560 Right diagonal adjacency.
562 normalize=2.0*(image->rows-distance)*(image->columns-distance);
568 Left diagonal adjacency.
570 normalize=2.0*(image->rows-distance)*(image->columns-distance);
574 normalize=1.0/(fabs((double) normalize) <= MagickEpsilon ? 1.0 : normalize);
575 for (y=0; y < (ssize_t) number_grays; y++)
580 for (x=0; x < (ssize_t) number_grays; x++)
582 cooccurrence[x][y].direction[i].red*=normalize;
583 cooccurrence[x][y].direction[i].green*=normalize;
584 cooccurrence[x][y].direction[i].blue*=normalize;
585 if (image->colorspace == CMYKColorspace)
586 cooccurrence[x][y].direction[i].black*=normalize;
587 if (image->matte != MagickFalse)
588 cooccurrence[x][y].direction[i].alpha*=normalize;
593 Compute texture features.
595 #if defined(MAGICKCORE_OPENMP_SUPPORT)
596 #pragma omp parallel for schedule(static,4) shared(status)
598 for (i=0; i < 4; i++)
603 for (y=0; y < (ssize_t) number_grays; y++)
608 for (x=0; x < (ssize_t) number_grays; x++)
611 Angular second moment: measure of homogeneity of the image.
613 channel_features[RedPixelChannel].angular_second_moment[i]+=
614 cooccurrence[x][y].direction[i].red*
615 cooccurrence[x][y].direction[i].red;
616 channel_features[GreenPixelChannel].angular_second_moment[i]+=
617 cooccurrence[x][y].direction[i].green*
618 cooccurrence[x][y].direction[i].green;
619 channel_features[BluePixelChannel].angular_second_moment[i]+=
620 cooccurrence[x][y].direction[i].blue*
621 cooccurrence[x][y].direction[i].blue;
622 if (image->colorspace == CMYKColorspace)
623 channel_features[BlackPixelChannel].angular_second_moment[i]+=
624 cooccurrence[x][y].direction[i].black*
625 cooccurrence[x][y].direction[i].black;
626 if (image->matte != MagickFalse)
627 channel_features[AlphaPixelChannel].angular_second_moment[i]+=
628 cooccurrence[x][y].direction[i].alpha*
629 cooccurrence[x][y].direction[i].alpha;
631 Correlation: measure of linear-dependencies in the image.
633 sum[y].direction[i].red+=cooccurrence[x][y].direction[i].red;
634 sum[y].direction[i].green+=cooccurrence[x][y].direction[i].green;
635 sum[y].direction[i].blue+=cooccurrence[x][y].direction[i].blue;
636 if (image->colorspace == CMYKColorspace)
637 sum[y].direction[i].black+=cooccurrence[x][y].direction[i].black;
638 if (image->matte != MagickFalse)
639 sum[y].direction[i].alpha+=cooccurrence[x][y].direction[i].alpha;
640 correlation.direction[i].red+=x*y*cooccurrence[x][y].direction[i].red;
641 correlation.direction[i].green+=x*y*
642 cooccurrence[x][y].direction[i].green;
643 correlation.direction[i].blue+=x*y*
644 cooccurrence[x][y].direction[i].blue;
645 if (image->colorspace == CMYKColorspace)
646 correlation.direction[i].black+=x*y*
647 cooccurrence[x][y].direction[i].black;
648 if (image->matte != MagickFalse)
649 correlation.direction[i].alpha+=x*y*
650 cooccurrence[x][y].direction[i].alpha;
652 Inverse Difference Moment.
654 channel_features[RedPixelChannel].inverse_difference_moment[i]+=
655 cooccurrence[x][y].direction[i].red/((y-x)*(y-x)+1);
656 channel_features[GreenPixelChannel].inverse_difference_moment[i]+=
657 cooccurrence[x][y].direction[i].green/((y-x)*(y-x)+1);
658 channel_features[BluePixelChannel].inverse_difference_moment[i]+=
659 cooccurrence[x][y].direction[i].blue/((y-x)*(y-x)+1);
660 if (image->colorspace == CMYKColorspace)
661 channel_features[BlackPixelChannel].inverse_difference_moment[i]+=
662 cooccurrence[x][y].direction[i].black/((y-x)*(y-x)+1);
663 if (image->matte != MagickFalse)
664 channel_features[AlphaPixelChannel].inverse_difference_moment[i]+=
665 cooccurrence[x][y].direction[i].alpha/((y-x)*(y-x)+1);
669 density_xy[y+x+2].direction[i].red+=
670 cooccurrence[x][y].direction[i].red;
671 density_xy[y+x+2].direction[i].green+=
672 cooccurrence[x][y].direction[i].green;
673 density_xy[y+x+2].direction[i].blue+=
674 cooccurrence[x][y].direction[i].blue;
675 if (image->colorspace == CMYKColorspace)
676 density_xy[y+x+2].direction[i].black+=
677 cooccurrence[x][y].direction[i].black;
678 if (image->matte != MagickFalse)
679 density_xy[y+x+2].direction[i].alpha+=
680 cooccurrence[x][y].direction[i].alpha;
684 channel_features[RedPixelChannel].entropy[i]-=
685 cooccurrence[x][y].direction[i].red*
686 log10(cooccurrence[x][y].direction[i].red+MagickEpsilon);
687 channel_features[GreenPixelChannel].entropy[i]-=
688 cooccurrence[x][y].direction[i].green*
689 log10(cooccurrence[x][y].direction[i].green+MagickEpsilon);
690 channel_features[BluePixelChannel].entropy[i]-=
691 cooccurrence[x][y].direction[i].blue*
692 log10(cooccurrence[x][y].direction[i].blue+MagickEpsilon);
693 if (image->colorspace == CMYKColorspace)
694 channel_features[BlackPixelChannel].entropy[i]-=
695 cooccurrence[x][y].direction[i].black*
696 log10(cooccurrence[x][y].direction[i].black+MagickEpsilon);
697 if (image->matte != MagickFalse)
698 channel_features[AlphaPixelChannel].entropy[i]-=
699 cooccurrence[x][y].direction[i].alpha*
700 log10(cooccurrence[x][y].direction[i].alpha+MagickEpsilon);
702 Information Measures of Correlation.
704 density_x[x].direction[i].red+=cooccurrence[x][y].direction[i].red;
705 density_x[x].direction[i].green+=cooccurrence[x][y].direction[i].green;
706 density_x[x].direction[i].blue+=cooccurrence[x][y].direction[i].blue;
707 if (image->matte != MagickFalse)
708 density_x[x].direction[i].alpha+=
709 cooccurrence[x][y].direction[i].alpha;
710 if (image->colorspace == CMYKColorspace)
711 density_x[x].direction[i].black+=
712 cooccurrence[x][y].direction[i].black;
713 density_y[y].direction[i].red+=cooccurrence[x][y].direction[i].red;
714 density_y[y].direction[i].green+=cooccurrence[x][y].direction[i].green;
715 density_y[y].direction[i].blue+=cooccurrence[x][y].direction[i].blue;
716 if (image->colorspace == CMYKColorspace)
717 density_y[y].direction[i].black+=
718 cooccurrence[x][y].direction[i].black;
719 if (image->matte != MagickFalse)
720 density_y[y].direction[i].alpha+=
721 cooccurrence[x][y].direction[i].alpha;
723 mean.direction[i].red+=y*sum[y].direction[i].red;
724 sum_squares.direction[i].red+=y*y*sum[y].direction[i].red;
725 mean.direction[i].green+=y*sum[y].direction[i].green;
726 sum_squares.direction[i].green+=y*y*sum[y].direction[i].green;
727 mean.direction[i].blue+=y*sum[y].direction[i].blue;
728 sum_squares.direction[i].blue+=y*y*sum[y].direction[i].blue;
729 if (image->colorspace == CMYKColorspace)
731 mean.direction[i].black+=y*sum[y].direction[i].black;
732 sum_squares.direction[i].black+=y*y*sum[y].direction[i].black;
734 if (image->matte != MagickFalse)
736 mean.direction[i].alpha+=y*sum[y].direction[i].alpha;
737 sum_squares.direction[i].alpha+=y*y*sum[y].direction[i].alpha;
741 Correlation: measure of linear-dependencies in the image.
743 channel_features[RedPixelChannel].correlation[i]=
744 (correlation.direction[i].red-mean.direction[i].red*
745 mean.direction[i].red)/(sqrt(sum_squares.direction[i].red-
746 (mean.direction[i].red*mean.direction[i].red))*sqrt(
747 sum_squares.direction[i].red-(mean.direction[i].red*
748 mean.direction[i].red)));
749 channel_features[GreenPixelChannel].correlation[i]=
750 (correlation.direction[i].green-mean.direction[i].green*
751 mean.direction[i].green)/(sqrt(sum_squares.direction[i].green-
752 (mean.direction[i].green*mean.direction[i].green))*sqrt(
753 sum_squares.direction[i].green-(mean.direction[i].green*
754 mean.direction[i].green)));
755 channel_features[BluePixelChannel].correlation[i]=
756 (correlation.direction[i].blue-mean.direction[i].blue*
757 mean.direction[i].blue)/(sqrt(sum_squares.direction[i].blue-
758 (mean.direction[i].blue*mean.direction[i].blue))*sqrt(
759 sum_squares.direction[i].blue-(mean.direction[i].blue*
760 mean.direction[i].blue)));
761 if (image->colorspace == CMYKColorspace)
762 channel_features[BlackPixelChannel].correlation[i]=
763 (correlation.direction[i].black-mean.direction[i].black*
764 mean.direction[i].black)/(sqrt(sum_squares.direction[i].black-
765 (mean.direction[i].black*mean.direction[i].black))*sqrt(
766 sum_squares.direction[i].black-(mean.direction[i].black*
767 mean.direction[i].black)));
768 if (image->matte != MagickFalse)
769 channel_features[AlphaPixelChannel].correlation[i]=
770 (correlation.direction[i].alpha-mean.direction[i].alpha*
771 mean.direction[i].alpha)/(sqrt(sum_squares.direction[i].alpha-
772 (mean.direction[i].alpha*mean.direction[i].alpha))*sqrt(
773 sum_squares.direction[i].alpha-(mean.direction[i].alpha*
774 mean.direction[i].alpha)));
777 Compute more texture features.
779 #if defined(MAGICKCORE_OPENMP_SUPPORT)
780 #pragma omp parallel for schedule(static,4) shared(status)
782 for (i=0; i < 4; i++)
787 for (x=2; x < (ssize_t) (2*number_grays); x++)
792 channel_features[RedPixelChannel].sum_average[i]+=
793 x*density_xy[x].direction[i].red;
794 channel_features[GreenPixelChannel].sum_average[i]+=
795 x*density_xy[x].direction[i].green;
796 channel_features[BluePixelChannel].sum_average[i]+=
797 x*density_xy[x].direction[i].blue;
798 if (image->colorspace == CMYKColorspace)
799 channel_features[BlackPixelChannel].sum_average[i]+=
800 x*density_xy[x].direction[i].black;
801 if (image->matte != MagickFalse)
802 channel_features[AlphaPixelChannel].sum_average[i]+=
803 x*density_xy[x].direction[i].alpha;
807 channel_features[RedPixelChannel].sum_entropy[i]-=
808 density_xy[x].direction[i].red*
809 log10(density_xy[x].direction[i].red+MagickEpsilon);
810 channel_features[GreenPixelChannel].sum_entropy[i]-=
811 density_xy[x].direction[i].green*
812 log10(density_xy[x].direction[i].green+MagickEpsilon);
813 channel_features[BluePixelChannel].sum_entropy[i]-=
814 density_xy[x].direction[i].blue*
815 log10(density_xy[x].direction[i].blue+MagickEpsilon);
816 if (image->colorspace == CMYKColorspace)
817 channel_features[BlackPixelChannel].sum_entropy[i]-=
818 density_xy[x].direction[i].black*
819 log10(density_xy[x].direction[i].black+MagickEpsilon);
820 if (image->matte != MagickFalse)
821 channel_features[AlphaPixelChannel].sum_entropy[i]-=
822 density_xy[x].direction[i].alpha*
823 log10(density_xy[x].direction[i].alpha+MagickEpsilon);
827 channel_features[RedPixelChannel].sum_variance[i]+=
828 (x-channel_features[RedPixelChannel].sum_entropy[i])*
829 (x-channel_features[RedPixelChannel].sum_entropy[i])*
830 density_xy[x].direction[i].red;
831 channel_features[GreenPixelChannel].sum_variance[i]+=
832 (x-channel_features[GreenPixelChannel].sum_entropy[i])*
833 (x-channel_features[GreenPixelChannel].sum_entropy[i])*
834 density_xy[x].direction[i].green;
835 channel_features[BluePixelChannel].sum_variance[i]+=
836 (x-channel_features[BluePixelChannel].sum_entropy[i])*
837 (x-channel_features[BluePixelChannel].sum_entropy[i])*
838 density_xy[x].direction[i].blue;
839 if (image->colorspace == CMYKColorspace)
840 channel_features[BlackPixelChannel].sum_variance[i]+=
841 (x-channel_features[BlackPixelChannel].sum_entropy[i])*
842 (x-channel_features[BlackPixelChannel].sum_entropy[i])*
843 density_xy[x].direction[i].black;
844 if (image->matte != MagickFalse)
845 channel_features[AlphaPixelChannel].sum_variance[i]+=
846 (x-channel_features[AlphaPixelChannel].sum_entropy[i])*
847 (x-channel_features[AlphaPixelChannel].sum_entropy[i])*
848 density_xy[x].direction[i].alpha;
852 Compute more texture features.
854 #if defined(MAGICKCORE_OPENMP_SUPPORT)
855 #pragma omp parallel for schedule(static,4) shared(status)
857 for (i=0; i < 4; i++)
862 for (y=0; y < (ssize_t) number_grays; y++)
867 for (x=0; x < (ssize_t) number_grays; x++)
870 Sum of Squares: Variance
872 variance.direction[i].red+=(y-mean.direction[i].red+1)*
873 (y-mean.direction[i].red+1)*cooccurrence[x][y].direction[i].red;
874 variance.direction[i].green+=(y-mean.direction[i].green+1)*
875 (y-mean.direction[i].green+1)*cooccurrence[x][y].direction[i].green;
876 variance.direction[i].blue+=(y-mean.direction[i].blue+1)*
877 (y-mean.direction[i].blue+1)*cooccurrence[x][y].direction[i].blue;
878 if (image->colorspace == CMYKColorspace)
879 variance.direction[i].black+=(y-mean.direction[i].black+1)*
880 (y-mean.direction[i].black+1)*cooccurrence[x][y].direction[i].black;
881 if (image->matte != MagickFalse)
882 variance.direction[i].alpha+=(y-mean.direction[i].alpha+1)*
883 (y-mean.direction[i].alpha+1)*
884 cooccurrence[x][y].direction[i].alpha;
886 Sum average / Difference Variance.
888 density_xy[MagickAbsoluteValue(y-x)].direction[i].red+=
889 cooccurrence[x][y].direction[i].red;
890 density_xy[MagickAbsoluteValue(y-x)].direction[i].green+=
891 cooccurrence[x][y].direction[i].green;
892 density_xy[MagickAbsoluteValue(y-x)].direction[i].blue+=
893 cooccurrence[x][y].direction[i].blue;
894 if (image->colorspace == CMYKColorspace)
895 density_xy[MagickAbsoluteValue(y-x)].direction[i].black+=
896 cooccurrence[x][y].direction[i].black;
897 if (image->matte != MagickFalse)
898 density_xy[MagickAbsoluteValue(y-x)].direction[i].alpha+=
899 cooccurrence[x][y].direction[i].alpha;
901 Information Measures of Correlation.
903 entropy_xy.direction[i].red-=cooccurrence[x][y].direction[i].red*
904 log10(cooccurrence[x][y].direction[i].red+MagickEpsilon);
905 entropy_xy.direction[i].green-=cooccurrence[x][y].direction[i].green*
906 log10(cooccurrence[x][y].direction[i].green+MagickEpsilon);
907 entropy_xy.direction[i].blue-=cooccurrence[x][y].direction[i].blue*
908 log10(cooccurrence[x][y].direction[i].blue+MagickEpsilon);
909 if (image->colorspace == CMYKColorspace)
910 entropy_xy.direction[i].black-=cooccurrence[x][y].direction[i].black*
911 log10(cooccurrence[x][y].direction[i].black+MagickEpsilon);
912 if (image->matte != MagickFalse)
913 entropy_xy.direction[i].alpha-=
914 cooccurrence[x][y].direction[i].alpha*log10(
915 cooccurrence[x][y].direction[i].alpha+MagickEpsilon);
916 entropy_xy1.direction[i].red-=(cooccurrence[x][y].direction[i].red*
917 log10(density_x[x].direction[i].red*density_y[y].direction[i].red+
919 entropy_xy1.direction[i].green-=(cooccurrence[x][y].direction[i].green*
920 log10(density_x[x].direction[i].green*density_y[y].direction[i].green+
922 entropy_xy1.direction[i].blue-=(cooccurrence[x][y].direction[i].blue*
923 log10(density_x[x].direction[i].blue*density_y[y].direction[i].blue+
925 if (image->colorspace == CMYKColorspace)
926 entropy_xy1.direction[i].black-=(
927 cooccurrence[x][y].direction[i].black*log10(
928 density_x[x].direction[i].black*density_y[y].direction[i].black+
930 if (image->matte != MagickFalse)
931 entropy_xy1.direction[i].alpha-=(
932 cooccurrence[x][y].direction[i].alpha*log10(
933 density_x[x].direction[i].alpha*density_y[y].direction[i].alpha+
935 entropy_xy2.direction[i].red-=(density_x[x].direction[i].red*
936 density_y[y].direction[i].red*log10(density_x[x].direction[i].red*
937 density_y[y].direction[i].red+MagickEpsilon));
938 entropy_xy2.direction[i].green-=(density_x[x].direction[i].green*
939 density_y[y].direction[i].green*log10(density_x[x].direction[i].green*
940 density_y[y].direction[i].green+MagickEpsilon));
941 entropy_xy2.direction[i].blue-=(density_x[x].direction[i].blue*
942 density_y[y].direction[i].blue*log10(density_x[x].direction[i].blue*
943 density_y[y].direction[i].blue+MagickEpsilon));
944 if (image->colorspace == CMYKColorspace)
945 entropy_xy2.direction[i].black-=(density_x[x].direction[i].black*
946 density_y[y].direction[i].black*log10(
947 density_x[x].direction[i].black*density_y[y].direction[i].black+
949 if (image->matte != MagickFalse)
950 entropy_xy2.direction[i].alpha-=(density_x[x].direction[i].alpha*
951 density_y[y].direction[i].alpha*log10(
952 density_x[x].direction[i].alpha*density_y[y].direction[i].alpha+
956 channel_features[RedPixelChannel].variance_sum_of_squares[i]=
957 variance.direction[i].red;
958 channel_features[GreenPixelChannel].variance_sum_of_squares[i]=
959 variance.direction[i].green;
960 channel_features[BluePixelChannel].variance_sum_of_squares[i]=
961 variance.direction[i].blue;
962 if (image->colorspace == CMYKColorspace)
963 channel_features[BlackPixelChannel].variance_sum_of_squares[i]=
964 variance.direction[i].black;
965 if (image->matte != MagickFalse)
966 channel_features[AlphaPixelChannel].variance_sum_of_squares[i]=
967 variance.direction[i].alpha;
970 Compute more texture features.
972 (void) ResetMagickMemory(&variance,0,sizeof(variance));
973 (void) ResetMagickMemory(&sum_squares,0,sizeof(sum_squares));
974 #if defined(MAGICKCORE_OPENMP_SUPPORT)
975 #pragma omp parallel for schedule(static,4) shared(status)
977 for (i=0; i < 4; i++)
982 for (x=0; x < (ssize_t) number_grays; x++)
987 variance.direction[i].red+=density_xy[x].direction[i].red;
988 variance.direction[i].green+=density_xy[x].direction[i].green;
989 variance.direction[i].blue+=density_xy[x].direction[i].blue;
990 if (image->colorspace == CMYKColorspace)
991 variance.direction[i].black+=density_xy[x].direction[i].black;
992 if (image->matte != MagickFalse)
993 variance.direction[i].alpha+=density_xy[x].direction[i].alpha;
994 sum_squares.direction[i].red+=density_xy[x].direction[i].red*
995 density_xy[x].direction[i].red;
996 sum_squares.direction[i].green+=density_xy[x].direction[i].green*
997 density_xy[x].direction[i].green;
998 sum_squares.direction[i].blue+=density_xy[x].direction[i].blue*
999 density_xy[x].direction[i].blue;
1000 if (image->colorspace == CMYKColorspace)
1001 sum_squares.direction[i].black+=density_xy[x].direction[i].black*
1002 density_xy[x].direction[i].black;
1003 if (image->matte != MagickFalse)
1004 sum_squares.direction[i].alpha+=density_xy[x].direction[i].alpha*
1005 density_xy[x].direction[i].alpha;
1009 channel_features[RedPixelChannel].difference_entropy[i]-=
1010 density_xy[x].direction[i].red*
1011 log10(density_xy[x].direction[i].red+MagickEpsilon);
1012 channel_features[GreenPixelChannel].difference_entropy[i]-=
1013 density_xy[x].direction[i].green*
1014 log10(density_xy[x].direction[i].green+MagickEpsilon);
1015 channel_features[BluePixelChannel].difference_entropy[i]-=
1016 density_xy[x].direction[i].blue*
1017 log10(density_xy[x].direction[i].blue+MagickEpsilon);
1018 if (image->colorspace == CMYKColorspace)
1019 channel_features[BlackPixelChannel].difference_entropy[i]-=
1020 density_xy[x].direction[i].black*
1021 log10(density_xy[x].direction[i].black+MagickEpsilon);
1022 if (image->matte != MagickFalse)
1023 channel_features[AlphaPixelChannel].difference_entropy[i]-=
1024 density_xy[x].direction[i].alpha*
1025 log10(density_xy[x].direction[i].alpha+MagickEpsilon);
1027 Information Measures of Correlation.
1029 entropy_x.direction[i].red-=(density_x[x].direction[i].red*
1030 log10(density_x[x].direction[i].red+MagickEpsilon));
1031 entropy_x.direction[i].green-=(density_x[x].direction[i].green*
1032 log10(density_x[x].direction[i].green+MagickEpsilon));
1033 entropy_x.direction[i].blue-=(density_x[x].direction[i].blue*
1034 log10(density_x[x].direction[i].blue+MagickEpsilon));
1035 if (image->colorspace == CMYKColorspace)
1036 entropy_x.direction[i].black-=(density_x[x].direction[i].black*
1037 log10(density_x[x].direction[i].black+MagickEpsilon));
1038 if (image->matte != MagickFalse)
1039 entropy_x.direction[i].alpha-=(density_x[x].direction[i].alpha*
1040 log10(density_x[x].direction[i].alpha+MagickEpsilon));
1041 entropy_y.direction[i].red-=(density_y[x].direction[i].red*
1042 log10(density_y[x].direction[i].red+MagickEpsilon));
1043 entropy_y.direction[i].green-=(density_y[x].direction[i].green*
1044 log10(density_y[x].direction[i].green+MagickEpsilon));
1045 entropy_y.direction[i].blue-=(density_y[x].direction[i].blue*
1046 log10(density_y[x].direction[i].blue+MagickEpsilon));
1047 if (image->colorspace == CMYKColorspace)
1048 entropy_y.direction[i].black-=(density_y[x].direction[i].black*
1049 log10(density_y[x].direction[i].black+MagickEpsilon));
1050 if (image->matte != MagickFalse)
1051 entropy_y.direction[i].alpha-=(density_y[x].direction[i].alpha*
1052 log10(density_y[x].direction[i].alpha+MagickEpsilon));
1055 Difference variance.
1057 channel_features[RedPixelChannel].difference_variance[i]=
1058 (((double) number_grays*number_grays*sum_squares.direction[i].red)-
1059 (variance.direction[i].red*variance.direction[i].red))/
1060 ((double) number_grays*number_grays*number_grays*number_grays);
1061 channel_features[GreenPixelChannel].difference_variance[i]=
1062 (((double) number_grays*number_grays*sum_squares.direction[i].green)-
1063 (variance.direction[i].green*variance.direction[i].green))/
1064 ((double) number_grays*number_grays*number_grays*number_grays);
1065 channel_features[BluePixelChannel].difference_variance[i]=
1066 (((double) number_grays*number_grays*sum_squares.direction[i].blue)-
1067 (variance.direction[i].blue*variance.direction[i].blue))/
1068 ((double) number_grays*number_grays*number_grays*number_grays);
1069 if (image->colorspace == CMYKColorspace)
1070 channel_features[BlackPixelChannel].difference_variance[i]=
1071 (((double) number_grays*number_grays*sum_squares.direction[i].black)-
1072 (variance.direction[i].black*variance.direction[i].black))/
1073 ((double) number_grays*number_grays*number_grays*number_grays);
1074 if (image->matte != MagickFalse)
1075 channel_features[AlphaPixelChannel].difference_variance[i]=
1076 (((double) number_grays*number_grays*sum_squares.direction[i].alpha)-
1077 (variance.direction[i].alpha*variance.direction[i].alpha))/
1078 ((double) number_grays*number_grays*number_grays*number_grays);
1080 Information Measures of Correlation.
1082 channel_features[RedPixelChannel].measure_of_correlation_1[i]=
1083 (entropy_xy.direction[i].red-entropy_xy1.direction[i].red)/
1084 (entropy_x.direction[i].red > entropy_y.direction[i].red ?
1085 entropy_x.direction[i].red : entropy_y.direction[i].red);
1086 channel_features[GreenPixelChannel].measure_of_correlation_1[i]=
1087 (entropy_xy.direction[i].green-entropy_xy1.direction[i].green)/
1088 (entropy_x.direction[i].green > entropy_y.direction[i].green ?
1089 entropy_x.direction[i].green : entropy_y.direction[i].green);
1090 channel_features[BluePixelChannel].measure_of_correlation_1[i]=
1091 (entropy_xy.direction[i].blue-entropy_xy1.direction[i].blue)/
1092 (entropy_x.direction[i].blue > entropy_y.direction[i].blue ?
1093 entropy_x.direction[i].blue : entropy_y.direction[i].blue);
1094 if (image->colorspace == CMYKColorspace)
1095 channel_features[BlackPixelChannel].measure_of_correlation_1[i]=
1096 (entropy_xy.direction[i].black-entropy_xy1.direction[i].black)/
1097 (entropy_x.direction[i].black > entropy_y.direction[i].black ?
1098 entropy_x.direction[i].black : entropy_y.direction[i].black);
1099 if (image->matte != MagickFalse)
1100 channel_features[AlphaPixelChannel].measure_of_correlation_1[i]=
1101 (entropy_xy.direction[i].alpha-entropy_xy1.direction[i].alpha)/
1102 (entropy_x.direction[i].alpha > entropy_y.direction[i].alpha ?
1103 entropy_x.direction[i].alpha : entropy_y.direction[i].alpha);
1104 channel_features[RedPixelChannel].measure_of_correlation_2[i]=
1105 (sqrt(fabs(1.0-exp(-2.0*(entropy_xy2.direction[i].red-
1106 entropy_xy.direction[i].red)))));
1107 channel_features[GreenPixelChannel].measure_of_correlation_2[i]=
1108 (sqrt(fabs(1.0-exp(-2.0*(entropy_xy2.direction[i].green-
1109 entropy_xy.direction[i].green)))));
1110 channel_features[BluePixelChannel].measure_of_correlation_2[i]=
1111 (sqrt(fabs(1.0-exp(-2.0*(entropy_xy2.direction[i].blue-
1112 entropy_xy.direction[i].blue)))));
1113 if (image->colorspace == CMYKColorspace)
1114 channel_features[BlackPixelChannel].measure_of_correlation_2[i]=
1115 (sqrt(fabs(1.0-exp(-2.0*(entropy_xy2.direction[i].black-
1116 entropy_xy.direction[i].black)))));
1117 if (image->matte != MagickFalse)
1118 channel_features[AlphaPixelChannel].measure_of_correlation_2[i]=
1119 (sqrt(fabs(1.0-exp(-2.0*(entropy_xy2.direction[i].alpha-
1120 entropy_xy.direction[i].alpha)))));
1123 Compute more texture features.
1125 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1126 #pragma omp parallel for schedule(static,4) shared(status)
1128 for (i=0; i < 4; i++)
1130 for (z=0; z < (ssize_t) number_grays; z++)
1138 (void) ResetMagickMemory(&pixel,0,sizeof(pixel));
1139 for (y=0; y < (ssize_t) number_grays; y++)
1144 for (x=0; x < (ssize_t) number_grays; x++)
1147 Contrast: amount of local variations present in an image.
1149 if (((y-x) == z) || ((x-y) == z))
1151 pixel.direction[i].red+=cooccurrence[x][y].direction[i].red;
1152 pixel.direction[i].green+=cooccurrence[x][y].direction[i].green;
1153 pixel.direction[i].blue+=cooccurrence[x][y].direction[i].blue;
1154 if (image->colorspace == CMYKColorspace)
1155 pixel.direction[i].black+=cooccurrence[x][y].direction[i].black;
1156 if (image->matte != MagickFalse)
1157 pixel.direction[i].alpha+=
1158 cooccurrence[x][y].direction[i].alpha;
1161 Maximum Correlation Coefficient.
1163 Q[z][y].direction[i].red+=cooccurrence[z][x].direction[i].red*
1164 cooccurrence[y][x].direction[i].red/density_x[z].direction[i].red/
1165 density_y[x].direction[i].red;
1166 Q[z][y].direction[i].green+=cooccurrence[z][x].direction[i].green*
1167 cooccurrence[y][x].direction[i].green/
1168 density_x[z].direction[i].green/density_y[x].direction[i].red;
1169 Q[z][y].direction[i].blue+=cooccurrence[z][x].direction[i].blue*
1170 cooccurrence[y][x].direction[i].blue/density_x[z].direction[i].blue/
1171 density_y[x].direction[i].blue;
1172 if (image->colorspace == CMYKColorspace)
1173 Q[z][y].direction[i].black+=cooccurrence[z][x].direction[i].black*
1174 cooccurrence[y][x].direction[i].black/
1175 density_x[z].direction[i].black/density_y[x].direction[i].black;
1176 if (image->matte != MagickFalse)
1177 Q[z][y].direction[i].alpha+=
1178 cooccurrence[z][x].direction[i].alpha*
1179 cooccurrence[y][x].direction[i].alpha/
1180 density_x[z].direction[i].alpha/
1181 density_y[x].direction[i].alpha;
1184 channel_features[RedPixelChannel].contrast[i]+=z*z*
1185 pixel.direction[i].red;
1186 channel_features[GreenPixelChannel].contrast[i]+=z*z*
1187 pixel.direction[i].green;
1188 channel_features[BluePixelChannel].contrast[i]+=z*z*
1189 pixel.direction[i].blue;
1190 if (image->colorspace == CMYKColorspace)
1191 channel_features[BlackPixelChannel].contrast[i]+=z*z*
1192 pixel.direction[i].black;
1193 if (image->matte != MagickFalse)
1194 channel_features[AlphaPixelChannel].contrast[i]+=z*z*
1195 pixel.direction[i].alpha;
1198 Maximum Correlation Coefficient.
1199 Future: return second largest eigenvalue of Q.
1201 channel_features[RedPixelChannel].maximum_correlation_coefficient[i]=
1202 sqrt((double) -1.0);
1203 channel_features[GreenPixelChannel].maximum_correlation_coefficient[i]=
1204 sqrt((double) -1.0);
1205 channel_features[BluePixelChannel].maximum_correlation_coefficient[i]=
1206 sqrt((double) -1.0);
1207 if (image->colorspace == CMYKColorspace)
1208 channel_features[BlackPixelChannel].maximum_correlation_coefficient[i]=
1209 sqrt((double) -1.0);
1210 if (image->matte != MagickFalse)
1211 channel_features[AlphaPixelChannel].maximum_correlation_coefficient[i]=
1212 sqrt((double) -1.0);
1215 Relinquish resources.
1217 sum=(ChannelStatistics *) RelinquishMagickMemory(sum);
1218 for (i=0; i < (ssize_t) number_grays; i++)
1219 Q[i]=(ChannelStatistics *) RelinquishMagickMemory(Q[i]);
1220 Q=(ChannelStatistics **) RelinquishMagickMemory(Q);
1221 density_y=(ChannelStatistics *) RelinquishMagickMemory(density_y);
1222 density_xy=(ChannelStatistics *) RelinquishMagickMemory(density_xy);
1223 density_x=(ChannelStatistics *) RelinquishMagickMemory(density_x);
1224 for (i=0; i < (ssize_t) number_grays; i++)
1225 cooccurrence[i]=(ChannelStatistics *)
1226 RelinquishMagickMemory(cooccurrence[i]);
1227 cooccurrence=(ChannelStatistics **) RelinquishMagickMemory(cooccurrence);
1228 return(channel_features);