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