|
MagickCore
6.7.5
|
00001 /* 00002 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00003 % % 00004 % % 00005 % % 00006 % FFFFF EEEEE AAA TTTTT U U RRRR EEEEE % 00007 % F E A A T U U R R E % 00008 % FFF EEE AAAAA T U U RRRR EEE % 00009 % F E A A T U U R R E % 00010 % F EEEEE A A T UUU R R EEEEE % 00011 % % 00012 % % 00013 % MagickCore Image Feature Methods % 00014 % % 00015 % Software Design % 00016 % John Cristy % 00017 % July 1992 % 00018 % % 00019 % % 00020 % Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization % 00021 % dedicated to making software imaging solutions freely available. % 00022 % % 00023 % You may not use this file except in compliance with the License. You may % 00024 % obtain a copy of the License at % 00025 % % 00026 % http://www.imagemagick.org/script/license.php % 00027 % % 00028 % Unless required by applicable law or agreed to in writing, software % 00029 % distributed under the License is distributed on an "AS IS" BASIS, % 00030 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. % 00031 % See the License for the specific language governing permissions and % 00032 % limitations under the License. % 00033 % % 00034 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00035 % 00036 % 00037 % 00038 */ 00039 00040 /* 00041 Include declarations. 00042 */ 00043 #include "MagickCore/studio.h" 00044 #include "MagickCore/property.h" 00045 #include "MagickCore/animate.h" 00046 #include "MagickCore/blob.h" 00047 #include "MagickCore/blob-private.h" 00048 #include "MagickCore/cache.h" 00049 #include "MagickCore/cache-private.h" 00050 #include "MagickCore/cache-view.h" 00051 #include "MagickCore/client.h" 00052 #include "MagickCore/color.h" 00053 #include "MagickCore/color-private.h" 00054 #include "MagickCore/colorspace.h" 00055 #include "MagickCore/colorspace-private.h" 00056 #include "MagickCore/composite.h" 00057 #include "MagickCore/composite-private.h" 00058 #include "MagickCore/compress.h" 00059 #include "MagickCore/constitute.h" 00060 #include "MagickCore/display.h" 00061 #include "MagickCore/draw.h" 00062 #include "MagickCore/enhance.h" 00063 #include "MagickCore/exception.h" 00064 #include "MagickCore/exception-private.h" 00065 #include "MagickCore/feature.h" 00066 #include "MagickCore/gem.h" 00067 #include "MagickCore/geometry.h" 00068 #include "MagickCore/list.h" 00069 #include "MagickCore/image-private.h" 00070 #include "MagickCore/magic.h" 00071 #include "MagickCore/magick.h" 00072 #include "MagickCore/memory_.h" 00073 #include "MagickCore/module.h" 00074 #include "MagickCore/monitor.h" 00075 #include "MagickCore/monitor-private.h" 00076 #include "MagickCore/option.h" 00077 #include "MagickCore/paint.h" 00078 #include "MagickCore/pixel-accessor.h" 00079 #include "MagickCore/profile.h" 00080 #include "MagickCore/quantize.h" 00081 #include "MagickCore/quantum-private.h" 00082 #include "MagickCore/random_.h" 00083 #include "MagickCore/segment.h" 00084 #include "MagickCore/semaphore.h" 00085 #include "MagickCore/signature-private.h" 00086 #include "MagickCore/string_.h" 00087 #include "MagickCore/thread-private.h" 00088 #include "MagickCore/timer.h" 00089 #include "MagickCore/utility.h" 00090 #include "MagickCore/version.h" 00091 00092 /* 00093 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00094 % % 00095 % % 00096 % % 00097 % G e t I m a g e F e a t u r e s % 00098 % % 00099 % % 00100 % % 00101 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00102 % 00103 % GetImageFeatures() returns features for each channel in the image in 00104 % each of four directions (horizontal, vertical, left and right diagonals) 00105 % for the specified distance. The features include the angular second 00106 % moment, contrast, correlation, sum of squares: variance, inverse difference 00107 % moment, sum average, sum varience, sum entropy, entropy, difference variance,% difference entropy, information measures of correlation 1, information 00108 % measures of correlation 2, and maximum correlation coefficient. You can 00109 % access the red channel contrast, for example, like this: 00110 % 00111 % channel_features=GetImageFeatures(image,1,exception); 00112 % contrast=channel_features[RedPixelChannel].contrast[0]; 00113 % 00114 % Use MagickRelinquishMemory() to free the features buffer. 00115 % 00116 % The format of the GetImageFeatures method is: 00117 % 00118 % ChannelFeatures *GetImageFeatures(const Image *image, 00119 % const size_t distance,ExceptionInfo *exception) 00120 % 00121 % A description of each parameter follows: 00122 % 00123 % o image: the image. 00124 % 00125 % o distance: the distance. 00126 % 00127 % o exception: return any errors or warnings in this structure. 00128 % 00129 */ 00130 00131 static inline ssize_t MagickAbsoluteValue(const ssize_t x) 00132 { 00133 if (x < 0) 00134 return(-x); 00135 return(x); 00136 } 00137 00138 MagickExport ChannelFeatures *GetImageFeatures(const Image *image, 00139 const size_t distance,ExceptionInfo *exception) 00140 { 00141 typedef struct _ChannelStatistics 00142 { 00143 PixelInfo 00144 direction[4]; /* horizontal, vertical, left and right diagonals */ 00145 } ChannelStatistics; 00146 00147 CacheView 00148 *image_view; 00149 00150 ChannelFeatures 00151 *channel_features; 00152 00153 ChannelStatistics 00154 **cooccurrence, 00155 correlation, 00156 *density_x, 00157 *density_xy, 00158 *density_y, 00159 entropy_x, 00160 entropy_xy, 00161 entropy_xy1, 00162 entropy_xy2, 00163 entropy_y, 00164 mean, 00165 **Q, 00166 *sum, 00167 sum_squares, 00168 variance; 00169 00170 PixelPacket 00171 gray, 00172 *grays; 00173 00174 MagickBooleanType 00175 status; 00176 00177 register ssize_t 00178 i; 00179 00180 size_t 00181 length; 00182 00183 ssize_t 00184 y; 00185 00186 unsigned int 00187 number_grays; 00188 00189 assert(image != (Image *) NULL); 00190 assert(image->signature == MagickSignature); 00191 if (image->debug != MagickFalse) 00192 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 00193 if ((image->columns < (distance+1)) || (image->rows < (distance+1))) 00194 return((ChannelFeatures *) NULL); 00195 length=CompositeChannels+1UL; 00196 channel_features=(ChannelFeatures *) AcquireQuantumMemory(length, 00197 sizeof(*channel_features)); 00198 if (channel_features == (ChannelFeatures *) NULL) 00199 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed"); 00200 (void) ResetMagickMemory(channel_features,0,length* 00201 sizeof(*channel_features)); 00202 /* 00203 Form grays. 00204 */ 00205 grays=(PixelPacket *) AcquireQuantumMemory(MaxMap+1UL,sizeof(*grays)); 00206 if (grays == (PixelPacket *) NULL) 00207 { 00208 channel_features=(ChannelFeatures *) RelinquishMagickMemory( 00209 channel_features); 00210 (void) ThrowMagickException(exception,GetMagickModule(), 00211 ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename); 00212 return(channel_features); 00213 } 00214 for (i=0; i <= (ssize_t) MaxMap; i++) 00215 { 00216 grays[i].red=(~0U); 00217 grays[i].green=(~0U); 00218 grays[i].blue=(~0U); 00219 grays[i].alpha=(~0U); 00220 grays[i].black=(~0U); 00221 } 00222 status=MagickTrue; 00223 image_view=AcquireCacheView(image); 00224 #if defined(MAGICKCORE_OPENMP_SUPPORT) 00225 #pragma omp parallel for schedule(static,4) shared(status) 00226 #endif 00227 for (y=0; y < (ssize_t) image->rows; y++) 00228 { 00229 register const Quantum 00230 *restrict p; 00231 00232 register ssize_t 00233 x; 00234 00235 if (status == MagickFalse) 00236 continue; 00237 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception); 00238 if (p == (const Quantum *) NULL) 00239 { 00240 status=MagickFalse; 00241 continue; 00242 } 00243 for (x=0; x < (ssize_t) image->columns; x++) 00244 { 00245 grays[ScaleQuantumToMap(GetPixelRed(image,p))].red= 00246 ScaleQuantumToMap(GetPixelRed(image,p)); 00247 grays[ScaleQuantumToMap(GetPixelGreen(image,p))].green= 00248 ScaleQuantumToMap(GetPixelGreen(image,p)); 00249 grays[ScaleQuantumToMap(GetPixelBlue(image,p))].blue= 00250 ScaleQuantumToMap(GetPixelBlue(image,p)); 00251 if (image->colorspace == CMYKColorspace) 00252 grays[ScaleQuantumToMap(GetPixelBlack(image,p))].black= 00253 ScaleQuantumToMap(GetPixelBlack(image,p)); 00254 if (image->matte != MagickFalse) 00255 grays[ScaleQuantumToMap(GetPixelAlpha(image,p))].alpha= 00256 ScaleQuantumToMap(GetPixelAlpha(image,p)); 00257 p+=GetPixelChannels(image); 00258 } 00259 } 00260 image_view=DestroyCacheView(image_view); 00261 if (status == MagickFalse) 00262 { 00263 grays=(PixelPacket *) RelinquishMagickMemory(grays); 00264 channel_features=(ChannelFeatures *) RelinquishMagickMemory( 00265 channel_features); 00266 return(channel_features); 00267 } 00268 (void) ResetMagickMemory(&gray,0,sizeof(gray)); 00269 for (i=0; i <= (ssize_t) MaxMap; i++) 00270 { 00271 if (grays[i].red != ~0U) 00272 grays[gray.red++].red=grays[i].red; 00273 if (grays[i].green != ~0U) 00274 grays[gray.green++].green=grays[i].green; 00275 if (grays[i].blue != ~0U) 00276 grays[gray.blue++].blue=grays[i].blue; 00277 if (image->colorspace == CMYKColorspace) 00278 if (grays[i].black != ~0U) 00279 grays[gray.black++].black=grays[i].black; 00280 if (image->matte != MagickFalse) 00281 if (grays[i].alpha != ~0U) 00282 grays[gray.alpha++].alpha=grays[i].alpha; 00283 } 00284 /* 00285 Allocate spatial dependence matrix. 00286 */ 00287 number_grays=gray.red; 00288 if (gray.green > number_grays) 00289 number_grays=gray.green; 00290 if (gray.blue > number_grays) 00291 number_grays=gray.blue; 00292 if (image->colorspace == CMYKColorspace) 00293 if (gray.black > number_grays) 00294 number_grays=gray.black; 00295 if (image->matte != MagickFalse) 00296 if (gray.alpha > number_grays) 00297 number_grays=gray.alpha; 00298 cooccurrence=(ChannelStatistics **) AcquireQuantumMemory(number_grays, 00299 sizeof(*cooccurrence)); 00300 density_x=(ChannelStatistics *) AcquireQuantumMemory(2*(number_grays+1), 00301 sizeof(*density_x)); 00302 density_xy=(ChannelStatistics *) AcquireQuantumMemory(2*(number_grays+1), 00303 sizeof(*density_xy)); 00304 density_y=(ChannelStatistics *) AcquireQuantumMemory(2*(number_grays+1), 00305 sizeof(*density_y)); 00306 Q=(ChannelStatistics **) AcquireQuantumMemory(number_grays,sizeof(*Q)); 00307 sum=(ChannelStatistics *) AcquireQuantumMemory(number_grays,sizeof(*sum)); 00308 if ((cooccurrence == (ChannelStatistics **) NULL) || 00309 (density_x == (ChannelStatistics *) NULL) || 00310 (density_xy == (ChannelStatistics *) NULL) || 00311 (density_y == (ChannelStatistics *) NULL) || 00312 (Q == (ChannelStatistics **) NULL) || 00313 (sum == (ChannelStatistics *) NULL)) 00314 { 00315 if (Q != (ChannelStatistics **) NULL) 00316 { 00317 for (i=0; i < (ssize_t) number_grays; i++) 00318 Q[i]=(ChannelStatistics *) RelinquishMagickMemory(Q[i]); 00319 Q=(ChannelStatistics **) RelinquishMagickMemory(Q); 00320 } 00321 if (sum != (ChannelStatistics *) NULL) 00322 sum=(ChannelStatistics *) RelinquishMagickMemory(sum); 00323 if (density_y != (ChannelStatistics *) NULL) 00324 density_y=(ChannelStatistics *) RelinquishMagickMemory(density_y); 00325 if (density_xy != (ChannelStatistics *) NULL) 00326 density_xy=(ChannelStatistics *) RelinquishMagickMemory(density_xy); 00327 if (density_x != (ChannelStatistics *) NULL) 00328 density_x=(ChannelStatistics *) RelinquishMagickMemory(density_x); 00329 if (cooccurrence != (ChannelStatistics **) NULL) 00330 { 00331 for (i=0; i < (ssize_t) number_grays; i++) 00332 cooccurrence[i]=(ChannelStatistics *) 00333 RelinquishMagickMemory(cooccurrence[i]); 00334 cooccurrence=(ChannelStatistics **) RelinquishMagickMemory( 00335 cooccurrence); 00336 } 00337 grays=(PixelPacket *) RelinquishMagickMemory(grays); 00338 channel_features=(ChannelFeatures *) RelinquishMagickMemory( 00339 channel_features); 00340 (void) ThrowMagickException(exception,GetMagickModule(), 00341 ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename); 00342 return(channel_features); 00343 } 00344 (void) ResetMagickMemory(&correlation,0,sizeof(correlation)); 00345 (void) ResetMagickMemory(density_x,0,2*(number_grays+1)*sizeof(*density_x)); 00346 (void) ResetMagickMemory(density_xy,0,2*(number_grays+1)*sizeof(*density_xy)); 00347 (void) ResetMagickMemory(density_y,0,2*(number_grays+1)*sizeof(*density_y)); 00348 (void) ResetMagickMemory(&mean,0,sizeof(mean)); 00349 (void) ResetMagickMemory(sum,0,number_grays*sizeof(*sum)); 00350 (void) ResetMagickMemory(&sum_squares,0,sizeof(sum_squares)); 00351 (void) ResetMagickMemory(density_xy,0,2*number_grays*sizeof(*density_xy)); 00352 (void) ResetMagickMemory(&entropy_x,0,sizeof(entropy_x)); 00353 (void) ResetMagickMemory(&entropy_xy,0,sizeof(entropy_xy)); 00354 (void) ResetMagickMemory(&entropy_xy1,0,sizeof(entropy_xy1)); 00355 (void) ResetMagickMemory(&entropy_xy2,0,sizeof(entropy_xy2)); 00356 (void) ResetMagickMemory(&entropy_y,0,sizeof(entropy_y)); 00357 (void) ResetMagickMemory(&variance,0,sizeof(variance)); 00358 for (i=0; i < (ssize_t) number_grays; i++) 00359 { 00360 cooccurrence[i]=(ChannelStatistics *) AcquireQuantumMemory(number_grays, 00361 sizeof(**cooccurrence)); 00362 Q[i]=(ChannelStatistics *) AcquireQuantumMemory(number_grays,sizeof(**Q)); 00363 if ((cooccurrence[i] == (ChannelStatistics *) NULL) || 00364 (Q[i] == (ChannelStatistics *) NULL)) 00365 break; 00366 (void) ResetMagickMemory(cooccurrence[i],0,number_grays* 00367 sizeof(**cooccurrence)); 00368 (void) ResetMagickMemory(Q[i],0,number_grays*sizeof(**Q)); 00369 } 00370 if (i < (ssize_t) number_grays) 00371 { 00372 for (i--; i >= 0; i--) 00373 { 00374 if (Q[i] != (ChannelStatistics *) NULL) 00375 Q[i]=(ChannelStatistics *) RelinquishMagickMemory(Q[i]); 00376 if (cooccurrence[i] != (ChannelStatistics *) NULL) 00377 cooccurrence[i]=(ChannelStatistics *) 00378 RelinquishMagickMemory(cooccurrence[i]); 00379 } 00380 Q=(ChannelStatistics **) RelinquishMagickMemory(Q); 00381 cooccurrence=(ChannelStatistics **) RelinquishMagickMemory(cooccurrence); 00382 sum=(ChannelStatistics *) RelinquishMagickMemory(sum); 00383 density_y=(ChannelStatistics *) RelinquishMagickMemory(density_y); 00384 density_xy=(ChannelStatistics *) RelinquishMagickMemory(density_xy); 00385 density_x=(ChannelStatistics *) RelinquishMagickMemory(density_x); 00386 grays=(PixelPacket *) RelinquishMagickMemory(grays); 00387 channel_features=(ChannelFeatures *) RelinquishMagickMemory( 00388 channel_features); 00389 (void) ThrowMagickException(exception,GetMagickModule(), 00390 ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename); 00391 return(channel_features); 00392 } 00393 /* 00394 Initialize spatial dependence matrix. 00395 */ 00396 status=MagickTrue; 00397 image_view=AcquireCacheView(image); 00398 for (y=0; y < (ssize_t) image->rows; y++) 00399 { 00400 register const Quantum 00401 *restrict p; 00402 00403 register ssize_t 00404 x; 00405 00406 ssize_t 00407 i, 00408 offset, 00409 u, 00410 v; 00411 00412 if (status == MagickFalse) 00413 continue; 00414 p=GetCacheViewVirtualPixels(image_view,-(ssize_t) distance,y,image->columns+ 00415 2*distance,distance+2,exception); 00416 if (p == (const Quantum *) NULL) 00417 { 00418 status=MagickFalse; 00419 continue; 00420 } 00421 p+=distance*GetPixelChannels(image);; 00422 for (x=0; x < (ssize_t) image->columns; x++) 00423 { 00424 for (i=0; i < 4; i++) 00425 { 00426 switch (i) 00427 { 00428 case 0: 00429 default: 00430 { 00431 /* 00432 Horizontal adjacency. 00433 */ 00434 offset=(ssize_t) distance; 00435 break; 00436 } 00437 case 1: 00438 { 00439 /* 00440 Vertical adjacency. 00441 */ 00442 offset=(ssize_t) (image->columns+2*distance); 00443 break; 00444 } 00445 case 2: 00446 { 00447 /* 00448 Right diagonal adjacency. 00449 */ 00450 offset=(ssize_t) ((image->columns+2*distance)-distance); 00451 break; 00452 } 00453 case 3: 00454 { 00455 /* 00456 Left diagonal adjacency. 00457 */ 00458 offset=(ssize_t) ((image->columns+2*distance)+distance); 00459 break; 00460 } 00461 } 00462 u=0; 00463 v=0; 00464 while (grays[u].red != ScaleQuantumToMap(GetPixelRed(image,p))) 00465 u++; 00466 while (grays[v].red != ScaleQuantumToMap(GetPixelRed(image,p+offset*GetPixelChannels(image)))) 00467 v++; 00468 cooccurrence[u][v].direction[i].red++; 00469 cooccurrence[v][u].direction[i].red++; 00470 u=0; 00471 v=0; 00472 while (grays[u].green != ScaleQuantumToMap(GetPixelGreen(image,p))) 00473 u++; 00474 while (grays[v].green != ScaleQuantumToMap(GetPixelGreen(image,p+offset*GetPixelChannels(image)))) 00475 v++; 00476 cooccurrence[u][v].direction[i].green++; 00477 cooccurrence[v][u].direction[i].green++; 00478 u=0; 00479 v=0; 00480 while (grays[u].blue != ScaleQuantumToMap(GetPixelBlue(image,p))) 00481 u++; 00482 while (grays[v].blue != ScaleQuantumToMap(GetPixelBlue(image,p+offset*GetPixelChannels(image)))) 00483 v++; 00484 cooccurrence[u][v].direction[i].blue++; 00485 cooccurrence[v][u].direction[i].blue++; 00486 if (image->colorspace == CMYKColorspace) 00487 { 00488 u=0; 00489 v=0; 00490 while (grays[u].black != ScaleQuantumToMap(GetPixelBlack(image,p))) 00491 u++; 00492 while (grays[v].black != ScaleQuantumToMap(GetPixelBlack(image,p+offset*GetPixelChannels(image)))) 00493 v++; 00494 cooccurrence[u][v].direction[i].black++; 00495 cooccurrence[v][u].direction[i].black++; 00496 } 00497 if (image->matte != MagickFalse) 00498 { 00499 u=0; 00500 v=0; 00501 while (grays[u].alpha != ScaleQuantumToMap(GetPixelAlpha(image,p))) 00502 u++; 00503 while (grays[v].alpha != ScaleQuantumToMap(GetPixelAlpha(image,p+offset*GetPixelChannels(image)))) 00504 v++; 00505 cooccurrence[u][v].direction[i].alpha++; 00506 cooccurrence[v][u].direction[i].alpha++; 00507 } 00508 } 00509 p+=GetPixelChannels(image); 00510 } 00511 } 00512 grays=(PixelPacket *) RelinquishMagickMemory(grays); 00513 image_view=DestroyCacheView(image_view); 00514 if (status == MagickFalse) 00515 { 00516 for (i=0; i < (ssize_t) number_grays; i++) 00517 cooccurrence[i]=(ChannelStatistics *) 00518 RelinquishMagickMemory(cooccurrence[i]); 00519 cooccurrence=(ChannelStatistics **) RelinquishMagickMemory(cooccurrence); 00520 channel_features=(ChannelFeatures *) RelinquishMagickMemory( 00521 channel_features); 00522 (void) ThrowMagickException(exception,GetMagickModule(), 00523 ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename); 00524 return(channel_features); 00525 } 00526 /* 00527 Normalize spatial dependence matrix. 00528 */ 00529 for (i=0; i < 4; i++) 00530 { 00531 double 00532 normalize; 00533 00534 register ssize_t 00535 y; 00536 00537 switch (i) 00538 { 00539 case 0: 00540 default: 00541 { 00542 /* 00543 Horizontal adjacency. 00544 */ 00545 normalize=2.0*image->rows*(image->columns-distance); 00546 break; 00547 } 00548 case 1: 00549 { 00550 /* 00551 Vertical adjacency. 00552 */ 00553 normalize=2.0*(image->rows-distance)*image->columns; 00554 break; 00555 } 00556 case 2: 00557 { 00558 /* 00559 Right diagonal adjacency. 00560 */ 00561 normalize=2.0*(image->rows-distance)*(image->columns-distance); 00562 break; 00563 } 00564 case 3: 00565 { 00566 /* 00567 Left diagonal adjacency. 00568 */ 00569 normalize=2.0*(image->rows-distance)*(image->columns-distance); 00570 break; 00571 } 00572 } 00573 normalize=1.0/(fabs((double) normalize) <= MagickEpsilon ? 1.0 : normalize); 00574 for (y=0; y < (ssize_t) number_grays; y++) 00575 { 00576 register ssize_t 00577 x; 00578 00579 for (x=0; x < (ssize_t) number_grays; x++) 00580 { 00581 cooccurrence[x][y].direction[i].red*=normalize; 00582 cooccurrence[x][y].direction[i].green*=normalize; 00583 cooccurrence[x][y].direction[i].blue*=normalize; 00584 if (image->colorspace == CMYKColorspace) 00585 cooccurrence[x][y].direction[i].black*=normalize; 00586 if (image->matte != MagickFalse) 00587 cooccurrence[x][y].direction[i].alpha*=normalize; 00588 } 00589 } 00590 } 00591 /* 00592 Compute texture features. 00593 */ 00594 #if defined(MAGICKCORE_OPENMP_SUPPORT) 00595 #pragma omp parallel for schedule(static,4) shared(status) 00596 #endif 00597 for (i=0; i < 4; i++) 00598 { 00599 register ssize_t 00600 y; 00601 00602 for (y=0; y < (ssize_t) number_grays; y++) 00603 { 00604 register ssize_t 00605 x; 00606 00607 for (x=0; x < (ssize_t) number_grays; x++) 00608 { 00609 /* 00610 Angular second moment: measure of homogeneity of the image. 00611 */ 00612 channel_features[RedPixelChannel].angular_second_moment[i]+= 00613 cooccurrence[x][y].direction[i].red* 00614 cooccurrence[x][y].direction[i].red; 00615 channel_features[GreenPixelChannel].angular_second_moment[i]+= 00616 cooccurrence[x][y].direction[i].green* 00617 cooccurrence[x][y].direction[i].green; 00618 channel_features[BluePixelChannel].angular_second_moment[i]+= 00619 cooccurrence[x][y].direction[i].blue* 00620 cooccurrence[x][y].direction[i].blue; 00621 if (image->colorspace == CMYKColorspace) 00622 channel_features[BlackPixelChannel].angular_second_moment[i]+= 00623 cooccurrence[x][y].direction[i].black* 00624 cooccurrence[x][y].direction[i].black; 00625 if (image->matte != MagickFalse) 00626 channel_features[AlphaPixelChannel].angular_second_moment[i]+= 00627 cooccurrence[x][y].direction[i].alpha* 00628 cooccurrence[x][y].direction[i].alpha; 00629 /* 00630 Correlation: measure of linear-dependencies in the image. 00631 */ 00632 sum[y].direction[i].red+=cooccurrence[x][y].direction[i].red; 00633 sum[y].direction[i].green+=cooccurrence[x][y].direction[i].green; 00634 sum[y].direction[i].blue+=cooccurrence[x][y].direction[i].blue; 00635 if (image->colorspace == CMYKColorspace) 00636 sum[y].direction[i].black+=cooccurrence[x][y].direction[i].black; 00637 if (image->matte != MagickFalse) 00638 sum[y].direction[i].alpha+=cooccurrence[x][y].direction[i].alpha; 00639 correlation.direction[i].red+=x*y*cooccurrence[x][y].direction[i].red; 00640 correlation.direction[i].green+=x*y* 00641 cooccurrence[x][y].direction[i].green; 00642 correlation.direction[i].blue+=x*y* 00643 cooccurrence[x][y].direction[i].blue; 00644 if (image->colorspace == CMYKColorspace) 00645 correlation.direction[i].black+=x*y* 00646 cooccurrence[x][y].direction[i].black; 00647 if (image->matte != MagickFalse) 00648 correlation.direction[i].alpha+=x*y* 00649 cooccurrence[x][y].direction[i].alpha; 00650 /* 00651 Inverse Difference Moment. 00652 */ 00653 channel_features[RedPixelChannel].inverse_difference_moment[i]+= 00654 cooccurrence[x][y].direction[i].red/((y-x)*(y-x)+1); 00655 channel_features[GreenPixelChannel].inverse_difference_moment[i]+= 00656 cooccurrence[x][y].direction[i].green/((y-x)*(y-x)+1); 00657 channel_features[BluePixelChannel].inverse_difference_moment[i]+= 00658 cooccurrence[x][y].direction[i].blue/((y-x)*(y-x)+1); 00659 if (image->colorspace == CMYKColorspace) 00660 channel_features[BlackPixelChannel].inverse_difference_moment[i]+= 00661 cooccurrence[x][y].direction[i].black/((y-x)*(y-x)+1); 00662 if (image->matte != MagickFalse) 00663 channel_features[AlphaPixelChannel].inverse_difference_moment[i]+= 00664 cooccurrence[x][y].direction[i].alpha/((y-x)*(y-x)+1); 00665 /* 00666 Sum average. 00667 */ 00668 density_xy[y+x+2].direction[i].red+= 00669 cooccurrence[x][y].direction[i].red; 00670 density_xy[y+x+2].direction[i].green+= 00671 cooccurrence[x][y].direction[i].green; 00672 density_xy[y+x+2].direction[i].blue+= 00673 cooccurrence[x][y].direction[i].blue; 00674 if (image->colorspace == CMYKColorspace) 00675 density_xy[y+x+2].direction[i].black+= 00676 cooccurrence[x][y].direction[i].black; 00677 if (image->matte != MagickFalse) 00678 density_xy[y+x+2].direction[i].alpha+= 00679 cooccurrence[x][y].direction[i].alpha; 00680 /* 00681 Entropy. 00682 */ 00683 channel_features[RedPixelChannel].entropy[i]-= 00684 cooccurrence[x][y].direction[i].red* 00685 log10(cooccurrence[x][y].direction[i].red+MagickEpsilon); 00686 channel_features[GreenPixelChannel].entropy[i]-= 00687 cooccurrence[x][y].direction[i].green* 00688 log10(cooccurrence[x][y].direction[i].green+MagickEpsilon); 00689 channel_features[BluePixelChannel].entropy[i]-= 00690 cooccurrence[x][y].direction[i].blue* 00691 log10(cooccurrence[x][y].direction[i].blue+MagickEpsilon); 00692 if (image->colorspace == CMYKColorspace) 00693 channel_features[BlackPixelChannel].entropy[i]-= 00694 cooccurrence[x][y].direction[i].black* 00695 log10(cooccurrence[x][y].direction[i].black+MagickEpsilon); 00696 if (image->matte != MagickFalse) 00697 channel_features[AlphaPixelChannel].entropy[i]-= 00698 cooccurrence[x][y].direction[i].alpha* 00699 log10(cooccurrence[x][y].direction[i].alpha+MagickEpsilon); 00700 /* 00701 Information Measures of Correlation. 00702 */ 00703 density_x[x].direction[i].red+=cooccurrence[x][y].direction[i].red; 00704 density_x[x].direction[i].green+=cooccurrence[x][y].direction[i].green; 00705 density_x[x].direction[i].blue+=cooccurrence[x][y].direction[i].blue; 00706 if (image->matte != MagickFalse) 00707 density_x[x].direction[i].alpha+= 00708 cooccurrence[x][y].direction[i].alpha; 00709 if (image->colorspace == CMYKColorspace) 00710 density_x[x].direction[i].black+= 00711 cooccurrence[x][y].direction[i].black; 00712 density_y[y].direction[i].red+=cooccurrence[x][y].direction[i].red; 00713 density_y[y].direction[i].green+=cooccurrence[x][y].direction[i].green; 00714 density_y[y].direction[i].blue+=cooccurrence[x][y].direction[i].blue; 00715 if (image->colorspace == CMYKColorspace) 00716 density_y[y].direction[i].black+= 00717 cooccurrence[x][y].direction[i].black; 00718 if (image->matte != MagickFalse) 00719 density_y[y].direction[i].alpha+= 00720 cooccurrence[x][y].direction[i].alpha; 00721 } 00722 mean.direction[i].red+=y*sum[y].direction[i].red; 00723 sum_squares.direction[i].red+=y*y*sum[y].direction[i].red; 00724 mean.direction[i].green+=y*sum[y].direction[i].green; 00725 sum_squares.direction[i].green+=y*y*sum[y].direction[i].green; 00726 mean.direction[i].blue+=y*sum[y].direction[i].blue; 00727 sum_squares.direction[i].blue+=y*y*sum[y].direction[i].blue; 00728 if (image->colorspace == CMYKColorspace) 00729 { 00730 mean.direction[i].black+=y*sum[y].direction[i].black; 00731 sum_squares.direction[i].black+=y*y*sum[y].direction[i].black; 00732 } 00733 if (image->matte != MagickFalse) 00734 { 00735 mean.direction[i].alpha+=y*sum[y].direction[i].alpha; 00736 sum_squares.direction[i].alpha+=y*y*sum[y].direction[i].alpha; 00737 } 00738 } 00739 /* 00740 Correlation: measure of linear-dependencies in the image. 00741 */ 00742 channel_features[RedPixelChannel].correlation[i]= 00743 (correlation.direction[i].red-mean.direction[i].red* 00744 mean.direction[i].red)/(sqrt(sum_squares.direction[i].red- 00745 (mean.direction[i].red*mean.direction[i].red))*sqrt( 00746 sum_squares.direction[i].red-(mean.direction[i].red* 00747 mean.direction[i].red))); 00748 channel_features[GreenPixelChannel].correlation[i]= 00749 (correlation.direction[i].green-mean.direction[i].green* 00750 mean.direction[i].green)/(sqrt(sum_squares.direction[i].green- 00751 (mean.direction[i].green*mean.direction[i].green))*sqrt( 00752 sum_squares.direction[i].green-(mean.direction[i].green* 00753 mean.direction[i].green))); 00754 channel_features[BluePixelChannel].correlation[i]= 00755 (correlation.direction[i].blue-mean.direction[i].blue* 00756 mean.direction[i].blue)/(sqrt(sum_squares.direction[i].blue- 00757 (mean.direction[i].blue*mean.direction[i].blue))*sqrt( 00758 sum_squares.direction[i].blue-(mean.direction[i].blue* 00759 mean.direction[i].blue))); 00760 if (image->colorspace == CMYKColorspace) 00761 channel_features[BlackPixelChannel].correlation[i]= 00762 (correlation.direction[i].black-mean.direction[i].black* 00763 mean.direction[i].black)/(sqrt(sum_squares.direction[i].black- 00764 (mean.direction[i].black*mean.direction[i].black))*sqrt( 00765 sum_squares.direction[i].black-(mean.direction[i].black* 00766 mean.direction[i].black))); 00767 if (image->matte != MagickFalse) 00768 channel_features[AlphaPixelChannel].correlation[i]= 00769 (correlation.direction[i].alpha-mean.direction[i].alpha* 00770 mean.direction[i].alpha)/(sqrt(sum_squares.direction[i].alpha- 00771 (mean.direction[i].alpha*mean.direction[i].alpha))*sqrt( 00772 sum_squares.direction[i].alpha-(mean.direction[i].alpha* 00773 mean.direction[i].alpha))); 00774 } 00775 /* 00776 Compute more texture features. 00777 */ 00778 #if defined(MAGICKCORE_OPENMP_SUPPORT) 00779 #pragma omp parallel for schedule(static,4) shared(status) 00780 #endif 00781 for (i=0; i < 4; i++) 00782 { 00783 register ssize_t 00784 x; 00785 00786 for (x=2; x < (ssize_t) (2*number_grays); x++) 00787 { 00788 /* 00789 Sum average. 00790 */ 00791 channel_features[RedPixelChannel].sum_average[i]+= 00792 x*density_xy[x].direction[i].red; 00793 channel_features[GreenPixelChannel].sum_average[i]+= 00794 x*density_xy[x].direction[i].green; 00795 channel_features[BluePixelChannel].sum_average[i]+= 00796 x*density_xy[x].direction[i].blue; 00797 if (image->colorspace == CMYKColorspace) 00798 channel_features[BlackPixelChannel].sum_average[i]+= 00799 x*density_xy[x].direction[i].black; 00800 if (image->matte != MagickFalse) 00801 channel_features[AlphaPixelChannel].sum_average[i]+= 00802 x*density_xy[x].direction[i].alpha; 00803 /* 00804 Sum entropy. 00805 */ 00806 channel_features[RedPixelChannel].sum_entropy[i]-= 00807 density_xy[x].direction[i].red* 00808 log10(density_xy[x].direction[i].red+MagickEpsilon); 00809 channel_features[GreenPixelChannel].sum_entropy[i]-= 00810 density_xy[x].direction[i].green* 00811 log10(density_xy[x].direction[i].green+MagickEpsilon); 00812 channel_features[BluePixelChannel].sum_entropy[i]-= 00813 density_xy[x].direction[i].blue* 00814 log10(density_xy[x].direction[i].blue+MagickEpsilon); 00815 if (image->colorspace == CMYKColorspace) 00816 channel_features[BlackPixelChannel].sum_entropy[i]-= 00817 density_xy[x].direction[i].black* 00818 log10(density_xy[x].direction[i].black+MagickEpsilon); 00819 if (image->matte != MagickFalse) 00820 channel_features[AlphaPixelChannel].sum_entropy[i]-= 00821 density_xy[x].direction[i].alpha* 00822 log10(density_xy[x].direction[i].alpha+MagickEpsilon); 00823 /* 00824 Sum variance. 00825 */ 00826 channel_features[RedPixelChannel].sum_variance[i]+= 00827 (x-channel_features[RedPixelChannel].sum_entropy[i])* 00828 (x-channel_features[RedPixelChannel].sum_entropy[i])* 00829 density_xy[x].direction[i].red; 00830 channel_features[GreenPixelChannel].sum_variance[i]+= 00831 (x-channel_features[GreenPixelChannel].sum_entropy[i])* 00832 (x-channel_features[GreenPixelChannel].sum_entropy[i])* 00833 density_xy[x].direction[i].green; 00834 channel_features[BluePixelChannel].sum_variance[i]+= 00835 (x-channel_features[BluePixelChannel].sum_entropy[i])* 00836 (x-channel_features[BluePixelChannel].sum_entropy[i])* 00837 density_xy[x].direction[i].blue; 00838 if (image->colorspace == CMYKColorspace) 00839 channel_features[BlackPixelChannel].sum_variance[i]+= 00840 (x-channel_features[BlackPixelChannel].sum_entropy[i])* 00841 (x-channel_features[BlackPixelChannel].sum_entropy[i])* 00842 density_xy[x].direction[i].black; 00843 if (image->matte != MagickFalse) 00844 channel_features[AlphaPixelChannel].sum_variance[i]+= 00845 (x-channel_features[AlphaPixelChannel].sum_entropy[i])* 00846 (x-channel_features[AlphaPixelChannel].sum_entropy[i])* 00847 density_xy[x].direction[i].alpha; 00848 } 00849 } 00850 /* 00851 Compute more texture features. 00852 */ 00853 #if defined(MAGICKCORE_OPENMP_SUPPORT) 00854 #pragma omp parallel for schedule(static,4) shared(status) 00855 #endif 00856 for (i=0; i < 4; i++) 00857 { 00858 register ssize_t 00859 y; 00860 00861 for (y=0; y < (ssize_t) number_grays; y++) 00862 { 00863 register ssize_t 00864 x; 00865 00866 for (x=0; x < (ssize_t) number_grays; x++) 00867 { 00868 /* 00869 Sum of Squares: Variance 00870 */ 00871 variance.direction[i].red+=(y-mean.direction[i].red+1)* 00872 (y-mean.direction[i].red+1)*cooccurrence[x][y].direction[i].red; 00873 variance.direction[i].green+=(y-mean.direction[i].green+1)* 00874 (y-mean.direction[i].green+1)*cooccurrence[x][y].direction[i].green; 00875 variance.direction[i].blue+=(y-mean.direction[i].blue+1)* 00876 (y-mean.direction[i].blue+1)*cooccurrence[x][y].direction[i].blue; 00877 if (image->colorspace == CMYKColorspace) 00878 variance.direction[i].black+=(y-mean.direction[i].black+1)* 00879 (y-mean.direction[i].black+1)*cooccurrence[x][y].direction[i].black; 00880 if (image->matte != MagickFalse) 00881 variance.direction[i].alpha+=(y-mean.direction[i].alpha+1)* 00882 (y-mean.direction[i].alpha+1)* 00883 cooccurrence[x][y].direction[i].alpha; 00884 /* 00885 Sum average / Difference Variance. 00886 */ 00887 density_xy[MagickAbsoluteValue(y-x)].direction[i].red+= 00888 cooccurrence[x][y].direction[i].red; 00889 density_xy[MagickAbsoluteValue(y-x)].direction[i].green+= 00890 cooccurrence[x][y].direction[i].green; 00891 density_xy[MagickAbsoluteValue(y-x)].direction[i].blue+= 00892 cooccurrence[x][y].direction[i].blue; 00893 if (image->colorspace == CMYKColorspace) 00894 density_xy[MagickAbsoluteValue(y-x)].direction[i].black+= 00895 cooccurrence[x][y].direction[i].black; 00896 if (image->matte != MagickFalse) 00897 density_xy[MagickAbsoluteValue(y-x)].direction[i].alpha+= 00898 cooccurrence[x][y].direction[i].alpha; 00899 /* 00900 Information Measures of Correlation. 00901 */ 00902 entropy_xy.direction[i].red-=cooccurrence[x][y].direction[i].red* 00903 log10(cooccurrence[x][y].direction[i].red+MagickEpsilon); 00904 entropy_xy.direction[i].green-=cooccurrence[x][y].direction[i].green* 00905 log10(cooccurrence[x][y].direction[i].green+MagickEpsilon); 00906 entropy_xy.direction[i].blue-=cooccurrence[x][y].direction[i].blue* 00907 log10(cooccurrence[x][y].direction[i].blue+MagickEpsilon); 00908 if (image->colorspace == CMYKColorspace) 00909 entropy_xy.direction[i].black-=cooccurrence[x][y].direction[i].black* 00910 log10(cooccurrence[x][y].direction[i].black+MagickEpsilon); 00911 if (image->matte != MagickFalse) 00912 entropy_xy.direction[i].alpha-= 00913 cooccurrence[x][y].direction[i].alpha*log10( 00914 cooccurrence[x][y].direction[i].alpha+MagickEpsilon); 00915 entropy_xy1.direction[i].red-=(cooccurrence[x][y].direction[i].red* 00916 log10(density_x[x].direction[i].red*density_y[y].direction[i].red+ 00917 MagickEpsilon)); 00918 entropy_xy1.direction[i].green-=(cooccurrence[x][y].direction[i].green* 00919 log10(density_x[x].direction[i].green*density_y[y].direction[i].green+ 00920 MagickEpsilon)); 00921 entropy_xy1.direction[i].blue-=(cooccurrence[x][y].direction[i].blue* 00922 log10(density_x[x].direction[i].blue*density_y[y].direction[i].blue+ 00923 MagickEpsilon)); 00924 if (image->colorspace == CMYKColorspace) 00925 entropy_xy1.direction[i].black-=( 00926 cooccurrence[x][y].direction[i].black*log10( 00927 density_x[x].direction[i].black*density_y[y].direction[i].black+ 00928 MagickEpsilon)); 00929 if (image->matte != MagickFalse) 00930 entropy_xy1.direction[i].alpha-=( 00931 cooccurrence[x][y].direction[i].alpha*log10( 00932 density_x[x].direction[i].alpha*density_y[y].direction[i].alpha+ 00933 MagickEpsilon)); 00934 entropy_xy2.direction[i].red-=(density_x[x].direction[i].red* 00935 density_y[y].direction[i].red*log10(density_x[x].direction[i].red* 00936 density_y[y].direction[i].red+MagickEpsilon)); 00937 entropy_xy2.direction[i].green-=(density_x[x].direction[i].green* 00938 density_y[y].direction[i].green*log10(density_x[x].direction[i].green* 00939 density_y[y].direction[i].green+MagickEpsilon)); 00940 entropy_xy2.direction[i].blue-=(density_x[x].direction[i].blue* 00941 density_y[y].direction[i].blue*log10(density_x[x].direction[i].blue* 00942 density_y[y].direction[i].blue+MagickEpsilon)); 00943 if (image->colorspace == CMYKColorspace) 00944 entropy_xy2.direction[i].black-=(density_x[x].direction[i].black* 00945 density_y[y].direction[i].black*log10( 00946 density_x[x].direction[i].black*density_y[y].direction[i].black+ 00947 MagickEpsilon)); 00948 if (image->matte != MagickFalse) 00949 entropy_xy2.direction[i].alpha-=(density_x[x].direction[i].alpha* 00950 density_y[y].direction[i].alpha*log10( 00951 density_x[x].direction[i].alpha*density_y[y].direction[i].alpha+ 00952 MagickEpsilon)); 00953 } 00954 } 00955 channel_features[RedPixelChannel].variance_sum_of_squares[i]= 00956 variance.direction[i].red; 00957 channel_features[GreenPixelChannel].variance_sum_of_squares[i]= 00958 variance.direction[i].green; 00959 channel_features[BluePixelChannel].variance_sum_of_squares[i]= 00960 variance.direction[i].blue; 00961 if (image->colorspace == CMYKColorspace) 00962 channel_features[BlackPixelChannel].variance_sum_of_squares[i]= 00963 variance.direction[i].black; 00964 if (image->matte != MagickFalse) 00965 channel_features[AlphaPixelChannel].variance_sum_of_squares[i]= 00966 variance.direction[i].alpha; 00967 } 00968 /* 00969 Compute more texture features. 00970 */ 00971 (void) ResetMagickMemory(&variance,0,sizeof(variance)); 00972 (void) ResetMagickMemory(&sum_squares,0,sizeof(sum_squares)); 00973 #if defined(MAGICKCORE_OPENMP_SUPPORT) 00974 #pragma omp parallel for schedule(static,4) shared(status) 00975 #endif 00976 for (i=0; i < 4; i++) 00977 { 00978 register ssize_t 00979 x; 00980 00981 for (x=0; x < (ssize_t) number_grays; x++) 00982 { 00983 /* 00984 Difference variance. 00985 */ 00986 variance.direction[i].red+=density_xy[x].direction[i].red; 00987 variance.direction[i].green+=density_xy[x].direction[i].green; 00988 variance.direction[i].blue+=density_xy[x].direction[i].blue; 00989 if (image->colorspace == CMYKColorspace) 00990 variance.direction[i].black+=density_xy[x].direction[i].black; 00991 if (image->matte != MagickFalse) 00992 variance.direction[i].alpha+=density_xy[x].direction[i].alpha; 00993 sum_squares.direction[i].red+=density_xy[x].direction[i].red* 00994 density_xy[x].direction[i].red; 00995 sum_squares.direction[i].green+=density_xy[x].direction[i].green* 00996 density_xy[x].direction[i].green; 00997 sum_squares.direction[i].blue+=density_xy[x].direction[i].blue* 00998 density_xy[x].direction[i].blue; 00999 if (image->colorspace == CMYKColorspace) 01000 sum_squares.direction[i].black+=density_xy[x].direction[i].black* 01001 density_xy[x].direction[i].black; 01002 if (image->matte != MagickFalse) 01003 sum_squares.direction[i].alpha+=density_xy[x].direction[i].alpha* 01004 density_xy[x].direction[i].alpha; 01005 /* 01006 Difference entropy. 01007 */ 01008 channel_features[RedPixelChannel].difference_entropy[i]-= 01009 density_xy[x].direction[i].red* 01010 log10(density_xy[x].direction[i].red+MagickEpsilon); 01011 channel_features[GreenPixelChannel].difference_entropy[i]-= 01012 density_xy[x].direction[i].green* 01013 log10(density_xy[x].direction[i].green+MagickEpsilon); 01014 channel_features[BluePixelChannel].difference_entropy[i]-= 01015 density_xy[x].direction[i].blue* 01016 log10(density_xy[x].direction[i].blue+MagickEpsilon); 01017 if (image->colorspace == CMYKColorspace) 01018 channel_features[BlackPixelChannel].difference_entropy[i]-= 01019 density_xy[x].direction[i].black* 01020 log10(density_xy[x].direction[i].black+MagickEpsilon); 01021 if (image->matte != MagickFalse) 01022 channel_features[AlphaPixelChannel].difference_entropy[i]-= 01023 density_xy[x].direction[i].alpha* 01024 log10(density_xy[x].direction[i].alpha+MagickEpsilon); 01025 /* 01026 Information Measures of Correlation. 01027 */ 01028 entropy_x.direction[i].red-=(density_x[x].direction[i].red* 01029 log10(density_x[x].direction[i].red+MagickEpsilon)); 01030 entropy_x.direction[i].green-=(density_x[x].direction[i].green* 01031 log10(density_x[x].direction[i].green+MagickEpsilon)); 01032 entropy_x.direction[i].blue-=(density_x[x].direction[i].blue* 01033 log10(density_x[x].direction[i].blue+MagickEpsilon)); 01034 if (image->colorspace == CMYKColorspace) 01035 entropy_x.direction[i].black-=(density_x[x].direction[i].black* 01036 log10(density_x[x].direction[i].black+MagickEpsilon)); 01037 if (image->matte != MagickFalse) 01038 entropy_x.direction[i].alpha-=(density_x[x].direction[i].alpha* 01039 log10(density_x[x].direction[i].alpha+MagickEpsilon)); 01040 entropy_y.direction[i].red-=(density_y[x].direction[i].red* 01041 log10(density_y[x].direction[i].red+MagickEpsilon)); 01042 entropy_y.direction[i].green-=(density_y[x].direction[i].green* 01043 log10(density_y[x].direction[i].green+MagickEpsilon)); 01044 entropy_y.direction[i].blue-=(density_y[x].direction[i].blue* 01045 log10(density_y[x].direction[i].blue+MagickEpsilon)); 01046 if (image->colorspace == CMYKColorspace) 01047 entropy_y.direction[i].black-=(density_y[x].direction[i].black* 01048 log10(density_y[x].direction[i].black+MagickEpsilon)); 01049 if (image->matte != MagickFalse) 01050 entropy_y.direction[i].alpha-=(density_y[x].direction[i].alpha* 01051 log10(density_y[x].direction[i].alpha+MagickEpsilon)); 01052 } 01053 /* 01054 Difference variance. 01055 */ 01056 channel_features[RedPixelChannel].difference_variance[i]= 01057 (((double) number_grays*number_grays*sum_squares.direction[i].red)- 01058 (variance.direction[i].red*variance.direction[i].red))/ 01059 ((double) number_grays*number_grays*number_grays*number_grays); 01060 channel_features[GreenPixelChannel].difference_variance[i]= 01061 (((double) number_grays*number_grays*sum_squares.direction[i].green)- 01062 (variance.direction[i].green*variance.direction[i].green))/ 01063 ((double) number_grays*number_grays*number_grays*number_grays); 01064 channel_features[BluePixelChannel].difference_variance[i]= 01065 (((double) number_grays*number_grays*sum_squares.direction[i].blue)- 01066 (variance.direction[i].blue*variance.direction[i].blue))/ 01067 ((double) number_grays*number_grays*number_grays*number_grays); 01068 if (image->colorspace == CMYKColorspace) 01069 channel_features[BlackPixelChannel].difference_variance[i]= 01070 (((double) number_grays*number_grays*sum_squares.direction[i].black)- 01071 (variance.direction[i].black*variance.direction[i].black))/ 01072 ((double) number_grays*number_grays*number_grays*number_grays); 01073 if (image->matte != MagickFalse) 01074 channel_features[AlphaPixelChannel].difference_variance[i]= 01075 (((double) number_grays*number_grays*sum_squares.direction[i].alpha)- 01076 (variance.direction[i].alpha*variance.direction[i].alpha))/ 01077 ((double) number_grays*number_grays*number_grays*number_grays); 01078 /* 01079 Information Measures of Correlation. 01080 */ 01081 channel_features[RedPixelChannel].measure_of_correlation_1[i]= 01082 (entropy_xy.direction[i].red-entropy_xy1.direction[i].red)/ 01083 (entropy_x.direction[i].red > entropy_y.direction[i].red ? 01084 entropy_x.direction[i].red : entropy_y.direction[i].red); 01085 channel_features[GreenPixelChannel].measure_of_correlation_1[i]= 01086 (entropy_xy.direction[i].green-entropy_xy1.direction[i].green)/ 01087 (entropy_x.direction[i].green > entropy_y.direction[i].green ? 01088 entropy_x.direction[i].green : entropy_y.direction[i].green); 01089 channel_features[BluePixelChannel].measure_of_correlation_1[i]= 01090 (entropy_xy.direction[i].blue-entropy_xy1.direction[i].blue)/ 01091 (entropy_x.direction[i].blue > entropy_y.direction[i].blue ? 01092 entropy_x.direction[i].blue : entropy_y.direction[i].blue); 01093 if (image->colorspace == CMYKColorspace) 01094 channel_features[BlackPixelChannel].measure_of_correlation_1[i]= 01095 (entropy_xy.direction[i].black-entropy_xy1.direction[i].black)/ 01096 (entropy_x.direction[i].black > entropy_y.direction[i].black ? 01097 entropy_x.direction[i].black : entropy_y.direction[i].black); 01098 if (image->matte != MagickFalse) 01099 channel_features[AlphaPixelChannel].measure_of_correlation_1[i]= 01100 (entropy_xy.direction[i].alpha-entropy_xy1.direction[i].alpha)/ 01101 (entropy_x.direction[i].alpha > entropy_y.direction[i].alpha ? 01102 entropy_x.direction[i].alpha : entropy_y.direction[i].alpha); 01103 channel_features[RedPixelChannel].measure_of_correlation_2[i]= 01104 (sqrt(fabs(1.0-exp(-2.0*(entropy_xy2.direction[i].red- 01105 entropy_xy.direction[i].red))))); 01106 channel_features[GreenPixelChannel].measure_of_correlation_2[i]= 01107 (sqrt(fabs(1.0-exp(-2.0*(entropy_xy2.direction[i].green- 01108 entropy_xy.direction[i].green))))); 01109 channel_features[BluePixelChannel].measure_of_correlation_2[i]= 01110 (sqrt(fabs(1.0-exp(-2.0*(entropy_xy2.direction[i].blue- 01111 entropy_xy.direction[i].blue))))); 01112 if (image->colorspace == CMYKColorspace) 01113 channel_features[BlackPixelChannel].measure_of_correlation_2[i]= 01114 (sqrt(fabs(1.0-exp(-2.0*(entropy_xy2.direction[i].black- 01115 entropy_xy.direction[i].black))))); 01116 if (image->matte != MagickFalse) 01117 channel_features[AlphaPixelChannel].measure_of_correlation_2[i]= 01118 (sqrt(fabs(1.0-exp(-2.0*(entropy_xy2.direction[i].alpha- 01119 entropy_xy.direction[i].alpha))))); 01120 } 01121 /* 01122 Compute more texture features. 01123 */ 01124 #if defined(MAGICKCORE_OPENMP_SUPPORT) 01125 #pragma omp parallel for schedule(static,4) shared(status) 01126 #endif 01127 for (i=0; i < 4; i++) 01128 { 01129 ssize_t 01130 z; 01131 01132 for (z=0; z < (ssize_t) number_grays; z++) 01133 { 01134 register ssize_t 01135 y; 01136 01137 ChannelStatistics 01138 pixel; 01139 01140 (void) ResetMagickMemory(&pixel,0,sizeof(pixel)); 01141 for (y=0; y < (ssize_t) number_grays; y++) 01142 { 01143 register ssize_t 01144 x; 01145 01146 for (x=0; x < (ssize_t) number_grays; x++) 01147 { 01148 /* 01149 Contrast: amount of local variations present in an image. 01150 */ 01151 if (((y-x) == z) || ((x-y) == z)) 01152 { 01153 pixel.direction[i].red+=cooccurrence[x][y].direction[i].red; 01154 pixel.direction[i].green+=cooccurrence[x][y].direction[i].green; 01155 pixel.direction[i].blue+=cooccurrence[x][y].direction[i].blue; 01156 if (image->colorspace == CMYKColorspace) 01157 pixel.direction[i].black+=cooccurrence[x][y].direction[i].black; 01158 if (image->matte != MagickFalse) 01159 pixel.direction[i].alpha+= 01160 cooccurrence[x][y].direction[i].alpha; 01161 } 01162 /* 01163 Maximum Correlation Coefficient. 01164 */ 01165 Q[z][y].direction[i].red+=cooccurrence[z][x].direction[i].red* 01166 cooccurrence[y][x].direction[i].red/density_x[z].direction[i].red/ 01167 density_y[x].direction[i].red; 01168 Q[z][y].direction[i].green+=cooccurrence[z][x].direction[i].green* 01169 cooccurrence[y][x].direction[i].green/ 01170 density_x[z].direction[i].green/density_y[x].direction[i].red; 01171 Q[z][y].direction[i].blue+=cooccurrence[z][x].direction[i].blue* 01172 cooccurrence[y][x].direction[i].blue/density_x[z].direction[i].blue/ 01173 density_y[x].direction[i].blue; 01174 if (image->colorspace == CMYKColorspace) 01175 Q[z][y].direction[i].black+=cooccurrence[z][x].direction[i].black* 01176 cooccurrence[y][x].direction[i].black/ 01177 density_x[z].direction[i].black/density_y[x].direction[i].black; 01178 if (image->matte != MagickFalse) 01179 Q[z][y].direction[i].alpha+= 01180 cooccurrence[z][x].direction[i].alpha* 01181 cooccurrence[y][x].direction[i].alpha/ 01182 density_x[z].direction[i].alpha/ 01183 density_y[x].direction[i].alpha; 01184 } 01185 } 01186 channel_features[RedPixelChannel].contrast[i]+=z*z* 01187 pixel.direction[i].red; 01188 channel_features[GreenPixelChannel].contrast[i]+=z*z* 01189 pixel.direction[i].green; 01190 channel_features[BluePixelChannel].contrast[i]+=z*z* 01191 pixel.direction[i].blue; 01192 if (image->colorspace == CMYKColorspace) 01193 channel_features[BlackPixelChannel].contrast[i]+=z*z* 01194 pixel.direction[i].black; 01195 if (image->matte != MagickFalse) 01196 channel_features[AlphaPixelChannel].contrast[i]+=z*z* 01197 pixel.direction[i].alpha; 01198 } 01199 /* 01200 Maximum Correlation Coefficient. 01201 Future: return second largest eigenvalue of Q. 01202 */ 01203 channel_features[RedPixelChannel].maximum_correlation_coefficient[i]= 01204 sqrt((double) -1.0); 01205 channel_features[GreenPixelChannel].maximum_correlation_coefficient[i]= 01206 sqrt((double) -1.0); 01207 channel_features[BluePixelChannel].maximum_correlation_coefficient[i]= 01208 sqrt((double) -1.0); 01209 if (image->colorspace == CMYKColorspace) 01210 channel_features[BlackPixelChannel].maximum_correlation_coefficient[i]= 01211 sqrt((double) -1.0); 01212 if (image->matte != MagickFalse) 01213 channel_features[AlphaPixelChannel].maximum_correlation_coefficient[i]= 01214 sqrt((double) -1.0); 01215 } 01216 /* 01217 Relinquish resources. 01218 */ 01219 sum=(ChannelStatistics *) RelinquishMagickMemory(sum); 01220 for (i=0; i < (ssize_t) number_grays; i++) 01221 Q[i]=(ChannelStatistics *) RelinquishMagickMemory(Q[i]); 01222 Q=(ChannelStatistics **) RelinquishMagickMemory(Q); 01223 density_y=(ChannelStatistics *) RelinquishMagickMemory(density_y); 01224 density_xy=(ChannelStatistics *) RelinquishMagickMemory(density_xy); 01225 density_x=(ChannelStatistics *) RelinquishMagickMemory(density_x); 01226 for (i=0; i < (ssize_t) number_grays; i++) 01227 cooccurrence[i]=(ChannelStatistics *) 01228 RelinquishMagickMemory(cooccurrence[i]); 01229 cooccurrence=(ChannelStatistics **) RelinquishMagickMemory(cooccurrence); 01230 return(channel_features); 01231 }