feature.c revision 05d2ff7ebf21f659f5b11e45afb294e152f4330c
13e2860cb0796fe77659325ec3d540d8766d54f49cristy/* 23e2860cb0796fe77659325ec3d540d8766d54f49cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 33e2860cb0796fe77659325ec3d540d8766d54f49cristy% % 43e2860cb0796fe77659325ec3d540d8766d54f49cristy% % 53e2860cb0796fe77659325ec3d540d8766d54f49cristy% % 63e2860cb0796fe77659325ec3d540d8766d54f49cristy% FFFFF EEEEE AAA TTTTT U U RRRR EEEEE % 73e2860cb0796fe77659325ec3d540d8766d54f49cristy% F E A A T U U R R E % 83e2860cb0796fe77659325ec3d540d8766d54f49cristy% FFF EEE AAAAA T U U RRRR EEE % 93e2860cb0796fe77659325ec3d540d8766d54f49cristy% F E A A T U U R R E % 103e2860cb0796fe77659325ec3d540d8766d54f49cristy% F EEEEE A A T UUU R R EEEEE % 113e2860cb0796fe77659325ec3d540d8766d54f49cristy% % 123e2860cb0796fe77659325ec3d540d8766d54f49cristy% % 133e2860cb0796fe77659325ec3d540d8766d54f49cristy% MagickCore Image Feature Methods % 143e2860cb0796fe77659325ec3d540d8766d54f49cristy% % 153e2860cb0796fe77659325ec3d540d8766d54f49cristy% Software Design % 16de984cdc3631106b1cbbb8d3972b76a0fc27e8e8cristy% Cristy % 173e2860cb0796fe77659325ec3d540d8766d54f49cristy% July 1992 % 183e2860cb0796fe77659325ec3d540d8766d54f49cristy% % 193e2860cb0796fe77659325ec3d540d8766d54f49cristy% % 20b56bb24a985ca4366713bcd8ffdfacbb48a98a2fcristy% Copyright 1999-2015 ImageMagick Studio LLC, a non-profit organization % 213e2860cb0796fe77659325ec3d540d8766d54f49cristy% dedicated to making software imaging solutions freely available. % 223e2860cb0796fe77659325ec3d540d8766d54f49cristy% % 233e2860cb0796fe77659325ec3d540d8766d54f49cristy% You may not use this file except in compliance with the License. You may % 243e2860cb0796fe77659325ec3d540d8766d54f49cristy% obtain a copy of the License at % 253e2860cb0796fe77659325ec3d540d8766d54f49cristy% % 263e2860cb0796fe77659325ec3d540d8766d54f49cristy% http://www.imagemagick.org/script/license.php % 273e2860cb0796fe77659325ec3d540d8766d54f49cristy% % 283e2860cb0796fe77659325ec3d540d8766d54f49cristy% Unless required by applicable law or agreed to in writing, software % 293e2860cb0796fe77659325ec3d540d8766d54f49cristy% distributed under the License is distributed on an "AS IS" BASIS, % 303e2860cb0796fe77659325ec3d540d8766d54f49cristy% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. % 313e2860cb0796fe77659325ec3d540d8766d54f49cristy% See the License for the specific language governing permissions and % 323e2860cb0796fe77659325ec3d540d8766d54f49cristy% limitations under the License. % 333e2860cb0796fe77659325ec3d540d8766d54f49cristy% % 343e2860cb0796fe77659325ec3d540d8766d54f49cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 353e2860cb0796fe77659325ec3d540d8766d54f49cristy% 363e2860cb0796fe77659325ec3d540d8766d54f49cristy% 373e2860cb0796fe77659325ec3d540d8766d54f49cristy% 383e2860cb0796fe77659325ec3d540d8766d54f49cristy*/ 393e2860cb0796fe77659325ec3d540d8766d54f49cristy 403e2860cb0796fe77659325ec3d540d8766d54f49cristy/* 413e2860cb0796fe77659325ec3d540d8766d54f49cristy Include declarations. 423e2860cb0796fe77659325ec3d540d8766d54f49cristy*/ 434c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/studio.h" 444c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/animate.h" 450f09a8ceb30556f22c8800ed7ff8faa260e4f6dccristy#include "MagickCore/artifact.h" 464c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/blob.h" 474c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/blob-private.h" 484c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/cache.h" 494c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/cache-private.h" 504c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/cache-view.h" 5131e75937db91fd53e7deb9e3544646d0459f2196cristy#include "MagickCore/channel.h" 524c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/client.h" 534c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/color.h" 544c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/color-private.h" 554c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/colorspace.h" 564c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/colorspace-private.h" 574c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/composite.h" 584c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/composite-private.h" 594c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/compress.h" 604c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/constitute.h" 614c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/display.h" 624c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/draw.h" 634c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/enhance.h" 644c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/exception.h" 654c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/exception-private.h" 664c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/feature.h" 674c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/gem.h" 684c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/geometry.h" 694c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/list.h" 704c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/image-private.h" 714c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/magic.h" 724c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/magick.h" 73c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy#include "MagickCore/matrix.h" 744c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/memory_.h" 754c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/module.h" 764c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/monitor.h" 774c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/monitor-private.h" 78c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy#include "MagickCore/morphology-private.h" 794c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/option.h" 804c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/paint.h" 814c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/pixel-accessor.h" 824c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/profile.h" 830f09a8ceb30556f22c8800ed7ff8faa260e4f6dccristy#include "MagickCore/property.h" 844c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/quantize.h" 854c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/quantum-private.h" 864c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/random_.h" 87ac245f8a51ea65b085d751c41d8ca4b426bdfe5bcristy#include "MagickCore/resource_.h" 884c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/segment.h" 894c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/semaphore.h" 904c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/signature-private.h" 914c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/string_.h" 924c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/thread-private.h" 934c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/timer.h" 944c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/utility.h" 954c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/version.h" 963e2860cb0796fe77659325ec3d540d8766d54f49cristy 973e2860cb0796fe77659325ec3d540d8766d54f49cristy/* 983e2860cb0796fe77659325ec3d540d8766d54f49cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 993e2860cb0796fe77659325ec3d540d8766d54f49cristy% % 1003e2860cb0796fe77659325ec3d540d8766d54f49cristy% % 1013e2860cb0796fe77659325ec3d540d8766d54f49cristy% % 102c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy% C a n n y E d g e I m a g e % 103c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy% % 104c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy% % 105c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy% % 106c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 107c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy% 108c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy% CannyEdgeImage() uses a multi-stage algorithm to detect a wide range of 109c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy% edges in images. 110c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy% 111233483c36e4f75e4337766b87cae1ab13d8b92a8cristy% The format of the CannyEdgeImage method is: 112c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy% 113c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy% Image *CannyEdgeImage(const Image *image,const double radius, 114c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy% const double sigma,const double lower_percent, 115c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy% const double upper_percent,ExceptionInfo *exception) 116c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy% 117c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy% A description of each parameter follows: 118c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy% 119c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy% o image: the image. 120c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy% 121c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy% o radius: the radius of the gaussian smoothing filter. 122c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy% 123c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy% o sigma: the sigma of the gaussian smoothing filter. 124c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy% 125c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy% o lower_precent: percentage of edge pixels in the lower threshold. 126c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy% 127c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy% o upper_percent: percentage of edge pixels in the upper threshold. 128c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy% 129c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy% o exception: return any errors or warnings in this structure. 130c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy% 131c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy*/ 132c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy 133c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristytypedef struct _CannyInfo 134c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy{ 135c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy double 136c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy magnitude, 137c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy intensity; 138c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy 139c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy int 140c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy orientation; 141c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy 142c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy ssize_t 143c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy x, 144c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy y; 145c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy} CannyInfo; 146c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy 147c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristystatic inline MagickBooleanType IsAuthenticPixel(const Image *image, 148c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy const ssize_t x,const ssize_t y) 149c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy{ 150c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy if ((x < 0) || (x >= (ssize_t) image->columns)) 151c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy return(MagickFalse); 152c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy if ((y < 0) || (y >= (ssize_t) image->rows)) 153c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy return(MagickFalse); 154c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy return(MagickTrue); 155c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy} 156c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy 157c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristystatic MagickBooleanType TraceEdges(Image *edge_image,CacheView *edge_view, 158c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy MatrixInfo *canny_cache,const ssize_t x,const ssize_t y, 159c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy const double lower_threshold,ExceptionInfo *exception) 160c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy{ 161c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy CannyInfo 162c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy edge, 163c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy pixel; 164c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy 165c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy MagickBooleanType 166c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy status; 167c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy 168c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy register Quantum 169c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy *q; 170c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy 171c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy register ssize_t 172c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy i; 173c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy 174c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy q=GetCacheViewAuthenticPixels(edge_view,x,y,1,1,exception); 175c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy if (q == (Quantum *) NULL) 176c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy return(MagickFalse); 177c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy *q=QuantumRange; 178c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy status=SyncCacheViewAuthenticPixels(edge_view,exception); 179c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy if (status == MagickFalse) 180c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy return(MagickFalse);; 181c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy if (GetMatrixElement(canny_cache,0,0,&edge) == MagickFalse) 182c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy return(MagickFalse); 183c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy edge.x=x; 184c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy edge.y=y; 185c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy if (SetMatrixElement(canny_cache,0,0,&edge) == MagickFalse) 186c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy return(MagickFalse); 187c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy for (i=1; i != 0; ) 188c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy { 189c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy ssize_t 190c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy v; 191c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy 192c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy i--; 193c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy status=GetMatrixElement(canny_cache,i,0,&edge); 194c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy if (status == MagickFalse) 195c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy return(MagickFalse); 196c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy for (v=(-1); v <= 1; v++) 197c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy { 198c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy ssize_t 199c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy u; 200c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy 201c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy for (u=(-1); u <= 1; u++) 202c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy { 203c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy if ((u == 0) && (v == 0)) 204c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy continue; 205c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy if (IsAuthenticPixel(edge_image,edge.x+u,edge.y+v) == MagickFalse) 206c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy continue; 207c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy /* 208c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy Not an edge if gradient value is below the lower threshold. 209c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy */ 210c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy q=GetCacheViewAuthenticPixels(edge_view,edge.x+u,edge.y+v,1,1, 211c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy exception); 212c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy if (q == (Quantum *) NULL) 213c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy return(MagickFalse); 214c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy status=GetMatrixElement(canny_cache,edge.x+u,edge.y+v,&pixel); 215c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy if (status == MagickFalse) 216c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy return(MagickFalse); 217c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy if ((GetPixelIntensity(edge_image,q) == 0.0) && 218c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy (pixel.intensity >= lower_threshold)) 219c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy { 220c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy *q=QuantumRange; 221c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy status=SyncCacheViewAuthenticPixels(edge_view,exception); 222c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy if (status == MagickFalse) 223c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy return(MagickFalse); 224c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy edge.x+=u; 225c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy edge.y+=v; 226c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy status=SetMatrixElement(canny_cache,i,0,&edge); 227c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy if (status == MagickFalse) 228c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy return(MagickFalse); 229c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy i++; 230c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy } 231c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy } 232c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy } 233c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy } 234c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy return(MagickTrue); 235c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy} 236c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy 237c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristyMagickExport Image *CannyEdgeImage(const Image *image,const double radius, 238c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy const double sigma,const double lower_percent,const double upper_percent, 239c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy ExceptionInfo *exception) 240c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy{ 2418fbcf1ad6a1d07a92ef39435f679143697be4edacristy#define CannyEdgeImageTag "CannyEdge/Image" 2428fbcf1ad6a1d07a92ef39435f679143697be4edacristy 243c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy CacheView 244c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy *edge_view; 245c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy 246c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy CannyInfo 247aa6a11c893e812e2b1f1c425353eaf72d3501a9edirk element; 248c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy 249c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy char 250151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy geometry[MagickPathExtent]; 251c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy 252c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy double 253c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy lower_threshold, 254c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy max, 255c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy min, 256c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy upper_threshold; 257c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy 258c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy Image 259c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy *edge_image; 260c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy 261c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy KernelInfo 262c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy *kernel_info; 263c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy 264c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy MagickBooleanType 265c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy status; 266c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy 2678fbcf1ad6a1d07a92ef39435f679143697be4edacristy MagickOffsetType 2688fbcf1ad6a1d07a92ef39435f679143697be4edacristy progress; 2698fbcf1ad6a1d07a92ef39435f679143697be4edacristy 270c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy MatrixInfo 271c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy *canny_cache; 272c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy 273c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy ssize_t 274c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy y; 275c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy 276c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy assert(image != (const Image *) NULL); 277e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy assert(image->signature == MagickCoreSignature); 278c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy if (image->debug != MagickFalse) 279c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 280c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy assert(exception != (ExceptionInfo *) NULL); 281e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy assert(exception->signature == MagickCoreSignature); 282c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy /* 283c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy Filter out noise. 284c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy */ 285151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy (void) FormatLocaleString(geometry,MagickPathExtent, 286c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy "blur:%.20gx%.20g;blur:%.20gx%.20g+90",radius,sigma,radius,sigma); 2872c57b74e160f9b605d74dec24081309f28b83899cristy kernel_info=AcquireKernelInfo(geometry,exception); 288c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy if (kernel_info == (KernelInfo *) NULL) 289c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy ThrowImageException(ResourceLimitError,"MemoryAllocationFailed"); 290c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy edge_image=MorphologyApply(image,ConvolveMorphology,1,kernel_info, 291c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy UndefinedCompositeOp,0.0,exception); 292c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy kernel_info=DestroyKernelInfo(kernel_info); 293c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy if (edge_image == (Image *) NULL) 294c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy return((Image *) NULL); 295c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy if (SetImageColorspace(edge_image,GRAYColorspace,exception) == MagickFalse) 296c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy { 297c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy edge_image=DestroyImage(edge_image); 298c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy return((Image *) NULL); 299c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy } 30031e75937db91fd53e7deb9e3544646d0459f2196cristy (void) SetImageAlphaChannel(edge_image,OffAlphaChannel,exception); 301c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy /* 302c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy Find the intensity gradient of the image. 303c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy */ 304c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy canny_cache=AcquireMatrixInfo(edge_image->columns,edge_image->rows, 305c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy sizeof(CannyInfo),exception); 306c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy if (canny_cache == (MatrixInfo *) NULL) 307c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy { 308c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy edge_image=DestroyImage(edge_image); 309c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy return((Image *) NULL); 310c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy } 311c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy status=MagickTrue; 312c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy edge_view=AcquireVirtualCacheView(edge_image,exception); 313c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy#if defined(MAGICKCORE_OPENMP_SUPPORT) 314c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy #pragma omp parallel for schedule(static,4) shared(status) \ 315c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy magick_threads(edge_image,edge_image,edge_image->rows,1) 316c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy#endif 317c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy for (y=0; y < (ssize_t) edge_image->rows; y++) 318c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy { 319c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy register const Quantum 32005d2ff7ebf21f659f5b11e45afb294e152f4330cdirk *magick_restrict p; 321c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy 322c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy register ssize_t 323c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy x; 324c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy 325c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy if (status == MagickFalse) 326c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy continue; 327c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy p=GetCacheViewVirtualPixels(edge_view,0,y,edge_image->columns+1,2, 328c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy exception); 329c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy if (p == (const Quantum *) NULL) 330c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy { 331c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy status=MagickFalse; 332c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy continue; 333c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy } 334c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy for (x=0; x < (ssize_t) edge_image->columns; x++) 335c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy { 336c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy CannyInfo 337c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy pixel; 338c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy 339c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy double 340c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy dx, 341c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy dy; 342c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy 343c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy register const Quantum 34405d2ff7ebf21f659f5b11e45afb294e152f4330cdirk *magick_restrict kernel_pixels; 345c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy 346c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy ssize_t 347c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy v; 348c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy 349c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy static double 350c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy Gx[2][2] = 351c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy { 352c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy { -1.0, +1.0 }, 353c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy { -1.0, +1.0 } 354c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy }, 355c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy Gy[2][2] = 356c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy { 357c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy { +1.0, +1.0 }, 358c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy { -1.0, -1.0 } 359c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy }; 360c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy 361c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy (void) ResetMagickMemory(&pixel,0,sizeof(pixel)); 362c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy dx=0.0; 363c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy dy=0.0; 364c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy kernel_pixels=p; 365c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy for (v=0; v < 2; v++) 366c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy { 367c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy ssize_t 368c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy u; 369c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy 370c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy for (u=0; u < 2; u++) 371c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy { 372c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy double 373c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy intensity; 374c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy 375c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy intensity=GetPixelIntensity(edge_image,kernel_pixels+u); 376c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy dx+=0.5*Gx[v][u]*intensity; 377c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy dy+=0.5*Gy[v][u]*intensity; 378c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy } 379c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy kernel_pixels+=edge_image->columns+1; 380c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy } 381c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy pixel.magnitude=hypot(dx,dy); 382c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy pixel.orientation=0; 383c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy if (fabs(dx) > MagickEpsilon) 384c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy { 385c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy double 386c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy slope; 387c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy 388c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy slope=dy/dx; 389c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy if (slope < 0.0) 390c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy { 391c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy if (slope < -2.41421356237) 392c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy pixel.orientation=0; 393c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy else 394c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy if (slope < -0.414213562373) 395c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy pixel.orientation=1; 396c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy else 397c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy pixel.orientation=2; 398c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy } 399c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy else 400c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy { 401c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy if (slope > 2.41421356237) 402c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy pixel.orientation=0; 403c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy else 404c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy if (slope > 0.414213562373) 405c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy pixel.orientation=3; 406c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy else 407c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy pixel.orientation=2; 408c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy } 409c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy } 410c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy if (SetMatrixElement(canny_cache,x,y,&pixel) == MagickFalse) 411c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy continue; 412c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy p+=GetPixelChannels(edge_image); 413c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy } 414c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy } 415c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy edge_view=DestroyCacheView(edge_view); 416c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy /* 417c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy Non-maxima suppression, remove pixels that are not considered to be part 418c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy of an edge. 419c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy */ 4208fbcf1ad6a1d07a92ef39435f679143697be4edacristy progress=0; 421aa6a11c893e812e2b1f1c425353eaf72d3501a9edirk (void) GetMatrixElement(canny_cache,0,0,&element); 422aa6a11c893e812e2b1f1c425353eaf72d3501a9edirk max=element.intensity; 423aa6a11c893e812e2b1f1c425353eaf72d3501a9edirk min=element.intensity; 424c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy edge_view=AcquireAuthenticCacheView(edge_image,exception); 425c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy#if defined(MAGICKCORE_OPENMP_SUPPORT) 426c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy #pragma omp parallel for schedule(static,4) shared(status) \ 427c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy magick_threads(edge_image,edge_image,edge_image->rows,1) 428c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy#endif 429c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy for (y=0; y < (ssize_t) edge_image->rows; y++) 430c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy { 431c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy register Quantum 43205d2ff7ebf21f659f5b11e45afb294e152f4330cdirk *magick_restrict q; 433c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy 434c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy register ssize_t 435c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy x; 436c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy 437c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy if (status == MagickFalse) 438c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy continue; 439c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy q=GetCacheViewAuthenticPixels(edge_view,0,y,edge_image->columns,1, 440c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy exception); 441c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy if (q == (Quantum *) NULL) 442c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy { 443c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy status=MagickFalse; 444c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy continue; 445c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy } 446c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy for (x=0; x < (ssize_t) edge_image->columns; x++) 447c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy { 448c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy CannyInfo 449c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy alpha_pixel, 450c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy beta_pixel, 451c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy pixel; 452c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy 453c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy (void) GetMatrixElement(canny_cache,x,y,&pixel); 454c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy switch (pixel.orientation) 455c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy { 456c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy case 0: 457b6ecf44155ec6e79fac7d9c51ed5f56962f6eda4dirk default: 458c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy { 459c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy /* 460c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy 0 degrees, north and south. 461c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy */ 462c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy (void) GetMatrixElement(canny_cache,x,y-1,&alpha_pixel); 463c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy (void) GetMatrixElement(canny_cache,x,y+1,&beta_pixel); 464c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy break; 465c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy } 466c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy case 1: 467c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy { 468c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy /* 469c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy 45 degrees, northwest and southeast. 470c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy */ 471c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy (void) GetMatrixElement(canny_cache,x-1,y-1,&alpha_pixel); 472c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy (void) GetMatrixElement(canny_cache,x+1,y+1,&beta_pixel); 473c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy break; 474c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy } 475c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy case 2: 476c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy { 477c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy /* 478c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy 90 degrees, east and west. 479c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy */ 480c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy (void) GetMatrixElement(canny_cache,x-1,y,&alpha_pixel); 481c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy (void) GetMatrixElement(canny_cache,x+1,y,&beta_pixel); 482c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy break; 483c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy } 484c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy case 3: 485c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy { 486c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy /* 487c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy 135 degrees, northeast and southwest. 488c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy */ 489c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy (void) GetMatrixElement(canny_cache,x+1,y-1,&beta_pixel); 490c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy (void) GetMatrixElement(canny_cache,x-1,y+1,&alpha_pixel); 491c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy break; 492c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy } 493c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy } 494c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy pixel.intensity=pixel.magnitude; 495c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy if ((pixel.magnitude < alpha_pixel.magnitude) || 496c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy (pixel.magnitude < beta_pixel.magnitude)) 497c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy pixel.intensity=0; 498c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy (void) SetMatrixElement(canny_cache,x,y,&pixel); 499c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy#if defined(MAGICKCORE_OPENMP_SUPPORT) 500c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy #pragma omp critical (MagickCore_CannyEdgeImage) 501c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy#endif 502c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy { 503c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy if (pixel.intensity < min) 504c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy min=pixel.intensity; 505c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy if (pixel.intensity > max) 506c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy max=pixel.intensity; 507c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy } 508c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy *q=0; 509c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy q+=GetPixelChannels(edge_image); 510c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy } 511c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy if (SyncCacheViewAuthenticPixels(edge_view,exception) == MagickFalse) 512c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy status=MagickFalse; 513c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy } 514c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy edge_view=DestroyCacheView(edge_view); 515c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy /* 516c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy Estimate hysteresis threshold. 517c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy */ 518c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy lower_threshold=lower_percent*(max-min)+min; 519c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy upper_threshold=upper_percent*(max-min)+min; 520c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy /* 521c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy Hysteresis threshold. 522c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy */ 523c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy edge_view=AcquireAuthenticCacheView(edge_image,exception); 524c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy for (y=0; y < (ssize_t) edge_image->rows; y++) 525c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy { 526c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy register ssize_t 527c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy x; 528c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy 529c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy if (status == MagickFalse) 530c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy continue; 531c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy for (x=0; x < (ssize_t) edge_image->columns; x++) 532c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy { 533c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy CannyInfo 534c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy pixel; 535c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy 536c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy register const Quantum 53705d2ff7ebf21f659f5b11e45afb294e152f4330cdirk *magick_restrict p; 538c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy 539c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy /* 540c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy Edge if pixel gradient higher than upper threshold. 541c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy */ 542c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy p=GetCacheViewVirtualPixels(edge_view,x,y,1,1,exception); 543c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy if (p == (const Quantum *) NULL) 544c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy continue; 545c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy status=GetMatrixElement(canny_cache,x,y,&pixel); 546c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy if (status == MagickFalse) 547c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy continue; 548c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy if ((GetPixelIntensity(edge_image,p) == 0.0) && 549c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy (pixel.intensity >= upper_threshold)) 550c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy status=TraceEdges(edge_image,edge_view,canny_cache,x,y,lower_threshold, 551c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy exception); 552c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy } 5538fbcf1ad6a1d07a92ef39435f679143697be4edacristy if (image->progress_monitor != (MagickProgressMonitor) NULL) 5548fbcf1ad6a1d07a92ef39435f679143697be4edacristy { 5558fbcf1ad6a1d07a92ef39435f679143697be4edacristy MagickBooleanType 5568fbcf1ad6a1d07a92ef39435f679143697be4edacristy proceed; 5578fbcf1ad6a1d07a92ef39435f679143697be4edacristy 5588fbcf1ad6a1d07a92ef39435f679143697be4edacristy#if defined(MAGICKCORE_OPENMP_SUPPORT) 5598fbcf1ad6a1d07a92ef39435f679143697be4edacristy #pragma omp critical (MagickCore_CannyEdgeImage) 5608fbcf1ad6a1d07a92ef39435f679143697be4edacristy#endif 5618fbcf1ad6a1d07a92ef39435f679143697be4edacristy proceed=SetImageProgress(image,CannyEdgeImageTag,progress++, 5628fbcf1ad6a1d07a92ef39435f679143697be4edacristy image->rows); 5638fbcf1ad6a1d07a92ef39435f679143697be4edacristy if (proceed == MagickFalse) 5648fbcf1ad6a1d07a92ef39435f679143697be4edacristy status=MagickFalse; 5658fbcf1ad6a1d07a92ef39435f679143697be4edacristy } 566c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy } 567c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy edge_view=DestroyCacheView(edge_view); 568c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy /* 569c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy Free resources. 570c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy */ 571c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy canny_cache=DestroyMatrixInfo(canny_cache); 572c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy return(edge_image); 573c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy} 574c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy 575c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy/* 576c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 577c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy% % 578c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy% % 579c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy% % 5802fc10e5aedab9144531a4668dc7526e3caf514e1cristy% G e t I m a g e F e a t u r e s % 581c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy% % 582c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy% % 583c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy% % 584c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 585c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy% 5862fc10e5aedab9144531a4668dc7526e3caf514e1cristy% GetImageFeatures() returns features for each channel in the image in 5872fc10e5aedab9144531a4668dc7526e3caf514e1cristy% each of four directions (horizontal, vertical, left and right diagonals) 5882fc10e5aedab9144531a4668dc7526e3caf514e1cristy% for the specified distance. The features include the angular second 5892fc10e5aedab9144531a4668dc7526e3caf514e1cristy% moment, contrast, correlation, sum of squares: variance, inverse difference 5902fc10e5aedab9144531a4668dc7526e3caf514e1cristy% moment, sum average, sum varience, sum entropy, entropy, difference variance,% difference entropy, information measures of correlation 1, information 5912fc10e5aedab9144531a4668dc7526e3caf514e1cristy% measures of correlation 2, and maximum correlation coefficient. You can 5922fc10e5aedab9144531a4668dc7526e3caf514e1cristy% access the red channel contrast, for example, like this: 5932fc10e5aedab9144531a4668dc7526e3caf514e1cristy% 5942fc10e5aedab9144531a4668dc7526e3caf514e1cristy% channel_features=GetImageFeatures(image,1,exception); 5952fc10e5aedab9144531a4668dc7526e3caf514e1cristy% contrast=channel_features[RedPixelChannel].contrast[0]; 5962fc10e5aedab9144531a4668dc7526e3caf514e1cristy% 5972fc10e5aedab9144531a4668dc7526e3caf514e1cristy% Use MagickRelinquishMemory() to free the features buffer. 598c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy% 5992fc10e5aedab9144531a4668dc7526e3caf514e1cristy% The format of the GetImageFeatures method is: 600c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy% 6012fc10e5aedab9144531a4668dc7526e3caf514e1cristy% ChannelFeatures *GetImageFeatures(const Image *image, 6022fc10e5aedab9144531a4668dc7526e3caf514e1cristy% const size_t distance,ExceptionInfo *exception) 603c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy% 604c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy% A description of each parameter follows: 605c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy% 606c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy% o image: the image. 607c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy% 6082fc10e5aedab9144531a4668dc7526e3caf514e1cristy% o distance: the distance. 609c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy% 610c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy% o exception: return any errors or warnings in this structure. 611c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy% 612c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy*/ 6130f09a8ceb30556f22c8800ed7ff8faa260e4f6dccristy 6142fc10e5aedab9144531a4668dc7526e3caf514e1cristystatic inline double MagickLog10(const double x) 615c1510626cf0bd77ecc1a9681bd1e0f599108d1b3cristy{ 6162fc10e5aedab9144531a4668dc7526e3caf514e1cristy#define Log10Epsilon (1.0e-11) 6170f09a8ceb30556f22c8800ed7ff8faa260e4f6dccristy 6182fc10e5aedab9144531a4668dc7526e3caf514e1cristy if (fabs(x) < Log10Epsilon) 6192fc10e5aedab9144531a4668dc7526e3caf514e1cristy return(log10(Log10Epsilon)); 6202fc10e5aedab9144531a4668dc7526e3caf514e1cristy return(log10(fabs(x))); 6212fc10e5aedab9144531a4668dc7526e3caf514e1cristy} 6220f09a8ceb30556f22c8800ed7ff8faa260e4f6dccristy 6232fc10e5aedab9144531a4668dc7526e3caf514e1cristyMagickExport ChannelFeatures *GetImageFeatures(const Image *image, 6242fc10e5aedab9144531a4668dc7526e3caf514e1cristy const size_t distance,ExceptionInfo *exception) 6252fc10e5aedab9144531a4668dc7526e3caf514e1cristy{ 6262fc10e5aedab9144531a4668dc7526e3caf514e1cristy typedef struct _ChannelStatistics 6272fc10e5aedab9144531a4668dc7526e3caf514e1cristy { 6282fc10e5aedab9144531a4668dc7526e3caf514e1cristy PixelInfo 6292fc10e5aedab9144531a4668dc7526e3caf514e1cristy direction[4]; /* horizontal, vertical, left and right diagonals */ 6302fc10e5aedab9144531a4668dc7526e3caf514e1cristy } ChannelStatistics; 6310f09a8ceb30556f22c8800ed7ff8faa260e4f6dccristy 6322fc10e5aedab9144531a4668dc7526e3caf514e1cristy CacheView 6332fc10e5aedab9144531a4668dc7526e3caf514e1cristy *image_view; 6340f09a8ceb30556f22c8800ed7ff8faa260e4f6dccristy 6352fc10e5aedab9144531a4668dc7526e3caf514e1cristy ChannelFeatures 6362fc10e5aedab9144531a4668dc7526e3caf514e1cristy *channel_features; 6370f09a8ceb30556f22c8800ed7ff8faa260e4f6dccristy 6382fc10e5aedab9144531a4668dc7526e3caf514e1cristy ChannelStatistics 6392fc10e5aedab9144531a4668dc7526e3caf514e1cristy **cooccurrence, 6402fc10e5aedab9144531a4668dc7526e3caf514e1cristy correlation, 6412fc10e5aedab9144531a4668dc7526e3caf514e1cristy *density_x, 6422fc10e5aedab9144531a4668dc7526e3caf514e1cristy *density_xy, 6432fc10e5aedab9144531a4668dc7526e3caf514e1cristy *density_y, 6442fc10e5aedab9144531a4668dc7526e3caf514e1cristy entropy_x, 6452fc10e5aedab9144531a4668dc7526e3caf514e1cristy entropy_xy, 6462fc10e5aedab9144531a4668dc7526e3caf514e1cristy entropy_xy1, 6472fc10e5aedab9144531a4668dc7526e3caf514e1cristy entropy_xy2, 6482fc10e5aedab9144531a4668dc7526e3caf514e1cristy entropy_y, 6492fc10e5aedab9144531a4668dc7526e3caf514e1cristy mean, 6502fc10e5aedab9144531a4668dc7526e3caf514e1cristy **Q, 6512fc10e5aedab9144531a4668dc7526e3caf514e1cristy *sum, 6522fc10e5aedab9144531a4668dc7526e3caf514e1cristy sum_squares, 6532fc10e5aedab9144531a4668dc7526e3caf514e1cristy variance; 6540f09a8ceb30556f22c8800ed7ff8faa260e4f6dccristy 6552fc10e5aedab9144531a4668dc7526e3caf514e1cristy PixelPacket 6562fc10e5aedab9144531a4668dc7526e3caf514e1cristy gray, 6572fc10e5aedab9144531a4668dc7526e3caf514e1cristy *grays; 6580f09a8ceb30556f22c8800ed7ff8faa260e4f6dccristy 6590f09a8ceb30556f22c8800ed7ff8faa260e4f6dccristy MagickBooleanType 6600f09a8ceb30556f22c8800ed7ff8faa260e4f6dccristy status; 6610f09a8ceb30556f22c8800ed7ff8faa260e4f6dccristy 6622fc10e5aedab9144531a4668dc7526e3caf514e1cristy register ssize_t 663aa6a11c893e812e2b1f1c425353eaf72d3501a9edirk i, 664aa6a11c893e812e2b1f1c425353eaf72d3501a9edirk r; 6650f09a8ceb30556f22c8800ed7ff8faa260e4f6dccristy 6662fc10e5aedab9144531a4668dc7526e3caf514e1cristy size_t 6672fc10e5aedab9144531a4668dc7526e3caf514e1cristy length; 6680f09a8ceb30556f22c8800ed7ff8faa260e4f6dccristy 6692fc10e5aedab9144531a4668dc7526e3caf514e1cristy unsigned int 6702fc10e5aedab9144531a4668dc7526e3caf514e1cristy number_grays; 6710f09a8ceb30556f22c8800ed7ff8faa260e4f6dccristy 6722fc10e5aedab9144531a4668dc7526e3caf514e1cristy assert(image != (Image *) NULL); 673e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy assert(image->signature == MagickCoreSignature); 6740f09a8ceb30556f22c8800ed7ff8faa260e4f6dccristy if (image->debug != MagickFalse) 6750f09a8ceb30556f22c8800ed7ff8faa260e4f6dccristy (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 6762fc10e5aedab9144531a4668dc7526e3caf514e1cristy if ((image->columns < (distance+1)) || (image->rows < (distance+1))) 6772fc10e5aedab9144531a4668dc7526e3caf514e1cristy return((ChannelFeatures *) NULL); 6782fc10e5aedab9144531a4668dc7526e3caf514e1cristy length=CompositeChannels+1UL; 6792fc10e5aedab9144531a4668dc7526e3caf514e1cristy channel_features=(ChannelFeatures *) AcquireQuantumMemory(length, 6802fc10e5aedab9144531a4668dc7526e3caf514e1cristy sizeof(*channel_features)); 6812fc10e5aedab9144531a4668dc7526e3caf514e1cristy if (channel_features == (ChannelFeatures *) NULL) 6822fc10e5aedab9144531a4668dc7526e3caf514e1cristy ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed"); 6832fc10e5aedab9144531a4668dc7526e3caf514e1cristy (void) ResetMagickMemory(channel_features,0,length* 6842fc10e5aedab9144531a4668dc7526e3caf514e1cristy sizeof(*channel_features)); 6850f09a8ceb30556f22c8800ed7ff8faa260e4f6dccristy /* 6862fc10e5aedab9144531a4668dc7526e3caf514e1cristy Form grays. 6870f09a8ceb30556f22c8800ed7ff8faa260e4f6dccristy */ 6882fc10e5aedab9144531a4668dc7526e3caf514e1cristy grays=(PixelPacket *) AcquireQuantumMemory(MaxMap+1UL,sizeof(*grays)); 6892fc10e5aedab9144531a4668dc7526e3caf514e1cristy if (grays == (PixelPacket *) NULL) 6902fc10e5aedab9144531a4668dc7526e3caf514e1cristy { 6912fc10e5aedab9144531a4668dc7526e3caf514e1cristy channel_features=(ChannelFeatures *) RelinquishMagickMemory( 6922fc10e5aedab9144531a4668dc7526e3caf514e1cristy channel_features); 6932fc10e5aedab9144531a4668dc7526e3caf514e1cristy (void) ThrowMagickException(exception,GetMagickModule(), 6942fc10e5aedab9144531a4668dc7526e3caf514e1cristy ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename); 6952fc10e5aedab9144531a4668dc7526e3caf514e1cristy return(channel_features); 6962fc10e5aedab9144531a4668dc7526e3caf514e1cristy } 6972fc10e5aedab9144531a4668dc7526e3caf514e1cristy for (i=0; i <= (ssize_t) MaxMap; i++) 6982fc10e5aedab9144531a4668dc7526e3caf514e1cristy { 6992fc10e5aedab9144531a4668dc7526e3caf514e1cristy grays[i].red=(~0U); 7002fc10e5aedab9144531a4668dc7526e3caf514e1cristy grays[i].green=(~0U); 7012fc10e5aedab9144531a4668dc7526e3caf514e1cristy grays[i].blue=(~0U); 7022fc10e5aedab9144531a4668dc7526e3caf514e1cristy grays[i].alpha=(~0U); 7032fc10e5aedab9144531a4668dc7526e3caf514e1cristy grays[i].black=(~0U); 7042fc10e5aedab9144531a4668dc7526e3caf514e1cristy } 7050f09a8ceb30556f22c8800ed7ff8faa260e4f6dccristy status=MagickTrue; 7060f09a8ceb30556f22c8800ed7ff8faa260e4f6dccristy image_view=AcquireVirtualCacheView(image,exception); 7072fc10e5aedab9144531a4668dc7526e3caf514e1cristy#if defined(MAGICKCORE_OPENMP_SUPPORT) 7082fc10e5aedab9144531a4668dc7526e3caf514e1cristy #pragma omp parallel for schedule(static,4) shared(status) \ 7092fc10e5aedab9144531a4668dc7526e3caf514e1cristy magick_threads(image,image,image->rows,1) 7102fc10e5aedab9144531a4668dc7526e3caf514e1cristy#endif 711aa6a11c893e812e2b1f1c425353eaf72d3501a9edirk for (r=0; r < (ssize_t) image->rows; r++) 7120f09a8ceb30556f22c8800ed7ff8faa260e4f6dccristy { 7130f09a8ceb30556f22c8800ed7ff8faa260e4f6dccristy register const Quantum 71405d2ff7ebf21f659f5b11e45afb294e152f4330cdirk *magick_restrict p; 7150f09a8ceb30556f22c8800ed7ff8faa260e4f6dccristy 7160f09a8ceb30556f22c8800ed7ff8faa260e4f6dccristy register ssize_t 7170f09a8ceb30556f22c8800ed7ff8faa260e4f6dccristy x; 7180f09a8ceb30556f22c8800ed7ff8faa260e4f6dccristy 7190f09a8ceb30556f22c8800ed7ff8faa260e4f6dccristy if (status == MagickFalse) 7200f09a8ceb30556f22c8800ed7ff8faa260e4f6dccristy continue; 721aa6a11c893e812e2b1f1c425353eaf72d3501a9edirk p=GetCacheViewVirtualPixels(image_view,0,r,image->columns,1,exception); 7222fc10e5aedab9144531a4668dc7526e3caf514e1cristy if (p == (const Quantum *) NULL) 7230f09a8ceb30556f22c8800ed7ff8faa260e4f6dccristy { 7240f09a8ceb30556f22c8800ed7ff8faa260e4f6dccristy status=MagickFalse; 7250f09a8ceb30556f22c8800ed7ff8faa260e4f6dccristy continue; 7260f09a8ceb30556f22c8800ed7ff8faa260e4f6dccristy } 7270f09a8ceb30556f22c8800ed7ff8faa260e4f6dccristy for (x=0; x < (ssize_t) image->columns; x++) 7280f09a8ceb30556f22c8800ed7ff8faa260e4f6dccristy { 7292fc10e5aedab9144531a4668dc7526e3caf514e1cristy grays[ScaleQuantumToMap(GetPixelRed(image,p))].red= 7302fc10e5aedab9144531a4668dc7526e3caf514e1cristy ScaleQuantumToMap(GetPixelRed(image,p)); 7312fc10e5aedab9144531a4668dc7526e3caf514e1cristy grays[ScaleQuantumToMap(GetPixelGreen(image,p))].green= 7322fc10e5aedab9144531a4668dc7526e3caf514e1cristy ScaleQuantumToMap(GetPixelGreen(image,p)); 7332fc10e5aedab9144531a4668dc7526e3caf514e1cristy grays[ScaleQuantumToMap(GetPixelBlue(image,p))].blue= 7342fc10e5aedab9144531a4668dc7526e3caf514e1cristy ScaleQuantumToMap(GetPixelBlue(image,p)); 7352fc10e5aedab9144531a4668dc7526e3caf514e1cristy if (image->colorspace == CMYKColorspace) 7362fc10e5aedab9144531a4668dc7526e3caf514e1cristy grays[ScaleQuantumToMap(GetPixelBlack(image,p))].black= 7372fc10e5aedab9144531a4668dc7526e3caf514e1cristy ScaleQuantumToMap(GetPixelBlack(image,p)); 73817f11b056210f082a6d0e54ac5d68e6d72fa76b2cristy if (image->alpha_trait != UndefinedPixelTrait) 7392fc10e5aedab9144531a4668dc7526e3caf514e1cristy grays[ScaleQuantumToMap(GetPixelAlpha(image,p))].alpha= 7402fc10e5aedab9144531a4668dc7526e3caf514e1cristy ScaleQuantumToMap(GetPixelAlpha(image,p)); 7410f09a8ceb30556f22c8800ed7ff8faa260e4f6dccristy p+=GetPixelChannels(image); 7420f09a8ceb30556f22c8800ed7ff8faa260e4f6dccristy } 7430f09a8ceb30556f22c8800ed7ff8faa260e4f6dccristy } 7440f09a8ceb30556f22c8800ed7ff8faa260e4f6dccristy image_view=DestroyCacheView(image_view); 7450f09a8ceb30556f22c8800ed7ff8faa260e4f6dccristy if (status == MagickFalse) 7460f09a8ceb30556f22c8800ed7ff8faa260e4f6dccristy { 7472fc10e5aedab9144531a4668dc7526e3caf514e1cristy grays=(PixelPacket *) RelinquishMagickMemory(grays); 7482fc10e5aedab9144531a4668dc7526e3caf514e1cristy channel_features=(ChannelFeatures *) RelinquishMagickMemory( 7492fc10e5aedab9144531a4668dc7526e3caf514e1cristy channel_features); 7502fc10e5aedab9144531a4668dc7526e3caf514e1cristy return(channel_features); 7510f09a8ceb30556f22c8800ed7ff8faa260e4f6dccristy } 7522fc10e5aedab9144531a4668dc7526e3caf514e1cristy (void) ResetMagickMemory(&gray,0,sizeof(gray)); 7532fc10e5aedab9144531a4668dc7526e3caf514e1cristy for (i=0; i <= (ssize_t) MaxMap; i++) 7542fc10e5aedab9144531a4668dc7526e3caf514e1cristy { 7552fc10e5aedab9144531a4668dc7526e3caf514e1cristy if (grays[i].red != ~0U) 7562fc10e5aedab9144531a4668dc7526e3caf514e1cristy grays[gray.red++].red=grays[i].red; 7572fc10e5aedab9144531a4668dc7526e3caf514e1cristy if (grays[i].green != ~0U) 7582fc10e5aedab9144531a4668dc7526e3caf514e1cristy grays[gray.green++].green=grays[i].green; 7592fc10e5aedab9144531a4668dc7526e3caf514e1cristy if (grays[i].blue != ~0U) 7602fc10e5aedab9144531a4668dc7526e3caf514e1cristy grays[gray.blue++].blue=grays[i].blue; 7612fc10e5aedab9144531a4668dc7526e3caf514e1cristy if (image->colorspace == CMYKColorspace) 7622fc10e5aedab9144531a4668dc7526e3caf514e1cristy if (grays[i].black != ~0U) 7632fc10e5aedab9144531a4668dc7526e3caf514e1cristy grays[gray.black++].black=grays[i].black; 76417f11b056210f082a6d0e54ac5d68e6d72fa76b2cristy if (image->alpha_trait != UndefinedPixelTrait) 7652fc10e5aedab9144531a4668dc7526e3caf514e1cristy if (grays[i].alpha != ~0U) 7662fc10e5aedab9144531a4668dc7526e3caf514e1cristy grays[gray.alpha++].alpha=grays[i].alpha; 7672fc10e5aedab9144531a4668dc7526e3caf514e1cristy } 7680f09a8ceb30556f22c8800ed7ff8faa260e4f6dccristy /* 7692fc10e5aedab9144531a4668dc7526e3caf514e1cristy Allocate spatial dependence matrix. 7700f09a8ceb30556f22c8800ed7ff8faa260e4f6dccristy */ 7712fc10e5aedab9144531a4668dc7526e3caf514e1cristy number_grays=gray.red; 7722fc10e5aedab9144531a4668dc7526e3caf514e1cristy if (gray.green > number_grays) 7732fc10e5aedab9144531a4668dc7526e3caf514e1cristy number_grays=gray.green; 7742fc10e5aedab9144531a4668dc7526e3caf514e1cristy if (gray.blue > number_grays) 7752fc10e5aedab9144531a4668dc7526e3caf514e1cristy number_grays=gray.blue; 7762fc10e5aedab9144531a4668dc7526e3caf514e1cristy if (image->colorspace == CMYKColorspace) 7772fc10e5aedab9144531a4668dc7526e3caf514e1cristy if (gray.black > number_grays) 7782fc10e5aedab9144531a4668dc7526e3caf514e1cristy number_grays=gray.black; 77917f11b056210f082a6d0e54ac5d68e6d72fa76b2cristy if (image->alpha_trait != UndefinedPixelTrait) 7802fc10e5aedab9144531a4668dc7526e3caf514e1cristy if (gray.alpha > number_grays) 7812fc10e5aedab9144531a4668dc7526e3caf514e1cristy number_grays=gray.alpha; 7822fc10e5aedab9144531a4668dc7526e3caf514e1cristy cooccurrence=(ChannelStatistics **) AcquireQuantumMemory(number_grays, 7832fc10e5aedab9144531a4668dc7526e3caf514e1cristy sizeof(*cooccurrence)); 7842fc10e5aedab9144531a4668dc7526e3caf514e1cristy density_x=(ChannelStatistics *) AcquireQuantumMemory(2*(number_grays+1), 7852fc10e5aedab9144531a4668dc7526e3caf514e1cristy sizeof(*density_x)); 7862fc10e5aedab9144531a4668dc7526e3caf514e1cristy density_xy=(ChannelStatistics *) AcquireQuantumMemory(2*(number_grays+1), 7872fc10e5aedab9144531a4668dc7526e3caf514e1cristy sizeof(*density_xy)); 7882fc10e5aedab9144531a4668dc7526e3caf514e1cristy density_y=(ChannelStatistics *) AcquireQuantumMemory(2*(number_grays+1), 7892fc10e5aedab9144531a4668dc7526e3caf514e1cristy sizeof(*density_y)); 7902fc10e5aedab9144531a4668dc7526e3caf514e1cristy Q=(ChannelStatistics **) AcquireQuantumMemory(number_grays,sizeof(*Q)); 7912fc10e5aedab9144531a4668dc7526e3caf514e1cristy sum=(ChannelStatistics *) AcquireQuantumMemory(number_grays,sizeof(*sum)); 7922fc10e5aedab9144531a4668dc7526e3caf514e1cristy if ((cooccurrence == (ChannelStatistics **) NULL) || 7932fc10e5aedab9144531a4668dc7526e3caf514e1cristy (density_x == (ChannelStatistics *) NULL) || 7942fc10e5aedab9144531a4668dc7526e3caf514e1cristy (density_xy == (ChannelStatistics *) NULL) || 7952fc10e5aedab9144531a4668dc7526e3caf514e1cristy (density_y == (ChannelStatistics *) NULL) || 7962fc10e5aedab9144531a4668dc7526e3caf514e1cristy (Q == (ChannelStatistics **) NULL) || 7972fc10e5aedab9144531a4668dc7526e3caf514e1cristy (sum == (ChannelStatistics *) NULL)) 798f2bf2c76eb0f9a013d0a4dd51d4b86d3d714ddf2cristy { 799ffa10d0fe53ef0f0db63ee506c52695595976b99cristy if (Q != (ChannelStatistics **) NULL) 800ffa10d0fe53ef0f0db63ee506c52695595976b99cristy { 801bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (i=0; i < (ssize_t) number_grays; i++) 802ffa10d0fe53ef0f0db63ee506c52695595976b99cristy Q[i]=(ChannelStatistics *) RelinquishMagickMemory(Q[i]); 803ffa10d0fe53ef0f0db63ee506c52695595976b99cristy Q=(ChannelStatistics **) RelinquishMagickMemory(Q); 804ffa10d0fe53ef0f0db63ee506c52695595976b99cristy } 805ffa10d0fe53ef0f0db63ee506c52695595976b99cristy if (sum != (ChannelStatistics *) NULL) 806ffa10d0fe53ef0f0db63ee506c52695595976b99cristy sum=(ChannelStatistics *) RelinquishMagickMemory(sum); 807ffa10d0fe53ef0f0db63ee506c52695595976b99cristy if (density_y != (ChannelStatistics *) NULL) 808ffa10d0fe53ef0f0db63ee506c52695595976b99cristy density_y=(ChannelStatistics *) RelinquishMagickMemory(density_y); 809ffa10d0fe53ef0f0db63ee506c52695595976b99cristy if (density_xy != (ChannelStatistics *) NULL) 810ffa10d0fe53ef0f0db63ee506c52695595976b99cristy density_xy=(ChannelStatistics *) RelinquishMagickMemory(density_xy); 811ffa10d0fe53ef0f0db63ee506c52695595976b99cristy if (density_x != (ChannelStatistics *) NULL) 812ffa10d0fe53ef0f0db63ee506c52695595976b99cristy density_x=(ChannelStatistics *) RelinquishMagickMemory(density_x); 813ffa10d0fe53ef0f0db63ee506c52695595976b99cristy if (cooccurrence != (ChannelStatistics **) NULL) 814ffa10d0fe53ef0f0db63ee506c52695595976b99cristy { 815bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (i=0; i < (ssize_t) number_grays; i++) 816ffa10d0fe53ef0f0db63ee506c52695595976b99cristy cooccurrence[i]=(ChannelStatistics *) 817ffa10d0fe53ef0f0db63ee506c52695595976b99cristy RelinquishMagickMemory(cooccurrence[i]); 818ffa10d0fe53ef0f0db63ee506c52695595976b99cristy cooccurrence=(ChannelStatistics **) RelinquishMagickMemory( 819ffa10d0fe53ef0f0db63ee506c52695595976b99cristy cooccurrence); 820ffa10d0fe53ef0f0db63ee506c52695595976b99cristy } 821101ab708b0574518ac5715da4d3915400e9df79acristy grays=(PixelPacket *) RelinquishMagickMemory(grays); 822f2bf2c76eb0f9a013d0a4dd51d4b86d3d714ddf2cristy channel_features=(ChannelFeatures *) RelinquishMagickMemory( 823f2bf2c76eb0f9a013d0a4dd51d4b86d3d714ddf2cristy channel_features); 824e18977973bff5866de9aa6ed097aea40e27570d6cristy (void) ThrowMagickException(exception,GetMagickModule(), 825efe601ce9ea5ad34ad0e8ad6e61d9be9b148b2a3cristy ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename); 826f2bf2c76eb0f9a013d0a4dd51d4b86d3d714ddf2cristy return(channel_features); 827f2bf2c76eb0f9a013d0a4dd51d4b86d3d714ddf2cristy } 828ffa10d0fe53ef0f0db63ee506c52695595976b99cristy (void) ResetMagickMemory(&correlation,0,sizeof(correlation)); 82977173e5c9ab59c80128f74d92b01da7e8a64de8dcristy (void) ResetMagickMemory(density_x,0,2*(number_grays+1)*sizeof(*density_x)); 83077173e5c9ab59c80128f74d92b01da7e8a64de8dcristy (void) ResetMagickMemory(density_xy,0,2*(number_grays+1)*sizeof(*density_xy)); 83177173e5c9ab59c80128f74d92b01da7e8a64de8dcristy (void) ResetMagickMemory(density_y,0,2*(number_grays+1)*sizeof(*density_y)); 832ffa10d0fe53ef0f0db63ee506c52695595976b99cristy (void) ResetMagickMemory(&mean,0,sizeof(mean)); 833ffa10d0fe53ef0f0db63ee506c52695595976b99cristy (void) ResetMagickMemory(sum,0,number_grays*sizeof(*sum)); 834ffa10d0fe53ef0f0db63ee506c52695595976b99cristy (void) ResetMagickMemory(&sum_squares,0,sizeof(sum_squares)); 835ffa10d0fe53ef0f0db63ee506c52695595976b99cristy (void) ResetMagickMemory(density_xy,0,2*number_grays*sizeof(*density_xy)); 836ffa10d0fe53ef0f0db63ee506c52695595976b99cristy (void) ResetMagickMemory(&entropy_x,0,sizeof(entropy_x)); 837ffa10d0fe53ef0f0db63ee506c52695595976b99cristy (void) ResetMagickMemory(&entropy_xy,0,sizeof(entropy_xy)); 838ffa10d0fe53ef0f0db63ee506c52695595976b99cristy (void) ResetMagickMemory(&entropy_xy1,0,sizeof(entropy_xy1)); 839ffa10d0fe53ef0f0db63ee506c52695595976b99cristy (void) ResetMagickMemory(&entropy_xy2,0,sizeof(entropy_xy2)); 840ffa10d0fe53ef0f0db63ee506c52695595976b99cristy (void) ResetMagickMemory(&entropy_y,0,sizeof(entropy_y)); 841ffa10d0fe53ef0f0db63ee506c52695595976b99cristy (void) ResetMagickMemory(&variance,0,sizeof(variance)); 842bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (i=0; i < (ssize_t) number_grays; i++) 843f2bf2c76eb0f9a013d0a4dd51d4b86d3d714ddf2cristy { 8447396d88d575791c136bc6d060e613bdfbfb58f95cristy cooccurrence[i]=(ChannelStatistics *) AcquireQuantumMemory(number_grays, 8457396d88d575791c136bc6d060e613bdfbfb58f95cristy sizeof(**cooccurrence)); 846ffa10d0fe53ef0f0db63ee506c52695595976b99cristy Q[i]=(ChannelStatistics *) AcquireQuantumMemory(number_grays,sizeof(**Q)); 847ffa10d0fe53ef0f0db63ee506c52695595976b99cristy if ((cooccurrence[i] == (ChannelStatistics *) NULL) || 848ffa10d0fe53ef0f0db63ee506c52695595976b99cristy (Q[i] == (ChannelStatistics *) NULL)) 849f2bf2c76eb0f9a013d0a4dd51d4b86d3d714ddf2cristy break; 8507396d88d575791c136bc6d060e613bdfbfb58f95cristy (void) ResetMagickMemory(cooccurrence[i],0,number_grays* 8513749be456a491c22c19b273d1871e896bd8eae79cristy sizeof(**cooccurrence)); 8523749be456a491c22c19b273d1871e896bd8eae79cristy (void) ResetMagickMemory(Q[i],0,number_grays*sizeof(**Q)); 853f2bf2c76eb0f9a013d0a4dd51d4b86d3d714ddf2cristy } 854bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy if (i < (ssize_t) number_grays) 855f2bf2c76eb0f9a013d0a4dd51d4b86d3d714ddf2cristy { 856f2bf2c76eb0f9a013d0a4dd51d4b86d3d714ddf2cristy for (i--; i >= 0; i--) 857ffa10d0fe53ef0f0db63ee506c52695595976b99cristy { 858ffa10d0fe53ef0f0db63ee506c52695595976b99cristy if (Q[i] != (ChannelStatistics *) NULL) 859ffa10d0fe53ef0f0db63ee506c52695595976b99cristy Q[i]=(ChannelStatistics *) RelinquishMagickMemory(Q[i]); 860ffa10d0fe53ef0f0db63ee506c52695595976b99cristy if (cooccurrence[i] != (ChannelStatistics *) NULL) 861ffa10d0fe53ef0f0db63ee506c52695595976b99cristy cooccurrence[i]=(ChannelStatistics *) 862ffa10d0fe53ef0f0db63ee506c52695595976b99cristy RelinquishMagickMemory(cooccurrence[i]); 863ffa10d0fe53ef0f0db63ee506c52695595976b99cristy } 864ffa10d0fe53ef0f0db63ee506c52695595976b99cristy Q=(ChannelStatistics **) RelinquishMagickMemory(Q); 8657396d88d575791c136bc6d060e613bdfbfb58f95cristy cooccurrence=(ChannelStatistics **) RelinquishMagickMemory(cooccurrence); 866ffa10d0fe53ef0f0db63ee506c52695595976b99cristy sum=(ChannelStatistics *) RelinquishMagickMemory(sum); 867ffa10d0fe53ef0f0db63ee506c52695595976b99cristy density_y=(ChannelStatistics *) RelinquishMagickMemory(density_y); 868ffa10d0fe53ef0f0db63ee506c52695595976b99cristy density_xy=(ChannelStatistics *) RelinquishMagickMemory(density_xy); 869ffa10d0fe53ef0f0db63ee506c52695595976b99cristy density_x=(ChannelStatistics *) RelinquishMagickMemory(density_x); 870101ab708b0574518ac5715da4d3915400e9df79acristy grays=(PixelPacket *) RelinquishMagickMemory(grays); 871f2bf2c76eb0f9a013d0a4dd51d4b86d3d714ddf2cristy channel_features=(ChannelFeatures *) RelinquishMagickMemory( 872f2bf2c76eb0f9a013d0a4dd51d4b86d3d714ddf2cristy channel_features); 873e18977973bff5866de9aa6ed097aea40e27570d6cristy (void) ThrowMagickException(exception,GetMagickModule(), 874efe601ce9ea5ad34ad0e8ad6e61d9be9b148b2a3cristy ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename); 875f2bf2c76eb0f9a013d0a4dd51d4b86d3d714ddf2cristy return(channel_features); 876f2bf2c76eb0f9a013d0a4dd51d4b86d3d714ddf2cristy } 877f2bf2c76eb0f9a013d0a4dd51d4b86d3d714ddf2cristy /* 878f2bf2c76eb0f9a013d0a4dd51d4b86d3d714ddf2cristy Initialize spatial dependence matrix. 879f2bf2c76eb0f9a013d0a4dd51d4b86d3d714ddf2cristy */ 880f2bf2c76eb0f9a013d0a4dd51d4b86d3d714ddf2cristy status=MagickTrue; 88146ff2676b1044ea4101ac7a59b83289cd8f6cfdacristy image_view=AcquireVirtualCacheView(image,exception); 882aa6a11c893e812e2b1f1c425353eaf72d3501a9edirk for (r=0; r < (ssize_t) image->rows; r++) 883f2bf2c76eb0f9a013d0a4dd51d4b86d3d714ddf2cristy { 8844c08aed51c5899665ade97263692328eea4af106cristy register const Quantum 88505d2ff7ebf21f659f5b11e45afb294e152f4330cdirk *magick_restrict p; 886f2bf2c76eb0f9a013d0a4dd51d4b86d3d714ddf2cristy 887bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy register ssize_t 888f2bf2c76eb0f9a013d0a4dd51d4b86d3d714ddf2cristy x; 889f2bf2c76eb0f9a013d0a4dd51d4b86d3d714ddf2cristy 8907e9726d27d1b1e079b9b94b78f5ffd49352fcc91cristy ssize_t 8919d314ff2c17a77996c05413c2013880387e50f0ecristy offset, 8929d314ff2c17a77996c05413c2013880387e50f0ecristy u, 8939d314ff2c17a77996c05413c2013880387e50f0ecristy v; 8947e9726d27d1b1e079b9b94b78f5ffd49352fcc91cristy 895f2bf2c76eb0f9a013d0a4dd51d4b86d3d714ddf2cristy if (status == MagickFalse) 896f2bf2c76eb0f9a013d0a4dd51d4b86d3d714ddf2cristy continue; 897aa6a11c893e812e2b1f1c425353eaf72d3501a9edirk p=GetCacheViewVirtualPixels(image_view,-(ssize_t) distance,r,image->columns+ 898a1d2bd306531d35abea0440a3008714d36b5c50ccristy 2*distance,distance+2,exception); 8994c08aed51c5899665ade97263692328eea4af106cristy if (p == (const Quantum *) NULL) 900f2bf2c76eb0f9a013d0a4dd51d4b86d3d714ddf2cristy { 901f2bf2c76eb0f9a013d0a4dd51d4b86d3d714ddf2cristy status=MagickFalse; 902f2bf2c76eb0f9a013d0a4dd51d4b86d3d714ddf2cristy continue; 903f2bf2c76eb0f9a013d0a4dd51d4b86d3d714ddf2cristy } 9048a11cb146177680bfc1b7d89a8cd0c8f2befe468cristy p+=distance*GetPixelChannels(image);; 905bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (x=0; x < (ssize_t) image->columns; x++) 906f2bf2c76eb0f9a013d0a4dd51d4b86d3d714ddf2cristy { 907f2bf2c76eb0f9a013d0a4dd51d4b86d3d714ddf2cristy for (i=0; i < 4; i++) 908f2bf2c76eb0f9a013d0a4dd51d4b86d3d714ddf2cristy { 9097e9726d27d1b1e079b9b94b78f5ffd49352fcc91cristy switch (i) 9107e9726d27d1b1e079b9b94b78f5ffd49352fcc91cristy { 9117e9726d27d1b1e079b9b94b78f5ffd49352fcc91cristy case 0: 912549a37e6cd4593dcb997230cd3584c5afead5552cristy default: 9137e9726d27d1b1e079b9b94b78f5ffd49352fcc91cristy { 9147e9726d27d1b1e079b9b94b78f5ffd49352fcc91cristy /* 9157396d88d575791c136bc6d060e613bdfbfb58f95cristy Horizontal adjacency. 9167e9726d27d1b1e079b9b94b78f5ffd49352fcc91cristy */ 9177e9726d27d1b1e079b9b94b78f5ffd49352fcc91cristy offset=(ssize_t) distance; 9187e9726d27d1b1e079b9b94b78f5ffd49352fcc91cristy break; 9197e9726d27d1b1e079b9b94b78f5ffd49352fcc91cristy } 9207e9726d27d1b1e079b9b94b78f5ffd49352fcc91cristy case 1: 9217e9726d27d1b1e079b9b94b78f5ffd49352fcc91cristy { 9227e9726d27d1b1e079b9b94b78f5ffd49352fcc91cristy /* 9237396d88d575791c136bc6d060e613bdfbfb58f95cristy Vertical adjacency. 9247e9726d27d1b1e079b9b94b78f5ffd49352fcc91cristy */ 9257396d88d575791c136bc6d060e613bdfbfb58f95cristy offset=(ssize_t) (image->columns+2*distance); 9267e9726d27d1b1e079b9b94b78f5ffd49352fcc91cristy break; 9277e9726d27d1b1e079b9b94b78f5ffd49352fcc91cristy } 9287e9726d27d1b1e079b9b94b78f5ffd49352fcc91cristy case 2: 9297e9726d27d1b1e079b9b94b78f5ffd49352fcc91cristy { 9307e9726d27d1b1e079b9b94b78f5ffd49352fcc91cristy /* 9317396d88d575791c136bc6d060e613bdfbfb58f95cristy Right diagonal adjacency. 9327e9726d27d1b1e079b9b94b78f5ffd49352fcc91cristy */ 933d99b096901994c291fdd5b648c5ec9c12d675947cristy offset=(ssize_t) ((image->columns+2*distance)-distance); 9347e9726d27d1b1e079b9b94b78f5ffd49352fcc91cristy break; 9357e9726d27d1b1e079b9b94b78f5ffd49352fcc91cristy } 9367e9726d27d1b1e079b9b94b78f5ffd49352fcc91cristy case 3: 9377e9726d27d1b1e079b9b94b78f5ffd49352fcc91cristy { 9387e9726d27d1b1e079b9b94b78f5ffd49352fcc91cristy /* 9397396d88d575791c136bc6d060e613bdfbfb58f95cristy Left diagonal adjacency. 9407e9726d27d1b1e079b9b94b78f5ffd49352fcc91cristy */ 941d99b096901994c291fdd5b648c5ec9c12d675947cristy offset=(ssize_t) ((image->columns+2*distance)+distance); 9427e9726d27d1b1e079b9b94b78f5ffd49352fcc91cristy break; 9437e9726d27d1b1e079b9b94b78f5ffd49352fcc91cristy } 9447e9726d27d1b1e079b9b94b78f5ffd49352fcc91cristy } 9457e9726d27d1b1e079b9b94b78f5ffd49352fcc91cristy u=0; 9467e9726d27d1b1e079b9b94b78f5ffd49352fcc91cristy v=0; 9474c08aed51c5899665ade97263692328eea4af106cristy while (grays[u].red != ScaleQuantumToMap(GetPixelRed(image,p))) 9487e9726d27d1b1e079b9b94b78f5ffd49352fcc91cristy u++; 949ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy while (grays[v].red != ScaleQuantumToMap(GetPixelRed(image,p+offset*GetPixelChannels(image)))) 9507e9726d27d1b1e079b9b94b78f5ffd49352fcc91cristy v++; 9517396d88d575791c136bc6d060e613bdfbfb58f95cristy cooccurrence[u][v].direction[i].red++; 9527396d88d575791c136bc6d060e613bdfbfb58f95cristy cooccurrence[v][u].direction[i].red++; 9537e9726d27d1b1e079b9b94b78f5ffd49352fcc91cristy u=0; 9547e9726d27d1b1e079b9b94b78f5ffd49352fcc91cristy v=0; 9554c08aed51c5899665ade97263692328eea4af106cristy while (grays[u].green != ScaleQuantumToMap(GetPixelGreen(image,p))) 9567e9726d27d1b1e079b9b94b78f5ffd49352fcc91cristy u++; 957ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy while (grays[v].green != ScaleQuantumToMap(GetPixelGreen(image,p+offset*GetPixelChannels(image)))) 9587e9726d27d1b1e079b9b94b78f5ffd49352fcc91cristy v++; 9597396d88d575791c136bc6d060e613bdfbfb58f95cristy cooccurrence[u][v].direction[i].green++; 9607396d88d575791c136bc6d060e613bdfbfb58f95cristy cooccurrence[v][u].direction[i].green++; 9617e9726d27d1b1e079b9b94b78f5ffd49352fcc91cristy u=0; 9627e9726d27d1b1e079b9b94b78f5ffd49352fcc91cristy v=0; 9634c08aed51c5899665ade97263692328eea4af106cristy while (grays[u].blue != ScaleQuantumToMap(GetPixelBlue(image,p))) 9647e9726d27d1b1e079b9b94b78f5ffd49352fcc91cristy u++; 965ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy while (grays[v].blue != ScaleQuantumToMap(GetPixelBlue(image,p+offset*GetPixelChannels(image)))) 9667e9726d27d1b1e079b9b94b78f5ffd49352fcc91cristy v++; 9677396d88d575791c136bc6d060e613bdfbfb58f95cristy cooccurrence[u][v].direction[i].blue++; 9687396d88d575791c136bc6d060e613bdfbfb58f95cristy cooccurrence[v][u].direction[i].blue++; 96953a727d91e1edeb3a67fa7d923db42974bba3b64cristy if (image->colorspace == CMYKColorspace) 9707e9726d27d1b1e079b9b94b78f5ffd49352fcc91cristy { 9717e9726d27d1b1e079b9b94b78f5ffd49352fcc91cristy u=0; 9727e9726d27d1b1e079b9b94b78f5ffd49352fcc91cristy v=0; 9734c08aed51c5899665ade97263692328eea4af106cristy while (grays[u].black != ScaleQuantumToMap(GetPixelBlack(image,p))) 9747e9726d27d1b1e079b9b94b78f5ffd49352fcc91cristy u++; 975ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy while (grays[v].black != ScaleQuantumToMap(GetPixelBlack(image,p+offset*GetPixelChannels(image)))) 9767e9726d27d1b1e079b9b94b78f5ffd49352fcc91cristy v++; 9774c08aed51c5899665ade97263692328eea4af106cristy cooccurrence[u][v].direction[i].black++; 9784c08aed51c5899665ade97263692328eea4af106cristy cooccurrence[v][u].direction[i].black++; 9797e9726d27d1b1e079b9b94b78f5ffd49352fcc91cristy } 98017f11b056210f082a6d0e54ac5d68e6d72fa76b2cristy if (image->alpha_trait != UndefinedPixelTrait) 9817e9726d27d1b1e079b9b94b78f5ffd49352fcc91cristy { 9827e9726d27d1b1e079b9b94b78f5ffd49352fcc91cristy u=0; 9837e9726d27d1b1e079b9b94b78f5ffd49352fcc91cristy v=0; 9844c08aed51c5899665ade97263692328eea4af106cristy while (grays[u].alpha != ScaleQuantumToMap(GetPixelAlpha(image,p))) 9857e9726d27d1b1e079b9b94b78f5ffd49352fcc91cristy u++; 986ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy while (grays[v].alpha != ScaleQuantumToMap(GetPixelAlpha(image,p+offset*GetPixelChannels(image)))) 9877e9726d27d1b1e079b9b94b78f5ffd49352fcc91cristy v++; 9884c08aed51c5899665ade97263692328eea4af106cristy cooccurrence[u][v].direction[i].alpha++; 9894c08aed51c5899665ade97263692328eea4af106cristy cooccurrence[v][u].direction[i].alpha++; 9907e9726d27d1b1e079b9b94b78f5ffd49352fcc91cristy } 991f2bf2c76eb0f9a013d0a4dd51d4b86d3d714ddf2cristy } 992ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy p+=GetPixelChannels(image); 993f2bf2c76eb0f9a013d0a4dd51d4b86d3d714ddf2cristy } 994f2bf2c76eb0f9a013d0a4dd51d4b86d3d714ddf2cristy } 995101ab708b0574518ac5715da4d3915400e9df79acristy grays=(PixelPacket *) RelinquishMagickMemory(grays); 996f2bf2c76eb0f9a013d0a4dd51d4b86d3d714ddf2cristy image_view=DestroyCacheView(image_view); 997f2bf2c76eb0f9a013d0a4dd51d4b86d3d714ddf2cristy if (status == MagickFalse) 998f2bf2c76eb0f9a013d0a4dd51d4b86d3d714ddf2cristy { 999bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (i=0; i < (ssize_t) number_grays; i++) 10007396d88d575791c136bc6d060e613bdfbfb58f95cristy cooccurrence[i]=(ChannelStatistics *) 10017396d88d575791c136bc6d060e613bdfbfb58f95cristy RelinquishMagickMemory(cooccurrence[i]); 10027396d88d575791c136bc6d060e613bdfbfb58f95cristy cooccurrence=(ChannelStatistics **) RelinquishMagickMemory(cooccurrence); 1003f2bf2c76eb0f9a013d0a4dd51d4b86d3d714ddf2cristy channel_features=(ChannelFeatures *) RelinquishMagickMemory( 1004f2bf2c76eb0f9a013d0a4dd51d4b86d3d714ddf2cristy channel_features); 1005e18977973bff5866de9aa6ed097aea40e27570d6cristy (void) ThrowMagickException(exception,GetMagickModule(), 1006efe601ce9ea5ad34ad0e8ad6e61d9be9b148b2a3cristy ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename); 1007f2bf2c76eb0f9a013d0a4dd51d4b86d3d714ddf2cristy return(channel_features); 1008f2bf2c76eb0f9a013d0a4dd51d4b86d3d714ddf2cristy } 1009f2bf2c76eb0f9a013d0a4dd51d4b86d3d714ddf2cristy /* 10107e9726d27d1b1e079b9b94b78f5ffd49352fcc91cristy Normalize spatial dependence matrix. 10117e9726d27d1b1e079b9b94b78f5ffd49352fcc91cristy */ 1012bd82207b3816471fba4de916fca7336f38b70493cristy for (i=0; i < 4; i++) 10137e9726d27d1b1e079b9b94b78f5ffd49352fcc91cristy { 1014549a37e6cd4593dcb997230cd3584c5afead5552cristy double 1015549a37e6cd4593dcb997230cd3584c5afead5552cristy normalize; 1016549a37e6cd4593dcb997230cd3584c5afead5552cristy 101753a727d91e1edeb3a67fa7d923db42974bba3b64cristy register ssize_t 101853a727d91e1edeb3a67fa7d923db42974bba3b64cristy y; 101953a727d91e1edeb3a67fa7d923db42974bba3b64cristy 1020bd82207b3816471fba4de916fca7336f38b70493cristy switch (i) 10217e9726d27d1b1e079b9b94b78f5ffd49352fcc91cristy { 1022bd82207b3816471fba4de916fca7336f38b70493cristy case 0: 1023bd82207b3816471fba4de916fca7336f38b70493cristy default: 1024bd82207b3816471fba4de916fca7336f38b70493cristy { 1025bd82207b3816471fba4de916fca7336f38b70493cristy /* 10267396d88d575791c136bc6d060e613bdfbfb58f95cristy Horizontal adjacency. 1027bd82207b3816471fba4de916fca7336f38b70493cristy */ 1028bd82207b3816471fba4de916fca7336f38b70493cristy normalize=2.0*image->rows*(image->columns-distance); 1029bd82207b3816471fba4de916fca7336f38b70493cristy break; 1030bd82207b3816471fba4de916fca7336f38b70493cristy } 1031bd82207b3816471fba4de916fca7336f38b70493cristy case 1: 1032bd82207b3816471fba4de916fca7336f38b70493cristy { 1033bd82207b3816471fba4de916fca7336f38b70493cristy /* 10347396d88d575791c136bc6d060e613bdfbfb58f95cristy Vertical adjacency. 1035bd82207b3816471fba4de916fca7336f38b70493cristy */ 10367396d88d575791c136bc6d060e613bdfbfb58f95cristy normalize=2.0*(image->rows-distance)*image->columns; 1037bd82207b3816471fba4de916fca7336f38b70493cristy break; 1038bd82207b3816471fba4de916fca7336f38b70493cristy } 1039bd82207b3816471fba4de916fca7336f38b70493cristy case 2: 1040bd82207b3816471fba4de916fca7336f38b70493cristy { 1041bd82207b3816471fba4de916fca7336f38b70493cristy /* 10427396d88d575791c136bc6d060e613bdfbfb58f95cristy Right diagonal adjacency. 1043bd82207b3816471fba4de916fca7336f38b70493cristy */ 10447396d88d575791c136bc6d060e613bdfbfb58f95cristy normalize=2.0*(image->rows-distance)*(image->columns-distance); 1045bd82207b3816471fba4de916fca7336f38b70493cristy break; 1046bd82207b3816471fba4de916fca7336f38b70493cristy } 1047bd82207b3816471fba4de916fca7336f38b70493cristy case 3: 1048bd82207b3816471fba4de916fca7336f38b70493cristy { 1049bd82207b3816471fba4de916fca7336f38b70493cristy /* 10507396d88d575791c136bc6d060e613bdfbfb58f95cristy Left diagonal adjacency. 1051bd82207b3816471fba4de916fca7336f38b70493cristy */ 1052bd82207b3816471fba4de916fca7336f38b70493cristy normalize=2.0*(image->rows-distance)*(image->columns-distance); 1053bd82207b3816471fba4de916fca7336f38b70493cristy break; 1054bd82207b3816471fba4de916fca7336f38b70493cristy } 1055bd82207b3816471fba4de916fca7336f38b70493cristy } 10563e3ec3afbb0782697f201cbe30a56794c10dc7efcristy normalize=PerceptibleReciprocal(normalize); 1057bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (y=0; y < (ssize_t) number_grays; y++) 1058bd82207b3816471fba4de916fca7336f38b70493cristy { 1059bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy register ssize_t 1060bd82207b3816471fba4de916fca7336f38b70493cristy x; 1061bd82207b3816471fba4de916fca7336f38b70493cristy 1062bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (x=0; x < (ssize_t) number_grays; x++) 10637e9726d27d1b1e079b9b94b78f5ffd49352fcc91cristy { 106453a727d91e1edeb3a67fa7d923db42974bba3b64cristy cooccurrence[x][y].direction[i].red*=normalize; 106553a727d91e1edeb3a67fa7d923db42974bba3b64cristy cooccurrence[x][y].direction[i].green*=normalize; 106653a727d91e1edeb3a67fa7d923db42974bba3b64cristy cooccurrence[x][y].direction[i].blue*=normalize; 1067549a37e6cd4593dcb997230cd3584c5afead5552cristy if (image->colorspace == CMYKColorspace) 10684c08aed51c5899665ade97263692328eea4af106cristy cooccurrence[x][y].direction[i].black*=normalize; 106917f11b056210f082a6d0e54ac5d68e6d72fa76b2cristy if (image->alpha_trait != UndefinedPixelTrait) 10704c08aed51c5899665ade97263692328eea4af106cristy cooccurrence[x][y].direction[i].alpha*=normalize; 1071549a37e6cd4593dcb997230cd3584c5afead5552cristy } 1072549a37e6cd4593dcb997230cd3584c5afead5552cristy } 1073549a37e6cd4593dcb997230cd3584c5afead5552cristy } 1074549a37e6cd4593dcb997230cd3584c5afead5552cristy /* 1075549a37e6cd4593dcb997230cd3584c5afead5552cristy Compute texture features. 1076549a37e6cd4593dcb997230cd3584c5afead5552cristy */ 10773a82f25dfc8e47ea3049f3a474a8c79ebc268926cristy#if defined(MAGICKCORE_OPENMP_SUPPORT) 1078ac245f8a51ea65b085d751c41d8ca4b426bdfe5bcristy #pragma omp parallel for schedule(static,4) shared(status) \ 10795e6b259130f9dbe0da4666f734937017babe573acristy magick_threads(image,image,number_grays,1) 10803a82f25dfc8e47ea3049f3a474a8c79ebc268926cristy#endif 1081bd82207b3816471fba4de916fca7336f38b70493cristy for (i=0; i < 4; i++) 1082549a37e6cd4593dcb997230cd3584c5afead5552cristy { 1083bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy register ssize_t 1084bd82207b3816471fba4de916fca7336f38b70493cristy y; 1085549a37e6cd4593dcb997230cd3584c5afead5552cristy 1086bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (y=0; y < (ssize_t) number_grays; y++) 1087549a37e6cd4593dcb997230cd3584c5afead5552cristy { 1088bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy register ssize_t 1089bd82207b3816471fba4de916fca7336f38b70493cristy x; 1090bd82207b3816471fba4de916fca7336f38b70493cristy 1091bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (x=0; x < (ssize_t) number_grays; x++) 1092549a37e6cd4593dcb997230cd3584c5afead5552cristy { 1093549a37e6cd4593dcb997230cd3584c5afead5552cristy /* 10943a82f25dfc8e47ea3049f3a474a8c79ebc268926cristy Angular second moment: measure of homogeneity of the image. 1095549a37e6cd4593dcb997230cd3584c5afead5552cristy */ 1096d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy channel_features[RedPixelChannel].angular_second_moment[i]+= 10977396d88d575791c136bc6d060e613bdfbfb58f95cristy cooccurrence[x][y].direction[i].red* 10987396d88d575791c136bc6d060e613bdfbfb58f95cristy cooccurrence[x][y].direction[i].red; 1099d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy channel_features[GreenPixelChannel].angular_second_moment[i]+= 11007396d88d575791c136bc6d060e613bdfbfb58f95cristy cooccurrence[x][y].direction[i].green* 11017396d88d575791c136bc6d060e613bdfbfb58f95cristy cooccurrence[x][y].direction[i].green; 1102d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy channel_features[BluePixelChannel].angular_second_moment[i]+= 11037396d88d575791c136bc6d060e613bdfbfb58f95cristy cooccurrence[x][y].direction[i].blue* 11047396d88d575791c136bc6d060e613bdfbfb58f95cristy cooccurrence[x][y].direction[i].blue; 1105549a37e6cd4593dcb997230cd3584c5afead5552cristy if (image->colorspace == CMYKColorspace) 1106d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy channel_features[BlackPixelChannel].angular_second_moment[i]+= 11074c08aed51c5899665ade97263692328eea4af106cristy cooccurrence[x][y].direction[i].black* 11084c08aed51c5899665ade97263692328eea4af106cristy cooccurrence[x][y].direction[i].black; 110917f11b056210f082a6d0e54ac5d68e6d72fa76b2cristy if (image->alpha_trait != UndefinedPixelTrait) 1110d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy channel_features[AlphaPixelChannel].angular_second_moment[i]+= 11114c08aed51c5899665ade97263692328eea4af106cristy cooccurrence[x][y].direction[i].alpha* 11124c08aed51c5899665ade97263692328eea4af106cristy cooccurrence[x][y].direction[i].alpha; 11137396d88d575791c136bc6d060e613bdfbfb58f95cristy /* 11147396d88d575791c136bc6d060e613bdfbfb58f95cristy Correlation: measure of linear-dependencies in the image. 11157396d88d575791c136bc6d060e613bdfbfb58f95cristy */ 11167396d88d575791c136bc6d060e613bdfbfb58f95cristy sum[y].direction[i].red+=cooccurrence[x][y].direction[i].red; 11177396d88d575791c136bc6d060e613bdfbfb58f95cristy sum[y].direction[i].green+=cooccurrence[x][y].direction[i].green; 1118cdf8e1b14a1280a464eeaa3c8b37b8ece8b9cdb2cristy sum[y].direction[i].blue+=cooccurrence[x][y].direction[i].blue; 1119cdf8e1b14a1280a464eeaa3c8b37b8ece8b9cdb2cristy if (image->colorspace == CMYKColorspace) 11204c08aed51c5899665ade97263692328eea4af106cristy sum[y].direction[i].black+=cooccurrence[x][y].direction[i].black; 112117f11b056210f082a6d0e54ac5d68e6d72fa76b2cristy if (image->alpha_trait != UndefinedPixelTrait) 11224c08aed51c5899665ade97263692328eea4af106cristy sum[y].direction[i].alpha+=cooccurrence[x][y].direction[i].alpha; 1123cdf8e1b14a1280a464eeaa3c8b37b8ece8b9cdb2cristy correlation.direction[i].red+=x*y*cooccurrence[x][y].direction[i].red; 11247396d88d575791c136bc6d060e613bdfbfb58f95cristy correlation.direction[i].green+=x*y* 11257396d88d575791c136bc6d060e613bdfbfb58f95cristy cooccurrence[x][y].direction[i].green; 11267396d88d575791c136bc6d060e613bdfbfb58f95cristy correlation.direction[i].blue+=x*y* 11277396d88d575791c136bc6d060e613bdfbfb58f95cristy cooccurrence[x][y].direction[i].blue; 11287396d88d575791c136bc6d060e613bdfbfb58f95cristy if (image->colorspace == CMYKColorspace) 11294c08aed51c5899665ade97263692328eea4af106cristy correlation.direction[i].black+=x*y* 11304c08aed51c5899665ade97263692328eea4af106cristy cooccurrence[x][y].direction[i].black; 113117f11b056210f082a6d0e54ac5d68e6d72fa76b2cristy if (image->alpha_trait != UndefinedPixelTrait) 11324c08aed51c5899665ade97263692328eea4af106cristy correlation.direction[i].alpha+=x*y* 11334c08aed51c5899665ade97263692328eea4af106cristy cooccurrence[x][y].direction[i].alpha; 1134cf5e649a2c6de215ffc88ee00987090773ba0722cristy /* 1135cf5e649a2c6de215ffc88ee00987090773ba0722cristy Inverse Difference Moment. 1136cf5e649a2c6de215ffc88ee00987090773ba0722cristy */ 1137d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy channel_features[RedPixelChannel].inverse_difference_moment[i]+= 1138cf5e649a2c6de215ffc88ee00987090773ba0722cristy cooccurrence[x][y].direction[i].red/((y-x)*(y-x)+1); 1139d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy channel_features[GreenPixelChannel].inverse_difference_moment[i]+= 1140cf5e649a2c6de215ffc88ee00987090773ba0722cristy cooccurrence[x][y].direction[i].green/((y-x)*(y-x)+1); 1141d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy channel_features[BluePixelChannel].inverse_difference_moment[i]+= 1142cf5e649a2c6de215ffc88ee00987090773ba0722cristy cooccurrence[x][y].direction[i].blue/((y-x)*(y-x)+1); 1143cf5e649a2c6de215ffc88ee00987090773ba0722cristy if (image->colorspace == CMYKColorspace) 1144d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy channel_features[BlackPixelChannel].inverse_difference_moment[i]+= 11454c08aed51c5899665ade97263692328eea4af106cristy cooccurrence[x][y].direction[i].black/((y-x)*(y-x)+1); 114617f11b056210f082a6d0e54ac5d68e6d72fa76b2cristy if (image->alpha_trait != UndefinedPixelTrait) 1147d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy channel_features[AlphaPixelChannel].inverse_difference_moment[i]+= 11484c08aed51c5899665ade97263692328eea4af106cristy cooccurrence[x][y].direction[i].alpha/((y-x)*(y-x)+1); 1149e18977973bff5866de9aa6ed097aea40e27570d6cristy /* 1150e18977973bff5866de9aa6ed097aea40e27570d6cristy Sum average. 1151e18977973bff5866de9aa6ed097aea40e27570d6cristy */ 1152ffa10d0fe53ef0f0db63ee506c52695595976b99cristy density_xy[y+x+2].direction[i].red+= 1153e18977973bff5866de9aa6ed097aea40e27570d6cristy cooccurrence[x][y].direction[i].red; 1154ffa10d0fe53ef0f0db63ee506c52695595976b99cristy density_xy[y+x+2].direction[i].green+= 1155e18977973bff5866de9aa6ed097aea40e27570d6cristy cooccurrence[x][y].direction[i].green; 1156ffa10d0fe53ef0f0db63ee506c52695595976b99cristy density_xy[y+x+2].direction[i].blue+= 1157e18977973bff5866de9aa6ed097aea40e27570d6cristy cooccurrence[x][y].direction[i].blue; 1158e18977973bff5866de9aa6ed097aea40e27570d6cristy if (image->colorspace == CMYKColorspace) 11594c08aed51c5899665ade97263692328eea4af106cristy density_xy[y+x+2].direction[i].black+= 11604c08aed51c5899665ade97263692328eea4af106cristy cooccurrence[x][y].direction[i].black; 116117f11b056210f082a6d0e54ac5d68e6d72fa76b2cristy if (image->alpha_trait != UndefinedPixelTrait) 11624c08aed51c5899665ade97263692328eea4af106cristy density_xy[y+x+2].direction[i].alpha+= 11634c08aed51c5899665ade97263692328eea4af106cristy cooccurrence[x][y].direction[i].alpha; 1164e18977973bff5866de9aa6ed097aea40e27570d6cristy /* 1165e18977973bff5866de9aa6ed097aea40e27570d6cristy Entropy. 1166e18977973bff5866de9aa6ed097aea40e27570d6cristy */ 1167d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy channel_features[RedPixelChannel].entropy[i]-= 1168e18977973bff5866de9aa6ed097aea40e27570d6cristy cooccurrence[x][y].direction[i].red* 11690633a1f35940363594ecb272bb113e045fd65f93cristy MagickLog10(cooccurrence[x][y].direction[i].red); 1170d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy channel_features[GreenPixelChannel].entropy[i]-= 1171e18977973bff5866de9aa6ed097aea40e27570d6cristy cooccurrence[x][y].direction[i].green* 11720633a1f35940363594ecb272bb113e045fd65f93cristy MagickLog10(cooccurrence[x][y].direction[i].green); 1173d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy channel_features[BluePixelChannel].entropy[i]-= 1174e18977973bff5866de9aa6ed097aea40e27570d6cristy cooccurrence[x][y].direction[i].blue* 11750633a1f35940363594ecb272bb113e045fd65f93cristy MagickLog10(cooccurrence[x][y].direction[i].blue); 1176e18977973bff5866de9aa6ed097aea40e27570d6cristy if (image->colorspace == CMYKColorspace) 1177d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy channel_features[BlackPixelChannel].entropy[i]-= 11784c08aed51c5899665ade97263692328eea4af106cristy cooccurrence[x][y].direction[i].black* 11790633a1f35940363594ecb272bb113e045fd65f93cristy MagickLog10(cooccurrence[x][y].direction[i].black); 118017f11b056210f082a6d0e54ac5d68e6d72fa76b2cristy if (image->alpha_trait != UndefinedPixelTrait) 1181d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy channel_features[AlphaPixelChannel].entropy[i]-= 11824c08aed51c5899665ade97263692328eea4af106cristy cooccurrence[x][y].direction[i].alpha* 11830633a1f35940363594ecb272bb113e045fd65f93cristy MagickLog10(cooccurrence[x][y].direction[i].alpha); 1184e0acabf3ebf7da9eb716f98dfbbaa0d2f4d9d7e4cristy /* 1185e0acabf3ebf7da9eb716f98dfbbaa0d2f4d9d7e4cristy Information Measures of Correlation. 1186e0acabf3ebf7da9eb716f98dfbbaa0d2f4d9d7e4cristy */ 1187ffa10d0fe53ef0f0db63ee506c52695595976b99cristy density_x[x].direction[i].red+=cooccurrence[x][y].direction[i].red; 1188ffa10d0fe53ef0f0db63ee506c52695595976b99cristy density_x[x].direction[i].green+=cooccurrence[x][y].direction[i].green; 1189ffa10d0fe53ef0f0db63ee506c52695595976b99cristy density_x[x].direction[i].blue+=cooccurrence[x][y].direction[i].blue; 119017f11b056210f082a6d0e54ac5d68e6d72fa76b2cristy if (image->alpha_trait != UndefinedPixelTrait) 11914c08aed51c5899665ade97263692328eea4af106cristy density_x[x].direction[i].alpha+= 11924c08aed51c5899665ade97263692328eea4af106cristy cooccurrence[x][y].direction[i].alpha; 11934c08aed51c5899665ade97263692328eea4af106cristy if (image->colorspace == CMYKColorspace) 11944c08aed51c5899665ade97263692328eea4af106cristy density_x[x].direction[i].black+= 11954c08aed51c5899665ade97263692328eea4af106cristy cooccurrence[x][y].direction[i].black; 1196ffa10d0fe53ef0f0db63ee506c52695595976b99cristy density_y[y].direction[i].red+=cooccurrence[x][y].direction[i].red; 1197ffa10d0fe53ef0f0db63ee506c52695595976b99cristy density_y[y].direction[i].green+=cooccurrence[x][y].direction[i].green; 1198ffa10d0fe53ef0f0db63ee506c52695595976b99cristy density_y[y].direction[i].blue+=cooccurrence[x][y].direction[i].blue; 1199e0acabf3ebf7da9eb716f98dfbbaa0d2f4d9d7e4cristy if (image->colorspace == CMYKColorspace) 12004c08aed51c5899665ade97263692328eea4af106cristy density_y[y].direction[i].black+= 12014c08aed51c5899665ade97263692328eea4af106cristy cooccurrence[x][y].direction[i].black; 120217f11b056210f082a6d0e54ac5d68e6d72fa76b2cristy if (image->alpha_trait != UndefinedPixelTrait) 12034c08aed51c5899665ade97263692328eea4af106cristy density_y[y].direction[i].alpha+= 12044c08aed51c5899665ade97263692328eea4af106cristy cooccurrence[x][y].direction[i].alpha; 12057e9726d27d1b1e079b9b94b78f5ffd49352fcc91cristy } 1206cdf8e1b14a1280a464eeaa3c8b37b8ece8b9cdb2cristy mean.direction[i].red+=y*sum[y].direction[i].red; 1207cdf8e1b14a1280a464eeaa3c8b37b8ece8b9cdb2cristy sum_squares.direction[i].red+=y*y*sum[y].direction[i].red; 1208cdf8e1b14a1280a464eeaa3c8b37b8ece8b9cdb2cristy mean.direction[i].green+=y*sum[y].direction[i].green; 1209cdf8e1b14a1280a464eeaa3c8b37b8ece8b9cdb2cristy sum_squares.direction[i].green+=y*y*sum[y].direction[i].green; 1210cdf8e1b14a1280a464eeaa3c8b37b8ece8b9cdb2cristy mean.direction[i].blue+=y*sum[y].direction[i].blue; 1211cdf8e1b14a1280a464eeaa3c8b37b8ece8b9cdb2cristy sum_squares.direction[i].blue+=y*y*sum[y].direction[i].blue; 1212cdf8e1b14a1280a464eeaa3c8b37b8ece8b9cdb2cristy if (image->colorspace == CMYKColorspace) 1213cdf8e1b14a1280a464eeaa3c8b37b8ece8b9cdb2cristy { 12144c08aed51c5899665ade97263692328eea4af106cristy mean.direction[i].black+=y*sum[y].direction[i].black; 12154c08aed51c5899665ade97263692328eea4af106cristy sum_squares.direction[i].black+=y*y*sum[y].direction[i].black; 1216cdf8e1b14a1280a464eeaa3c8b37b8ece8b9cdb2cristy } 121717f11b056210f082a6d0e54ac5d68e6d72fa76b2cristy if (image->alpha_trait != UndefinedPixelTrait) 121853a727d91e1edeb3a67fa7d923db42974bba3b64cristy { 12194c08aed51c5899665ade97263692328eea4af106cristy mean.direction[i].alpha+=y*sum[y].direction[i].alpha; 12204c08aed51c5899665ade97263692328eea4af106cristy sum_squares.direction[i].alpha+=y*y*sum[y].direction[i].alpha; 122153a727d91e1edeb3a67fa7d923db42974bba3b64cristy } 12227e9726d27d1b1e079b9b94b78f5ffd49352fcc91cristy } 1223cdf8e1b14a1280a464eeaa3c8b37b8ece8b9cdb2cristy /* 1224cdf8e1b14a1280a464eeaa3c8b37b8ece8b9cdb2cristy Correlation: measure of linear-dependencies in the image. 1225cdf8e1b14a1280a464eeaa3c8b37b8ece8b9cdb2cristy */ 1226d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy channel_features[RedPixelChannel].correlation[i]= 1227cdf8e1b14a1280a464eeaa3c8b37b8ece8b9cdb2cristy (correlation.direction[i].red-mean.direction[i].red* 1228cdf8e1b14a1280a464eeaa3c8b37b8ece8b9cdb2cristy mean.direction[i].red)/(sqrt(sum_squares.direction[i].red- 1229cdf8e1b14a1280a464eeaa3c8b37b8ece8b9cdb2cristy (mean.direction[i].red*mean.direction[i].red))*sqrt( 1230cdf8e1b14a1280a464eeaa3c8b37b8ece8b9cdb2cristy sum_squares.direction[i].red-(mean.direction[i].red* 1231cdf8e1b14a1280a464eeaa3c8b37b8ece8b9cdb2cristy mean.direction[i].red))); 1232d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy channel_features[GreenPixelChannel].correlation[i]= 1233cdf8e1b14a1280a464eeaa3c8b37b8ece8b9cdb2cristy (correlation.direction[i].green-mean.direction[i].green* 1234cdf8e1b14a1280a464eeaa3c8b37b8ece8b9cdb2cristy mean.direction[i].green)/(sqrt(sum_squares.direction[i].green- 1235cdf8e1b14a1280a464eeaa3c8b37b8ece8b9cdb2cristy (mean.direction[i].green*mean.direction[i].green))*sqrt( 1236cdf8e1b14a1280a464eeaa3c8b37b8ece8b9cdb2cristy sum_squares.direction[i].green-(mean.direction[i].green* 1237cdf8e1b14a1280a464eeaa3c8b37b8ece8b9cdb2cristy mean.direction[i].green))); 1238d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy channel_features[BluePixelChannel].correlation[i]= 1239cdf8e1b14a1280a464eeaa3c8b37b8ece8b9cdb2cristy (correlation.direction[i].blue-mean.direction[i].blue* 1240cdf8e1b14a1280a464eeaa3c8b37b8ece8b9cdb2cristy mean.direction[i].blue)/(sqrt(sum_squares.direction[i].blue- 1241cdf8e1b14a1280a464eeaa3c8b37b8ece8b9cdb2cristy (mean.direction[i].blue*mean.direction[i].blue))*sqrt( 1242cdf8e1b14a1280a464eeaa3c8b37b8ece8b9cdb2cristy sum_squares.direction[i].blue-(mean.direction[i].blue* 1243cdf8e1b14a1280a464eeaa3c8b37b8ece8b9cdb2cristy mean.direction[i].blue))); 1244cdf8e1b14a1280a464eeaa3c8b37b8ece8b9cdb2cristy if (image->colorspace == CMYKColorspace) 1245d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy channel_features[BlackPixelChannel].correlation[i]= 12464c08aed51c5899665ade97263692328eea4af106cristy (correlation.direction[i].black-mean.direction[i].black* 12474c08aed51c5899665ade97263692328eea4af106cristy mean.direction[i].black)/(sqrt(sum_squares.direction[i].black- 12484c08aed51c5899665ade97263692328eea4af106cristy (mean.direction[i].black*mean.direction[i].black))*sqrt( 12494c08aed51c5899665ade97263692328eea4af106cristy sum_squares.direction[i].black-(mean.direction[i].black* 12504c08aed51c5899665ade97263692328eea4af106cristy mean.direction[i].black))); 125117f11b056210f082a6d0e54ac5d68e6d72fa76b2cristy if (image->alpha_trait != UndefinedPixelTrait) 1252d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy channel_features[AlphaPixelChannel].correlation[i]= 12534c08aed51c5899665ade97263692328eea4af106cristy (correlation.direction[i].alpha-mean.direction[i].alpha* 12544c08aed51c5899665ade97263692328eea4af106cristy mean.direction[i].alpha)/(sqrt(sum_squares.direction[i].alpha- 12554c08aed51c5899665ade97263692328eea4af106cristy (mean.direction[i].alpha*mean.direction[i].alpha))*sqrt( 12564c08aed51c5899665ade97263692328eea4af106cristy sum_squares.direction[i].alpha-(mean.direction[i].alpha* 12574c08aed51c5899665ade97263692328eea4af106cristy mean.direction[i].alpha))); 12587e9726d27d1b1e079b9b94b78f5ffd49352fcc91cristy } 1259cf5e649a2c6de215ffc88ee00987090773ba0722cristy /* 1260cf5e649a2c6de215ffc88ee00987090773ba0722cristy Compute more texture features. 1261cf5e649a2c6de215ffc88ee00987090773ba0722cristy */ 1262e18977973bff5866de9aa6ed097aea40e27570d6cristy#if defined(MAGICKCORE_OPENMP_SUPPORT) 1263ac245f8a51ea65b085d751c41d8ca4b426bdfe5bcristy #pragma omp parallel for schedule(static,4) shared(status) \ 12645e6b259130f9dbe0da4666f734937017babe573acristy magick_threads(image,image,number_grays,1) 1265e18977973bff5866de9aa6ed097aea40e27570d6cristy#endif 1266e18977973bff5866de9aa6ed097aea40e27570d6cristy for (i=0; i < 4; i++) 1267e18977973bff5866de9aa6ed097aea40e27570d6cristy { 1268bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy register ssize_t 1269e18977973bff5866de9aa6ed097aea40e27570d6cristy x; 1270e18977973bff5866de9aa6ed097aea40e27570d6cristy 1271bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (x=2; x < (ssize_t) (2*number_grays); x++) 1272e18977973bff5866de9aa6ed097aea40e27570d6cristy { 1273e18977973bff5866de9aa6ed097aea40e27570d6cristy /* 1274e18977973bff5866de9aa6ed097aea40e27570d6cristy Sum average. 1275e18977973bff5866de9aa6ed097aea40e27570d6cristy */ 1276d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy channel_features[RedPixelChannel].sum_average[i]+= 1277ffa10d0fe53ef0f0db63ee506c52695595976b99cristy x*density_xy[x].direction[i].red; 1278d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy channel_features[GreenPixelChannel].sum_average[i]+= 1279ffa10d0fe53ef0f0db63ee506c52695595976b99cristy x*density_xy[x].direction[i].green; 1280d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy channel_features[BluePixelChannel].sum_average[i]+= 1281ffa10d0fe53ef0f0db63ee506c52695595976b99cristy x*density_xy[x].direction[i].blue; 1282e18977973bff5866de9aa6ed097aea40e27570d6cristy if (image->colorspace == CMYKColorspace) 1283d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy channel_features[BlackPixelChannel].sum_average[i]+= 12844c08aed51c5899665ade97263692328eea4af106cristy x*density_xy[x].direction[i].black; 128517f11b056210f082a6d0e54ac5d68e6d72fa76b2cristy if (image->alpha_trait != UndefinedPixelTrait) 1286d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy channel_features[AlphaPixelChannel].sum_average[i]+= 12874c08aed51c5899665ade97263692328eea4af106cristy x*density_xy[x].direction[i].alpha; 1288e18977973bff5866de9aa6ed097aea40e27570d6cristy /* 1289e18977973bff5866de9aa6ed097aea40e27570d6cristy Sum entropy. 1290e18977973bff5866de9aa6ed097aea40e27570d6cristy */ 1291d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy channel_features[RedPixelChannel].sum_entropy[i]-= 1292ffa10d0fe53ef0f0db63ee506c52695595976b99cristy density_xy[x].direction[i].red* 12930633a1f35940363594ecb272bb113e045fd65f93cristy MagickLog10(density_xy[x].direction[i].red); 1294d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy channel_features[GreenPixelChannel].sum_entropy[i]-= 1295ffa10d0fe53ef0f0db63ee506c52695595976b99cristy density_xy[x].direction[i].green* 12960633a1f35940363594ecb272bb113e045fd65f93cristy MagickLog10(density_xy[x].direction[i].green); 1297d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy channel_features[BluePixelChannel].sum_entropy[i]-= 1298ffa10d0fe53ef0f0db63ee506c52695595976b99cristy density_xy[x].direction[i].blue* 12990633a1f35940363594ecb272bb113e045fd65f93cristy MagickLog10(density_xy[x].direction[i].blue); 1300e18977973bff5866de9aa6ed097aea40e27570d6cristy if (image->colorspace == CMYKColorspace) 1301d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy channel_features[BlackPixelChannel].sum_entropy[i]-= 13024c08aed51c5899665ade97263692328eea4af106cristy density_xy[x].direction[i].black* 13030633a1f35940363594ecb272bb113e045fd65f93cristy MagickLog10(density_xy[x].direction[i].black); 130417f11b056210f082a6d0e54ac5d68e6d72fa76b2cristy if (image->alpha_trait != UndefinedPixelTrait) 1305d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy channel_features[AlphaPixelChannel].sum_entropy[i]-= 13064c08aed51c5899665ade97263692328eea4af106cristy density_xy[x].direction[i].alpha* 13070633a1f35940363594ecb272bb113e045fd65f93cristy MagickLog10(density_xy[x].direction[i].alpha); 1308e18977973bff5866de9aa6ed097aea40e27570d6cristy /* 1309e18977973bff5866de9aa6ed097aea40e27570d6cristy Sum variance. 1310e18977973bff5866de9aa6ed097aea40e27570d6cristy */ 1311d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy channel_features[RedPixelChannel].sum_variance[i]+= 1312d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy (x-channel_features[RedPixelChannel].sum_entropy[i])* 1313d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy (x-channel_features[RedPixelChannel].sum_entropy[i])* 1314ffa10d0fe53ef0f0db63ee506c52695595976b99cristy density_xy[x].direction[i].red; 1315d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy channel_features[GreenPixelChannel].sum_variance[i]+= 1316d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy (x-channel_features[GreenPixelChannel].sum_entropy[i])* 1317d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy (x-channel_features[GreenPixelChannel].sum_entropy[i])* 1318ffa10d0fe53ef0f0db63ee506c52695595976b99cristy density_xy[x].direction[i].green; 1319d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy channel_features[BluePixelChannel].sum_variance[i]+= 1320d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy (x-channel_features[BluePixelChannel].sum_entropy[i])* 1321d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy (x-channel_features[BluePixelChannel].sum_entropy[i])* 1322ffa10d0fe53ef0f0db63ee506c52695595976b99cristy density_xy[x].direction[i].blue; 1323e18977973bff5866de9aa6ed097aea40e27570d6cristy if (image->colorspace == CMYKColorspace) 1324d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy channel_features[BlackPixelChannel].sum_variance[i]+= 1325d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy (x-channel_features[BlackPixelChannel].sum_entropy[i])* 1326d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy (x-channel_features[BlackPixelChannel].sum_entropy[i])* 13274c08aed51c5899665ade97263692328eea4af106cristy density_xy[x].direction[i].black; 132817f11b056210f082a6d0e54ac5d68e6d72fa76b2cristy if (image->alpha_trait != UndefinedPixelTrait) 1329d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy channel_features[AlphaPixelChannel].sum_variance[i]+= 1330d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy (x-channel_features[AlphaPixelChannel].sum_entropy[i])* 1331d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy (x-channel_features[AlphaPixelChannel].sum_entropy[i])* 13324c08aed51c5899665ade97263692328eea4af106cristy density_xy[x].direction[i].alpha; 1333e18977973bff5866de9aa6ed097aea40e27570d6cristy } 1334e18977973bff5866de9aa6ed097aea40e27570d6cristy } 1335e18977973bff5866de9aa6ed097aea40e27570d6cristy /* 1336e18977973bff5866de9aa6ed097aea40e27570d6cristy Compute more texture features. 1337e18977973bff5866de9aa6ed097aea40e27570d6cristy */ 1338cf5e649a2c6de215ffc88ee00987090773ba0722cristy#if defined(MAGICKCORE_OPENMP_SUPPORT) 1339ac245f8a51ea65b085d751c41d8ca4b426bdfe5bcristy #pragma omp parallel for schedule(static,4) shared(status) \ 13405e6b259130f9dbe0da4666f734937017babe573acristy magick_threads(image,image,number_grays,1) 1341cf5e649a2c6de215ffc88ee00987090773ba0722cristy#endif 1342cf5e649a2c6de215ffc88ee00987090773ba0722cristy for (i=0; i < 4; i++) 1343cf5e649a2c6de215ffc88ee00987090773ba0722cristy { 1344bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy register ssize_t 1345cf5e649a2c6de215ffc88ee00987090773ba0722cristy y; 1346cf5e649a2c6de215ffc88ee00987090773ba0722cristy 1347bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (y=0; y < (ssize_t) number_grays; y++) 1348cf5e649a2c6de215ffc88ee00987090773ba0722cristy { 1349bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy register ssize_t 1350cf5e649a2c6de215ffc88ee00987090773ba0722cristy x; 1351cf5e649a2c6de215ffc88ee00987090773ba0722cristy 1352bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (x=0; x < (ssize_t) number_grays; x++) 1353cf5e649a2c6de215ffc88ee00987090773ba0722cristy { 1354cf5e649a2c6de215ffc88ee00987090773ba0722cristy /* 1355cf5e649a2c6de215ffc88ee00987090773ba0722cristy Sum of Squares: Variance 1356cf5e649a2c6de215ffc88ee00987090773ba0722cristy */ 1357cf5e649a2c6de215ffc88ee00987090773ba0722cristy variance.direction[i].red+=(y-mean.direction[i].red+1)* 1358cf5e649a2c6de215ffc88ee00987090773ba0722cristy (y-mean.direction[i].red+1)*cooccurrence[x][y].direction[i].red; 1359cf5e649a2c6de215ffc88ee00987090773ba0722cristy variance.direction[i].green+=(y-mean.direction[i].green+1)* 1360cf5e649a2c6de215ffc88ee00987090773ba0722cristy (y-mean.direction[i].green+1)*cooccurrence[x][y].direction[i].green; 1361cf5e649a2c6de215ffc88ee00987090773ba0722cristy variance.direction[i].blue+=(y-mean.direction[i].blue+1)* 1362cf5e649a2c6de215ffc88ee00987090773ba0722cristy (y-mean.direction[i].blue+1)*cooccurrence[x][y].direction[i].blue; 136353a727d91e1edeb3a67fa7d923db42974bba3b64cristy if (image->colorspace == CMYKColorspace) 13644c08aed51c5899665ade97263692328eea4af106cristy variance.direction[i].black+=(y-mean.direction[i].black+1)* 13654c08aed51c5899665ade97263692328eea4af106cristy (y-mean.direction[i].black+1)*cooccurrence[x][y].direction[i].black; 136617f11b056210f082a6d0e54ac5d68e6d72fa76b2cristy if (image->alpha_trait != UndefinedPixelTrait) 13674c08aed51c5899665ade97263692328eea4af106cristy variance.direction[i].alpha+=(y-mean.direction[i].alpha+1)* 13684c08aed51c5899665ade97263692328eea4af106cristy (y-mean.direction[i].alpha+1)* 13694c08aed51c5899665ade97263692328eea4af106cristy cooccurrence[x][y].direction[i].alpha; 1370e18977973bff5866de9aa6ed097aea40e27570d6cristy /* 1371e0acabf3ebf7da9eb716f98dfbbaa0d2f4d9d7e4cristy Sum average / Difference Variance. 1372e18977973bff5866de9aa6ed097aea40e27570d6cristy */ 1373ffa10d0fe53ef0f0db63ee506c52695595976b99cristy density_xy[MagickAbsoluteValue(y-x)].direction[i].red+= 1374e18977973bff5866de9aa6ed097aea40e27570d6cristy cooccurrence[x][y].direction[i].red; 1375ffa10d0fe53ef0f0db63ee506c52695595976b99cristy density_xy[MagickAbsoluteValue(y-x)].direction[i].green+= 1376e18977973bff5866de9aa6ed097aea40e27570d6cristy cooccurrence[x][y].direction[i].green; 1377ffa10d0fe53ef0f0db63ee506c52695595976b99cristy density_xy[MagickAbsoluteValue(y-x)].direction[i].blue+= 1378e18977973bff5866de9aa6ed097aea40e27570d6cristy cooccurrence[x][y].direction[i].blue; 1379e18977973bff5866de9aa6ed097aea40e27570d6cristy if (image->colorspace == CMYKColorspace) 13804c08aed51c5899665ade97263692328eea4af106cristy density_xy[MagickAbsoluteValue(y-x)].direction[i].black+= 13814c08aed51c5899665ade97263692328eea4af106cristy cooccurrence[x][y].direction[i].black; 138217f11b056210f082a6d0e54ac5d68e6d72fa76b2cristy if (image->alpha_trait != UndefinedPixelTrait) 13834c08aed51c5899665ade97263692328eea4af106cristy density_xy[MagickAbsoluteValue(y-x)].direction[i].alpha+= 13844c08aed51c5899665ade97263692328eea4af106cristy cooccurrence[x][y].direction[i].alpha; 1385e0acabf3ebf7da9eb716f98dfbbaa0d2f4d9d7e4cristy /* 1386e0acabf3ebf7da9eb716f98dfbbaa0d2f4d9d7e4cristy Information Measures of Correlation. 1387e0acabf3ebf7da9eb716f98dfbbaa0d2f4d9d7e4cristy */ 1388ffa10d0fe53ef0f0db63ee506c52695595976b99cristy entropy_xy.direction[i].red-=cooccurrence[x][y].direction[i].red* 13890633a1f35940363594ecb272bb113e045fd65f93cristy MagickLog10(cooccurrence[x][y].direction[i].red); 1390ffa10d0fe53ef0f0db63ee506c52695595976b99cristy entropy_xy.direction[i].green-=cooccurrence[x][y].direction[i].green* 13910633a1f35940363594ecb272bb113e045fd65f93cristy MagickLog10(cooccurrence[x][y].direction[i].green); 1392ffa10d0fe53ef0f0db63ee506c52695595976b99cristy entropy_xy.direction[i].blue-=cooccurrence[x][y].direction[i].blue* 13930633a1f35940363594ecb272bb113e045fd65f93cristy MagickLog10(cooccurrence[x][y].direction[i].blue); 139453a727d91e1edeb3a67fa7d923db42974bba3b64cristy if (image->colorspace == CMYKColorspace) 13954c08aed51c5899665ade97263692328eea4af106cristy entropy_xy.direction[i].black-=cooccurrence[x][y].direction[i].black* 13960633a1f35940363594ecb272bb113e045fd65f93cristy MagickLog10(cooccurrence[x][y].direction[i].black); 139717f11b056210f082a6d0e54ac5d68e6d72fa76b2cristy if (image->alpha_trait != UndefinedPixelTrait) 13984c08aed51c5899665ade97263692328eea4af106cristy entropy_xy.direction[i].alpha-= 13990633a1f35940363594ecb272bb113e045fd65f93cristy cooccurrence[x][y].direction[i].alpha*MagickLog10( 14000633a1f35940363594ecb272bb113e045fd65f93cristy cooccurrence[x][y].direction[i].alpha); 1401ffa10d0fe53ef0f0db63ee506c52695595976b99cristy entropy_xy1.direction[i].red-=(cooccurrence[x][y].direction[i].red* 14020633a1f35940363594ecb272bb113e045fd65f93cristy MagickLog10(density_x[x].direction[i].red*density_y[y].direction[i].red)); 1403ffa10d0fe53ef0f0db63ee506c52695595976b99cristy entropy_xy1.direction[i].green-=(cooccurrence[x][y].direction[i].green* 14040633a1f35940363594ecb272bb113e045fd65f93cristy MagickLog10(density_x[x].direction[i].green* 14050633a1f35940363594ecb272bb113e045fd65f93cristy density_y[y].direction[i].green)); 1406ffa10d0fe53ef0f0db63ee506c52695595976b99cristy entropy_xy1.direction[i].blue-=(cooccurrence[x][y].direction[i].blue* 14070633a1f35940363594ecb272bb113e045fd65f93cristy MagickLog10(density_x[x].direction[i].blue*density_y[y].direction[i].blue)); 1408e0acabf3ebf7da9eb716f98dfbbaa0d2f4d9d7e4cristy if (image->colorspace == CMYKColorspace) 14094c08aed51c5899665ade97263692328eea4af106cristy entropy_xy1.direction[i].black-=( 14100633a1f35940363594ecb272bb113e045fd65f93cristy cooccurrence[x][y].direction[i].black*MagickLog10( 14110633a1f35940363594ecb272bb113e045fd65f93cristy density_x[x].direction[i].black*density_y[y].direction[i].black)); 141217f11b056210f082a6d0e54ac5d68e6d72fa76b2cristy if (image->alpha_trait != UndefinedPixelTrait) 14134c08aed51c5899665ade97263692328eea4af106cristy entropy_xy1.direction[i].alpha-=( 14140633a1f35940363594ecb272bb113e045fd65f93cristy cooccurrence[x][y].direction[i].alpha*MagickLog10( 14150633a1f35940363594ecb272bb113e045fd65f93cristy density_x[x].direction[i].alpha*density_y[y].direction[i].alpha)); 1416ffa10d0fe53ef0f0db63ee506c52695595976b99cristy entropy_xy2.direction[i].red-=(density_x[x].direction[i].red* 14170633a1f35940363594ecb272bb113e045fd65f93cristy density_y[y].direction[i].red*MagickLog10(density_x[x].direction[i].red* 14180633a1f35940363594ecb272bb113e045fd65f93cristy density_y[y].direction[i].red)); 1419ffa10d0fe53ef0f0db63ee506c52695595976b99cristy entropy_xy2.direction[i].green-=(density_x[x].direction[i].green* 14200633a1f35940363594ecb272bb113e045fd65f93cristy density_y[y].direction[i].green*MagickLog10(density_x[x].direction[i].green* 14210633a1f35940363594ecb272bb113e045fd65f93cristy density_y[y].direction[i].green)); 1422ffa10d0fe53ef0f0db63ee506c52695595976b99cristy entropy_xy2.direction[i].blue-=(density_x[x].direction[i].blue* 14230633a1f35940363594ecb272bb113e045fd65f93cristy density_y[y].direction[i].blue*MagickLog10(density_x[x].direction[i].blue* 14240633a1f35940363594ecb272bb113e045fd65f93cristy density_y[y].direction[i].blue)); 1425e0acabf3ebf7da9eb716f98dfbbaa0d2f4d9d7e4cristy if (image->colorspace == CMYKColorspace) 14264c08aed51c5899665ade97263692328eea4af106cristy entropy_xy2.direction[i].black-=(density_x[x].direction[i].black* 14270633a1f35940363594ecb272bb113e045fd65f93cristy density_y[y].direction[i].black*MagickLog10( 14280633a1f35940363594ecb272bb113e045fd65f93cristy density_x[x].direction[i].black*density_y[y].direction[i].black)); 142917f11b056210f082a6d0e54ac5d68e6d72fa76b2cristy if (image->alpha_trait != UndefinedPixelTrait) 14304c08aed51c5899665ade97263692328eea4af106cristy entropy_xy2.direction[i].alpha-=(density_x[x].direction[i].alpha* 14310633a1f35940363594ecb272bb113e045fd65f93cristy density_y[y].direction[i].alpha*MagickLog10( 14320633a1f35940363594ecb272bb113e045fd65f93cristy density_x[x].direction[i].alpha*density_y[y].direction[i].alpha)); 1433cf5e649a2c6de215ffc88ee00987090773ba0722cristy } 1434cf5e649a2c6de215ffc88ee00987090773ba0722cristy } 1435d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy channel_features[RedPixelChannel].variance_sum_of_squares[i]= 1436cf5e649a2c6de215ffc88ee00987090773ba0722cristy variance.direction[i].red; 1437d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy channel_features[GreenPixelChannel].variance_sum_of_squares[i]= 1438cf5e649a2c6de215ffc88ee00987090773ba0722cristy variance.direction[i].green; 1439d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy channel_features[BluePixelChannel].variance_sum_of_squares[i]= 1440cf5e649a2c6de215ffc88ee00987090773ba0722cristy variance.direction[i].blue; 1441cf5e649a2c6de215ffc88ee00987090773ba0722cristy if (image->colorspace == CMYKColorspace) 1442d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy channel_features[BlackPixelChannel].variance_sum_of_squares[i]= 14434c08aed51c5899665ade97263692328eea4af106cristy variance.direction[i].black; 144417f11b056210f082a6d0e54ac5d68e6d72fa76b2cristy if (image->alpha_trait != UndefinedPixelTrait) 1445d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy channel_features[AlphaPixelChannel].variance_sum_of_squares[i]= 14464c08aed51c5899665ade97263692328eea4af106cristy variance.direction[i].alpha; 1447cf5e649a2c6de215ffc88ee00987090773ba0722cristy } 1448cf5e649a2c6de215ffc88ee00987090773ba0722cristy /* 1449cf5e649a2c6de215ffc88ee00987090773ba0722cristy Compute more texture features. 1450cf5e649a2c6de215ffc88ee00987090773ba0722cristy */ 1451e18977973bff5866de9aa6ed097aea40e27570d6cristy (void) ResetMagickMemory(&variance,0,sizeof(variance)); 1452e18977973bff5866de9aa6ed097aea40e27570d6cristy (void) ResetMagickMemory(&sum_squares,0,sizeof(sum_squares)); 1453e18977973bff5866de9aa6ed097aea40e27570d6cristy#if defined(MAGICKCORE_OPENMP_SUPPORT) 1454ac245f8a51ea65b085d751c41d8ca4b426bdfe5bcristy #pragma omp parallel for schedule(static,4) shared(status) \ 14555e6b259130f9dbe0da4666f734937017babe573acristy magick_threads(image,image,number_grays,1) 1456e18977973bff5866de9aa6ed097aea40e27570d6cristy#endif 1457e18977973bff5866de9aa6ed097aea40e27570d6cristy for (i=0; i < 4; i++) 1458e18977973bff5866de9aa6ed097aea40e27570d6cristy { 1459bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy register ssize_t 1460e18977973bff5866de9aa6ed097aea40e27570d6cristy x; 1461e18977973bff5866de9aa6ed097aea40e27570d6cristy 1462bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (x=0; x < (ssize_t) number_grays; x++) 1463e18977973bff5866de9aa6ed097aea40e27570d6cristy { 1464e0acabf3ebf7da9eb716f98dfbbaa0d2f4d9d7e4cristy /* 1465e0acabf3ebf7da9eb716f98dfbbaa0d2f4d9d7e4cristy Difference variance. 1466e0acabf3ebf7da9eb716f98dfbbaa0d2f4d9d7e4cristy */ 1467ffa10d0fe53ef0f0db63ee506c52695595976b99cristy variance.direction[i].red+=density_xy[x].direction[i].red; 1468ffa10d0fe53ef0f0db63ee506c52695595976b99cristy variance.direction[i].green+=density_xy[x].direction[i].green; 1469ffa10d0fe53ef0f0db63ee506c52695595976b99cristy variance.direction[i].blue+=density_xy[x].direction[i].blue; 1470e18977973bff5866de9aa6ed097aea40e27570d6cristy if (image->colorspace == CMYKColorspace) 14714c08aed51c5899665ade97263692328eea4af106cristy variance.direction[i].black+=density_xy[x].direction[i].black; 147217f11b056210f082a6d0e54ac5d68e6d72fa76b2cristy if (image->alpha_trait != UndefinedPixelTrait) 14734c08aed51c5899665ade97263692328eea4af106cristy variance.direction[i].alpha+=density_xy[x].direction[i].alpha; 1474ffa10d0fe53ef0f0db63ee506c52695595976b99cristy sum_squares.direction[i].red+=density_xy[x].direction[i].red* 1475ffa10d0fe53ef0f0db63ee506c52695595976b99cristy density_xy[x].direction[i].red; 1476ffa10d0fe53ef0f0db63ee506c52695595976b99cristy sum_squares.direction[i].green+=density_xy[x].direction[i].green* 1477ffa10d0fe53ef0f0db63ee506c52695595976b99cristy density_xy[x].direction[i].green; 1478ffa10d0fe53ef0f0db63ee506c52695595976b99cristy sum_squares.direction[i].blue+=density_xy[x].direction[i].blue* 1479ffa10d0fe53ef0f0db63ee506c52695595976b99cristy density_xy[x].direction[i].blue; 1480e18977973bff5866de9aa6ed097aea40e27570d6cristy if (image->colorspace == CMYKColorspace) 14814c08aed51c5899665ade97263692328eea4af106cristy sum_squares.direction[i].black+=density_xy[x].direction[i].black* 14824c08aed51c5899665ade97263692328eea4af106cristy density_xy[x].direction[i].black; 148317f11b056210f082a6d0e54ac5d68e6d72fa76b2cristy if (image->alpha_trait != UndefinedPixelTrait) 14844c08aed51c5899665ade97263692328eea4af106cristy sum_squares.direction[i].alpha+=density_xy[x].direction[i].alpha* 14854c08aed51c5899665ade97263692328eea4af106cristy density_xy[x].direction[i].alpha; 1486f6214de6bb7f45514a52bf72c3977591aeeddc94cristy /* 1487f6214de6bb7f45514a52bf72c3977591aeeddc94cristy Difference entropy. 1488f6214de6bb7f45514a52bf72c3977591aeeddc94cristy */ 1489d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy channel_features[RedPixelChannel].difference_entropy[i]-= 1490ffa10d0fe53ef0f0db63ee506c52695595976b99cristy density_xy[x].direction[i].red* 14910633a1f35940363594ecb272bb113e045fd65f93cristy MagickLog10(density_xy[x].direction[i].red); 1492d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy channel_features[GreenPixelChannel].difference_entropy[i]-= 1493ffa10d0fe53ef0f0db63ee506c52695595976b99cristy density_xy[x].direction[i].green* 14940633a1f35940363594ecb272bb113e045fd65f93cristy MagickLog10(density_xy[x].direction[i].green); 1495d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy channel_features[BluePixelChannel].difference_entropy[i]-= 1496ffa10d0fe53ef0f0db63ee506c52695595976b99cristy density_xy[x].direction[i].blue* 14970633a1f35940363594ecb272bb113e045fd65f93cristy MagickLog10(density_xy[x].direction[i].blue); 1498f6214de6bb7f45514a52bf72c3977591aeeddc94cristy if (image->colorspace == CMYKColorspace) 1499d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy channel_features[BlackPixelChannel].difference_entropy[i]-= 15004c08aed51c5899665ade97263692328eea4af106cristy density_xy[x].direction[i].black* 15010633a1f35940363594ecb272bb113e045fd65f93cristy MagickLog10(density_xy[x].direction[i].black); 150217f11b056210f082a6d0e54ac5d68e6d72fa76b2cristy if (image->alpha_trait != UndefinedPixelTrait) 1503d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy channel_features[AlphaPixelChannel].difference_entropy[i]-= 15044c08aed51c5899665ade97263692328eea4af106cristy density_xy[x].direction[i].alpha* 15050633a1f35940363594ecb272bb113e045fd65f93cristy MagickLog10(density_xy[x].direction[i].alpha); 1506e0acabf3ebf7da9eb716f98dfbbaa0d2f4d9d7e4cristy /* 1507e0acabf3ebf7da9eb716f98dfbbaa0d2f4d9d7e4cristy Information Measures of Correlation. 1508e0acabf3ebf7da9eb716f98dfbbaa0d2f4d9d7e4cristy */ 1509ffa10d0fe53ef0f0db63ee506c52695595976b99cristy entropy_x.direction[i].red-=(density_x[x].direction[i].red* 15100633a1f35940363594ecb272bb113e045fd65f93cristy MagickLog10(density_x[x].direction[i].red)); 1511ffa10d0fe53ef0f0db63ee506c52695595976b99cristy entropy_x.direction[i].green-=(density_x[x].direction[i].green* 15120633a1f35940363594ecb272bb113e045fd65f93cristy MagickLog10(density_x[x].direction[i].green)); 1513ffa10d0fe53ef0f0db63ee506c52695595976b99cristy entropy_x.direction[i].blue-=(density_x[x].direction[i].blue* 15140633a1f35940363594ecb272bb113e045fd65f93cristy MagickLog10(density_x[x].direction[i].blue)); 1515e0acabf3ebf7da9eb716f98dfbbaa0d2f4d9d7e4cristy if (image->colorspace == CMYKColorspace) 15164c08aed51c5899665ade97263692328eea4af106cristy entropy_x.direction[i].black-=(density_x[x].direction[i].black* 15170633a1f35940363594ecb272bb113e045fd65f93cristy MagickLog10(density_x[x].direction[i].black)); 151817f11b056210f082a6d0e54ac5d68e6d72fa76b2cristy if (image->alpha_trait != UndefinedPixelTrait) 15194c08aed51c5899665ade97263692328eea4af106cristy entropy_x.direction[i].alpha-=(density_x[x].direction[i].alpha* 15200633a1f35940363594ecb272bb113e045fd65f93cristy MagickLog10(density_x[x].direction[i].alpha)); 152153a727d91e1edeb3a67fa7d923db42974bba3b64cristy entropy_y.direction[i].red-=(density_y[x].direction[i].red* 15220633a1f35940363594ecb272bb113e045fd65f93cristy MagickLog10(density_y[x].direction[i].red)); 152353a727d91e1edeb3a67fa7d923db42974bba3b64cristy entropy_y.direction[i].green-=(density_y[x].direction[i].green* 15240633a1f35940363594ecb272bb113e045fd65f93cristy MagickLog10(density_y[x].direction[i].green)); 152553a727d91e1edeb3a67fa7d923db42974bba3b64cristy entropy_y.direction[i].blue-=(density_y[x].direction[i].blue* 15260633a1f35940363594ecb272bb113e045fd65f93cristy MagickLog10(density_y[x].direction[i].blue)); 1527e0acabf3ebf7da9eb716f98dfbbaa0d2f4d9d7e4cristy if (image->colorspace == CMYKColorspace) 15284c08aed51c5899665ade97263692328eea4af106cristy entropy_y.direction[i].black-=(density_y[x].direction[i].black* 15290633a1f35940363594ecb272bb113e045fd65f93cristy MagickLog10(density_y[x].direction[i].black)); 153017f11b056210f082a6d0e54ac5d68e6d72fa76b2cristy if (image->alpha_trait != UndefinedPixelTrait) 15314c08aed51c5899665ade97263692328eea4af106cristy entropy_y.direction[i].alpha-=(density_y[x].direction[i].alpha* 15320633a1f35940363594ecb272bb113e045fd65f93cristy MagickLog10(density_y[x].direction[i].alpha)); 1533e18977973bff5866de9aa6ed097aea40e27570d6cristy } 1534f6214de6bb7f45514a52bf72c3977591aeeddc94cristy /* 1535f6214de6bb7f45514a52bf72c3977591aeeddc94cristy Difference variance. 1536f6214de6bb7f45514a52bf72c3977591aeeddc94cristy */ 1537d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy channel_features[RedPixelChannel].difference_variance[i]= 1538e0e19dc554957d2413f7fca5063a75fd92b8a12bcristy (((double) number_grays*number_grays*sum_squares.direction[i].red)- 1539e18977973bff5866de9aa6ed097aea40e27570d6cristy (variance.direction[i].red*variance.direction[i].red))/ 1540e18977973bff5866de9aa6ed097aea40e27570d6cristy ((double) number_grays*number_grays*number_grays*number_grays); 1541d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy channel_features[GreenPixelChannel].difference_variance[i]= 1542e0e19dc554957d2413f7fca5063a75fd92b8a12bcristy (((double) number_grays*number_grays*sum_squares.direction[i].green)- 1543e18977973bff5866de9aa6ed097aea40e27570d6cristy (variance.direction[i].green*variance.direction[i].green))/ 1544e18977973bff5866de9aa6ed097aea40e27570d6cristy ((double) number_grays*number_grays*number_grays*number_grays); 1545d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy channel_features[BluePixelChannel].difference_variance[i]= 1546e0e19dc554957d2413f7fca5063a75fd92b8a12bcristy (((double) number_grays*number_grays*sum_squares.direction[i].blue)- 1547e18977973bff5866de9aa6ed097aea40e27570d6cristy (variance.direction[i].blue*variance.direction[i].blue))/ 1548e18977973bff5866de9aa6ed097aea40e27570d6cristy ((double) number_grays*number_grays*number_grays*number_grays); 15494c08aed51c5899665ade97263692328eea4af106cristy if (image->colorspace == CMYKColorspace) 1550d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy channel_features[BlackPixelChannel].difference_variance[i]= 15514c08aed51c5899665ade97263692328eea4af106cristy (((double) number_grays*number_grays*sum_squares.direction[i].black)- 15524c08aed51c5899665ade97263692328eea4af106cristy (variance.direction[i].black*variance.direction[i].black))/ 15534c08aed51c5899665ade97263692328eea4af106cristy ((double) number_grays*number_grays*number_grays*number_grays); 155417f11b056210f082a6d0e54ac5d68e6d72fa76b2cristy if (image->alpha_trait != UndefinedPixelTrait) 1555d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy channel_features[AlphaPixelChannel].difference_variance[i]= 15564c08aed51c5899665ade97263692328eea4af106cristy (((double) number_grays*number_grays*sum_squares.direction[i].alpha)- 15574c08aed51c5899665ade97263692328eea4af106cristy (variance.direction[i].alpha*variance.direction[i].alpha))/ 1558e18977973bff5866de9aa6ed097aea40e27570d6cristy ((double) number_grays*number_grays*number_grays*number_grays); 1559e0acabf3ebf7da9eb716f98dfbbaa0d2f4d9d7e4cristy /* 1560e0acabf3ebf7da9eb716f98dfbbaa0d2f4d9d7e4cristy Information Measures of Correlation. 1561e0acabf3ebf7da9eb716f98dfbbaa0d2f4d9d7e4cristy */ 1562d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy channel_features[RedPixelChannel].measure_of_correlation_1[i]= 1563ffa10d0fe53ef0f0db63ee506c52695595976b99cristy (entropy_xy.direction[i].red-entropy_xy1.direction[i].red)/ 1564ffa10d0fe53ef0f0db63ee506c52695595976b99cristy (entropy_x.direction[i].red > entropy_y.direction[i].red ? 1565ffa10d0fe53ef0f0db63ee506c52695595976b99cristy entropy_x.direction[i].red : entropy_y.direction[i].red); 1566d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy channel_features[GreenPixelChannel].measure_of_correlation_1[i]= 1567ffa10d0fe53ef0f0db63ee506c52695595976b99cristy (entropy_xy.direction[i].green-entropy_xy1.direction[i].green)/ 1568ffa10d0fe53ef0f0db63ee506c52695595976b99cristy (entropy_x.direction[i].green > entropy_y.direction[i].green ? 1569ffa10d0fe53ef0f0db63ee506c52695595976b99cristy entropy_x.direction[i].green : entropy_y.direction[i].green); 1570d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy channel_features[BluePixelChannel].measure_of_correlation_1[i]= 1571ffa10d0fe53ef0f0db63ee506c52695595976b99cristy (entropy_xy.direction[i].blue-entropy_xy1.direction[i].blue)/ 1572ffa10d0fe53ef0f0db63ee506c52695595976b99cristy (entropy_x.direction[i].blue > entropy_y.direction[i].blue ? 1573ffa10d0fe53ef0f0db63ee506c52695595976b99cristy entropy_x.direction[i].blue : entropy_y.direction[i].blue); 1574e0acabf3ebf7da9eb716f98dfbbaa0d2f4d9d7e4cristy if (image->colorspace == CMYKColorspace) 1575d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy channel_features[BlackPixelChannel].measure_of_correlation_1[i]= 15764c08aed51c5899665ade97263692328eea4af106cristy (entropy_xy.direction[i].black-entropy_xy1.direction[i].black)/ 15774c08aed51c5899665ade97263692328eea4af106cristy (entropy_x.direction[i].black > entropy_y.direction[i].black ? 15784c08aed51c5899665ade97263692328eea4af106cristy entropy_x.direction[i].black : entropy_y.direction[i].black); 157917f11b056210f082a6d0e54ac5d68e6d72fa76b2cristy if (image->alpha_trait != UndefinedPixelTrait) 1580d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy channel_features[AlphaPixelChannel].measure_of_correlation_1[i]= 15814c08aed51c5899665ade97263692328eea4af106cristy (entropy_xy.direction[i].alpha-entropy_xy1.direction[i].alpha)/ 15824c08aed51c5899665ade97263692328eea4af106cristy (entropy_x.direction[i].alpha > entropy_y.direction[i].alpha ? 15834c08aed51c5899665ade97263692328eea4af106cristy entropy_x.direction[i].alpha : entropy_y.direction[i].alpha); 1584d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy channel_features[RedPixelChannel].measure_of_correlation_2[i]= 15853bdd925dbb0804df99e548c50667670319655816cristy (sqrt(fabs(1.0-exp(-2.0*(double) (entropy_xy2.direction[i].red- 1586ffa10d0fe53ef0f0db63ee506c52695595976b99cristy entropy_xy.direction[i].red))))); 1587d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy channel_features[GreenPixelChannel].measure_of_correlation_2[i]= 15883bdd925dbb0804df99e548c50667670319655816cristy (sqrt(fabs(1.0-exp(-2.0*(double) (entropy_xy2.direction[i].green- 1589ffa10d0fe53ef0f0db63ee506c52695595976b99cristy entropy_xy.direction[i].green))))); 1590d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy channel_features[BluePixelChannel].measure_of_correlation_2[i]= 15913bdd925dbb0804df99e548c50667670319655816cristy (sqrt(fabs(1.0-exp(-2.0*(double) (entropy_xy2.direction[i].blue- 1592ffa10d0fe53ef0f0db63ee506c52695595976b99cristy entropy_xy.direction[i].blue))))); 1593e0acabf3ebf7da9eb716f98dfbbaa0d2f4d9d7e4cristy if (image->colorspace == CMYKColorspace) 1594d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy channel_features[BlackPixelChannel].measure_of_correlation_2[i]= 15953bdd925dbb0804df99e548c50667670319655816cristy (sqrt(fabs(1.0-exp(-2.0*(double) (entropy_xy2.direction[i].black- 15964c08aed51c5899665ade97263692328eea4af106cristy entropy_xy.direction[i].black))))); 159717f11b056210f082a6d0e54ac5d68e6d72fa76b2cristy if (image->alpha_trait != UndefinedPixelTrait) 1598d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy channel_features[AlphaPixelChannel].measure_of_correlation_2[i]= 15993bdd925dbb0804df99e548c50667670319655816cristy (sqrt(fabs(1.0-exp(-2.0*(double) (entropy_xy2.direction[i].alpha- 16004c08aed51c5899665ade97263692328eea4af106cristy entropy_xy.direction[i].alpha))))); 1601e18977973bff5866de9aa6ed097aea40e27570d6cristy } 1602e18977973bff5866de9aa6ed097aea40e27570d6cristy /* 16032fc10e5aedab9144531a4668dc7526e3caf514e1cristy Compute more texture features. 16042fc10e5aedab9144531a4668dc7526e3caf514e1cristy */ 16052fc10e5aedab9144531a4668dc7526e3caf514e1cristy#if defined(MAGICKCORE_OPENMP_SUPPORT) 16062fc10e5aedab9144531a4668dc7526e3caf514e1cristy #pragma omp parallel for schedule(static,4) shared(status) \ 16072fc10e5aedab9144531a4668dc7526e3caf514e1cristy magick_threads(image,image,number_grays,1) 16082fc10e5aedab9144531a4668dc7526e3caf514e1cristy#endif 16092fc10e5aedab9144531a4668dc7526e3caf514e1cristy for (i=0; i < 4; i++) 16102fc10e5aedab9144531a4668dc7526e3caf514e1cristy { 16112fc10e5aedab9144531a4668dc7526e3caf514e1cristy ssize_t 16122fc10e5aedab9144531a4668dc7526e3caf514e1cristy z; 16132fc10e5aedab9144531a4668dc7526e3caf514e1cristy 16142fc10e5aedab9144531a4668dc7526e3caf514e1cristy for (z=0; z < (ssize_t) number_grays; z++) 16152fc10e5aedab9144531a4668dc7526e3caf514e1cristy { 16162fc10e5aedab9144531a4668dc7526e3caf514e1cristy register ssize_t 16172fc10e5aedab9144531a4668dc7526e3caf514e1cristy y; 16182fc10e5aedab9144531a4668dc7526e3caf514e1cristy 16192fc10e5aedab9144531a4668dc7526e3caf514e1cristy ChannelStatistics 16202fc10e5aedab9144531a4668dc7526e3caf514e1cristy pixel; 16212fc10e5aedab9144531a4668dc7526e3caf514e1cristy 16222fc10e5aedab9144531a4668dc7526e3caf514e1cristy (void) ResetMagickMemory(&pixel,0,sizeof(pixel)); 16232fc10e5aedab9144531a4668dc7526e3caf514e1cristy for (y=0; y < (ssize_t) number_grays; y++) 16242fc10e5aedab9144531a4668dc7526e3caf514e1cristy { 16252fc10e5aedab9144531a4668dc7526e3caf514e1cristy register ssize_t 16262fc10e5aedab9144531a4668dc7526e3caf514e1cristy x; 16272fc10e5aedab9144531a4668dc7526e3caf514e1cristy 16282fc10e5aedab9144531a4668dc7526e3caf514e1cristy for (x=0; x < (ssize_t) number_grays; x++) 16292fc10e5aedab9144531a4668dc7526e3caf514e1cristy { 16302fc10e5aedab9144531a4668dc7526e3caf514e1cristy /* 16312fc10e5aedab9144531a4668dc7526e3caf514e1cristy Contrast: amount of local variations present in an image. 16322fc10e5aedab9144531a4668dc7526e3caf514e1cristy */ 16332fc10e5aedab9144531a4668dc7526e3caf514e1cristy if (((y-x) == z) || ((x-y) == z)) 16342fc10e5aedab9144531a4668dc7526e3caf514e1cristy { 16352fc10e5aedab9144531a4668dc7526e3caf514e1cristy pixel.direction[i].red+=cooccurrence[x][y].direction[i].red; 16362fc10e5aedab9144531a4668dc7526e3caf514e1cristy pixel.direction[i].green+=cooccurrence[x][y].direction[i].green; 16372fc10e5aedab9144531a4668dc7526e3caf514e1cristy pixel.direction[i].blue+=cooccurrence[x][y].direction[i].blue; 16382fc10e5aedab9144531a4668dc7526e3caf514e1cristy if (image->colorspace == CMYKColorspace) 16392fc10e5aedab9144531a4668dc7526e3caf514e1cristy pixel.direction[i].black+=cooccurrence[x][y].direction[i].black; 164017f11b056210f082a6d0e54ac5d68e6d72fa76b2cristy if (image->alpha_trait != UndefinedPixelTrait) 16412fc10e5aedab9144531a4668dc7526e3caf514e1cristy pixel.direction[i].alpha+= 16422fc10e5aedab9144531a4668dc7526e3caf514e1cristy cooccurrence[x][y].direction[i].alpha; 16432fc10e5aedab9144531a4668dc7526e3caf514e1cristy } 16442fc10e5aedab9144531a4668dc7526e3caf514e1cristy /* 16452fc10e5aedab9144531a4668dc7526e3caf514e1cristy Maximum Correlation Coefficient. 16462fc10e5aedab9144531a4668dc7526e3caf514e1cristy */ 16472fc10e5aedab9144531a4668dc7526e3caf514e1cristy Q[z][y].direction[i].red+=cooccurrence[z][x].direction[i].red* 16482fc10e5aedab9144531a4668dc7526e3caf514e1cristy cooccurrence[y][x].direction[i].red/density_x[z].direction[i].red/ 16492fc10e5aedab9144531a4668dc7526e3caf514e1cristy density_y[x].direction[i].red; 16502fc10e5aedab9144531a4668dc7526e3caf514e1cristy Q[z][y].direction[i].green+=cooccurrence[z][x].direction[i].green* 16512fc10e5aedab9144531a4668dc7526e3caf514e1cristy cooccurrence[y][x].direction[i].green/ 16522fc10e5aedab9144531a4668dc7526e3caf514e1cristy density_x[z].direction[i].green/density_y[x].direction[i].red; 16532fc10e5aedab9144531a4668dc7526e3caf514e1cristy Q[z][y].direction[i].blue+=cooccurrence[z][x].direction[i].blue* 16542fc10e5aedab9144531a4668dc7526e3caf514e1cristy cooccurrence[y][x].direction[i].blue/density_x[z].direction[i].blue/ 16552fc10e5aedab9144531a4668dc7526e3caf514e1cristy density_y[x].direction[i].blue; 16562fc10e5aedab9144531a4668dc7526e3caf514e1cristy if (image->colorspace == CMYKColorspace) 16572fc10e5aedab9144531a4668dc7526e3caf514e1cristy Q[z][y].direction[i].black+=cooccurrence[z][x].direction[i].black* 16582fc10e5aedab9144531a4668dc7526e3caf514e1cristy cooccurrence[y][x].direction[i].black/ 16592fc10e5aedab9144531a4668dc7526e3caf514e1cristy density_x[z].direction[i].black/density_y[x].direction[i].black; 166017f11b056210f082a6d0e54ac5d68e6d72fa76b2cristy if (image->alpha_trait != UndefinedPixelTrait) 16612fc10e5aedab9144531a4668dc7526e3caf514e1cristy Q[z][y].direction[i].alpha+= 16622fc10e5aedab9144531a4668dc7526e3caf514e1cristy cooccurrence[z][x].direction[i].alpha* 16632fc10e5aedab9144531a4668dc7526e3caf514e1cristy cooccurrence[y][x].direction[i].alpha/ 16642fc10e5aedab9144531a4668dc7526e3caf514e1cristy density_x[z].direction[i].alpha/ 16652fc10e5aedab9144531a4668dc7526e3caf514e1cristy density_y[x].direction[i].alpha; 16662fc10e5aedab9144531a4668dc7526e3caf514e1cristy } 16672fc10e5aedab9144531a4668dc7526e3caf514e1cristy } 16682fc10e5aedab9144531a4668dc7526e3caf514e1cristy channel_features[RedPixelChannel].contrast[i]+=z*z* 16692fc10e5aedab9144531a4668dc7526e3caf514e1cristy pixel.direction[i].red; 16702fc10e5aedab9144531a4668dc7526e3caf514e1cristy channel_features[GreenPixelChannel].contrast[i]+=z*z* 16712fc10e5aedab9144531a4668dc7526e3caf514e1cristy pixel.direction[i].green; 16722fc10e5aedab9144531a4668dc7526e3caf514e1cristy channel_features[BluePixelChannel].contrast[i]+=z*z* 16732fc10e5aedab9144531a4668dc7526e3caf514e1cristy pixel.direction[i].blue; 16742fc10e5aedab9144531a4668dc7526e3caf514e1cristy if (image->colorspace == CMYKColorspace) 16752fc10e5aedab9144531a4668dc7526e3caf514e1cristy channel_features[BlackPixelChannel].contrast[i]+=z*z* 16762fc10e5aedab9144531a4668dc7526e3caf514e1cristy pixel.direction[i].black; 167717f11b056210f082a6d0e54ac5d68e6d72fa76b2cristy if (image->alpha_trait != UndefinedPixelTrait) 16782fc10e5aedab9144531a4668dc7526e3caf514e1cristy channel_features[AlphaPixelChannel].contrast[i]+=z*z* 16792fc10e5aedab9144531a4668dc7526e3caf514e1cristy pixel.direction[i].alpha; 16802fc10e5aedab9144531a4668dc7526e3caf514e1cristy } 16812fc10e5aedab9144531a4668dc7526e3caf514e1cristy /* 16822fc10e5aedab9144531a4668dc7526e3caf514e1cristy Maximum Correlation Coefficient. 16832fc10e5aedab9144531a4668dc7526e3caf514e1cristy Future: return second largest eigenvalue of Q. 16842fc10e5aedab9144531a4668dc7526e3caf514e1cristy */ 16852fc10e5aedab9144531a4668dc7526e3caf514e1cristy channel_features[RedPixelChannel].maximum_correlation_coefficient[i]= 16862fc10e5aedab9144531a4668dc7526e3caf514e1cristy sqrt((double) -1.0); 16872fc10e5aedab9144531a4668dc7526e3caf514e1cristy channel_features[GreenPixelChannel].maximum_correlation_coefficient[i]= 16882fc10e5aedab9144531a4668dc7526e3caf514e1cristy sqrt((double) -1.0); 16892fc10e5aedab9144531a4668dc7526e3caf514e1cristy channel_features[BluePixelChannel].maximum_correlation_coefficient[i]= 16902fc10e5aedab9144531a4668dc7526e3caf514e1cristy sqrt((double) -1.0); 16912fc10e5aedab9144531a4668dc7526e3caf514e1cristy if (image->colorspace == CMYKColorspace) 16922fc10e5aedab9144531a4668dc7526e3caf514e1cristy channel_features[BlackPixelChannel].maximum_correlation_coefficient[i]= 16932fc10e5aedab9144531a4668dc7526e3caf514e1cristy sqrt((double) -1.0); 169417f11b056210f082a6d0e54ac5d68e6d72fa76b2cristy if (image->alpha_trait != UndefinedPixelTrait) 16952fc10e5aedab9144531a4668dc7526e3caf514e1cristy channel_features[AlphaPixelChannel].maximum_correlation_coefficient[i]= 16962fc10e5aedab9144531a4668dc7526e3caf514e1cristy sqrt((double) -1.0); 16972fc10e5aedab9144531a4668dc7526e3caf514e1cristy } 16982fc10e5aedab9144531a4668dc7526e3caf514e1cristy /* 16992fc10e5aedab9144531a4668dc7526e3caf514e1cristy Relinquish resources. 17002fc10e5aedab9144531a4668dc7526e3caf514e1cristy */ 17012fc10e5aedab9144531a4668dc7526e3caf514e1cristy sum=(ChannelStatistics *) RelinquishMagickMemory(sum); 17022fc10e5aedab9144531a4668dc7526e3caf514e1cristy for (i=0; i < (ssize_t) number_grays; i++) 17032fc10e5aedab9144531a4668dc7526e3caf514e1cristy Q[i]=(ChannelStatistics *) RelinquishMagickMemory(Q[i]); 17042fc10e5aedab9144531a4668dc7526e3caf514e1cristy Q=(ChannelStatistics **) RelinquishMagickMemory(Q); 17052fc10e5aedab9144531a4668dc7526e3caf514e1cristy density_y=(ChannelStatistics *) RelinquishMagickMemory(density_y); 17062fc10e5aedab9144531a4668dc7526e3caf514e1cristy density_xy=(ChannelStatistics *) RelinquishMagickMemory(density_xy); 17072fc10e5aedab9144531a4668dc7526e3caf514e1cristy density_x=(ChannelStatistics *) RelinquishMagickMemory(density_x); 17082fc10e5aedab9144531a4668dc7526e3caf514e1cristy for (i=0; i < (ssize_t) number_grays; i++) 17092fc10e5aedab9144531a4668dc7526e3caf514e1cristy cooccurrence[i]=(ChannelStatistics *) 17102fc10e5aedab9144531a4668dc7526e3caf514e1cristy RelinquishMagickMemory(cooccurrence[i]); 17112fc10e5aedab9144531a4668dc7526e3caf514e1cristy cooccurrence=(ChannelStatistics **) RelinquishMagickMemory(cooccurrence); 17122fc10e5aedab9144531a4668dc7526e3caf514e1cristy return(channel_features); 17132fc10e5aedab9144531a4668dc7526e3caf514e1cristy} 17142fc10e5aedab9144531a4668dc7526e3caf514e1cristy 17152fc10e5aedab9144531a4668dc7526e3caf514e1cristy/* 17162fc10e5aedab9144531a4668dc7526e3caf514e1cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 17172fc10e5aedab9144531a4668dc7526e3caf514e1cristy% % 17182fc10e5aedab9144531a4668dc7526e3caf514e1cristy% % 17192fc10e5aedab9144531a4668dc7526e3caf514e1cristy% % 17202fc10e5aedab9144531a4668dc7526e3caf514e1cristy% H o u g h L i n e I m a g e % 17212fc10e5aedab9144531a4668dc7526e3caf514e1cristy% % 17222fc10e5aedab9144531a4668dc7526e3caf514e1cristy% % 17232fc10e5aedab9144531a4668dc7526e3caf514e1cristy% % 17242fc10e5aedab9144531a4668dc7526e3caf514e1cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 17252fc10e5aedab9144531a4668dc7526e3caf514e1cristy% 1726ec9a82a7d6938f4ff9993500e150cac3628c0e4bcristy% Use HoughLineImage() in conjunction with any binary edge extracted image (we 1727ec9a82a7d6938f4ff9993500e150cac3628c0e4bcristy% recommand Canny) to identify lines in the image. The algorithm accumulates 1728ec9a82a7d6938f4ff9993500e150cac3628c0e4bcristy% counts for every white pixel for every possible orientation (for angles from 1729ec9a82a7d6938f4ff9993500e150cac3628c0e4bcristy% 0 to 179 in 1 degree increments) and distance from the center of the image to 1730ec9a82a7d6938f4ff9993500e150cac3628c0e4bcristy% the corner (in 1 px increments) and stores the counts in an accumulator matrix 1731ec9a82a7d6938f4ff9993500e150cac3628c0e4bcristy% of angle vs distance. The size of the accumulator is 180x(diagonal/2). Next 1732ec9a82a7d6938f4ff9993500e150cac3628c0e4bcristy% it searches this space for peaks in counts and converts the locations of the 1733ec9a82a7d6938f4ff9993500e150cac3628c0e4bcristy% peaks to slope and intercept in the normal x,y input image space. Use the 1734ec9a82a7d6938f4ff9993500e150cac3628c0e4bcristy% slope/intercepts to find the endpoints clipped to the bounds of the image. The 1735ec9a82a7d6938f4ff9993500e150cac3628c0e4bcristy% lines are then drawn. The counts are a measure of the length of the lines 17362fc10e5aedab9144531a4668dc7526e3caf514e1cristy% 17372fc10e5aedab9144531a4668dc7526e3caf514e1cristy% The format of the HoughLineImage method is: 17382fc10e5aedab9144531a4668dc7526e3caf514e1cristy% 17392fc10e5aedab9144531a4668dc7526e3caf514e1cristy% Image *HoughLineImage(const Image *image,const size_t width, 17402fc10e5aedab9144531a4668dc7526e3caf514e1cristy% const size_t height,const size_t threshold,ExceptionInfo *exception) 17412fc10e5aedab9144531a4668dc7526e3caf514e1cristy% 17422fc10e5aedab9144531a4668dc7526e3caf514e1cristy% A description of each parameter follows: 17432fc10e5aedab9144531a4668dc7526e3caf514e1cristy% 17442fc10e5aedab9144531a4668dc7526e3caf514e1cristy% o image: the image. 17452fc10e5aedab9144531a4668dc7526e3caf514e1cristy% 17462fc10e5aedab9144531a4668dc7526e3caf514e1cristy% o width, height: find line pairs as local maxima in this neighborhood. 17472fc10e5aedab9144531a4668dc7526e3caf514e1cristy% 17482fc10e5aedab9144531a4668dc7526e3caf514e1cristy% o threshold: the line count threshold. 17492fc10e5aedab9144531a4668dc7526e3caf514e1cristy% 17502fc10e5aedab9144531a4668dc7526e3caf514e1cristy% o exception: return any errors or warnings in this structure. 17512fc10e5aedab9144531a4668dc7526e3caf514e1cristy% 17522fc10e5aedab9144531a4668dc7526e3caf514e1cristy*/ 17532fc10e5aedab9144531a4668dc7526e3caf514e1cristy 17542fc10e5aedab9144531a4668dc7526e3caf514e1cristystatic inline double MagickRound(double x) 17552fc10e5aedab9144531a4668dc7526e3caf514e1cristy{ 17562fc10e5aedab9144531a4668dc7526e3caf514e1cristy /* 17572fc10e5aedab9144531a4668dc7526e3caf514e1cristy Round the fraction to nearest integer. 17582fc10e5aedab9144531a4668dc7526e3caf514e1cristy */ 17592fc10e5aedab9144531a4668dc7526e3caf514e1cristy if ((x-floor(x)) < (ceil(x)-x)) 17602fc10e5aedab9144531a4668dc7526e3caf514e1cristy return(floor(x)); 17612fc10e5aedab9144531a4668dc7526e3caf514e1cristy return(ceil(x)); 17622fc10e5aedab9144531a4668dc7526e3caf514e1cristy} 17632fc10e5aedab9144531a4668dc7526e3caf514e1cristy 17642fc10e5aedab9144531a4668dc7526e3caf514e1cristyMagickExport Image *HoughLineImage(const Image *image,const size_t width, 17652fc10e5aedab9144531a4668dc7526e3caf514e1cristy const size_t height,const size_t threshold,ExceptionInfo *exception) 17662fc10e5aedab9144531a4668dc7526e3caf514e1cristy{ 17678fbcf1ad6a1d07a92ef39435f679143697be4edacristy#define HoughLineImageTag "HoughLine/Image" 17688fbcf1ad6a1d07a92ef39435f679143697be4edacristy 17692fc10e5aedab9144531a4668dc7526e3caf514e1cristy CacheView 17702fc10e5aedab9144531a4668dc7526e3caf514e1cristy *image_view; 17712fc10e5aedab9144531a4668dc7526e3caf514e1cristy 17722fc10e5aedab9144531a4668dc7526e3caf514e1cristy char 1773151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy message[MagickPathExtent], 1774151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy path[MagickPathExtent]; 17752fc10e5aedab9144531a4668dc7526e3caf514e1cristy 17762fc10e5aedab9144531a4668dc7526e3caf514e1cristy const char 17772fc10e5aedab9144531a4668dc7526e3caf514e1cristy *artifact; 17782fc10e5aedab9144531a4668dc7526e3caf514e1cristy 17792fc10e5aedab9144531a4668dc7526e3caf514e1cristy double 17802fc10e5aedab9144531a4668dc7526e3caf514e1cristy hough_height; 17812fc10e5aedab9144531a4668dc7526e3caf514e1cristy 17822fc10e5aedab9144531a4668dc7526e3caf514e1cristy Image 17832fc10e5aedab9144531a4668dc7526e3caf514e1cristy *lines_image = NULL; 17842fc10e5aedab9144531a4668dc7526e3caf514e1cristy 17852fc10e5aedab9144531a4668dc7526e3caf514e1cristy ImageInfo 17862fc10e5aedab9144531a4668dc7526e3caf514e1cristy *image_info; 17872fc10e5aedab9144531a4668dc7526e3caf514e1cristy 17882fc10e5aedab9144531a4668dc7526e3caf514e1cristy int 17892fc10e5aedab9144531a4668dc7526e3caf514e1cristy file; 17902fc10e5aedab9144531a4668dc7526e3caf514e1cristy 17912fc10e5aedab9144531a4668dc7526e3caf514e1cristy MagickBooleanType 17922fc10e5aedab9144531a4668dc7526e3caf514e1cristy status; 17932fc10e5aedab9144531a4668dc7526e3caf514e1cristy 17948fbcf1ad6a1d07a92ef39435f679143697be4edacristy MagickOffsetType 17958fbcf1ad6a1d07a92ef39435f679143697be4edacristy progress; 17968fbcf1ad6a1d07a92ef39435f679143697be4edacristy 17972fc10e5aedab9144531a4668dc7526e3caf514e1cristy MatrixInfo 17982fc10e5aedab9144531a4668dc7526e3caf514e1cristy *accumulator; 17992fc10e5aedab9144531a4668dc7526e3caf514e1cristy 18002fc10e5aedab9144531a4668dc7526e3caf514e1cristy PointInfo 18012fc10e5aedab9144531a4668dc7526e3caf514e1cristy center; 18022fc10e5aedab9144531a4668dc7526e3caf514e1cristy 18032fc10e5aedab9144531a4668dc7526e3caf514e1cristy register ssize_t 18042fc10e5aedab9144531a4668dc7526e3caf514e1cristy y; 18052fc10e5aedab9144531a4668dc7526e3caf514e1cristy 18062fc10e5aedab9144531a4668dc7526e3caf514e1cristy size_t 18072fc10e5aedab9144531a4668dc7526e3caf514e1cristy accumulator_height, 18082fc10e5aedab9144531a4668dc7526e3caf514e1cristy accumulator_width, 18092fc10e5aedab9144531a4668dc7526e3caf514e1cristy line_count; 18102fc10e5aedab9144531a4668dc7526e3caf514e1cristy 18112fc10e5aedab9144531a4668dc7526e3caf514e1cristy /* 18122fc10e5aedab9144531a4668dc7526e3caf514e1cristy Create the accumulator. 18132fc10e5aedab9144531a4668dc7526e3caf514e1cristy */ 18142fc10e5aedab9144531a4668dc7526e3caf514e1cristy assert(image != (const Image *) NULL); 1815e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy assert(image->signature == MagickCoreSignature); 18162fc10e5aedab9144531a4668dc7526e3caf514e1cristy if (image->debug != MagickFalse) 18172fc10e5aedab9144531a4668dc7526e3caf514e1cristy (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 18182fc10e5aedab9144531a4668dc7526e3caf514e1cristy assert(exception != (ExceptionInfo *) NULL); 1819e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy assert(exception->signature == MagickCoreSignature); 18202fc10e5aedab9144531a4668dc7526e3caf514e1cristy accumulator_width=180; 18212fc10e5aedab9144531a4668dc7526e3caf514e1cristy hough_height=((sqrt(2.0)*(double) (image->rows > image->columns ? 18222fc10e5aedab9144531a4668dc7526e3caf514e1cristy image->rows : image->columns))/2.0); 18232fc10e5aedab9144531a4668dc7526e3caf514e1cristy accumulator_height=(size_t) (2.0*hough_height); 18242fc10e5aedab9144531a4668dc7526e3caf514e1cristy accumulator=AcquireMatrixInfo(accumulator_width,accumulator_height, 18252fc10e5aedab9144531a4668dc7526e3caf514e1cristy sizeof(double),exception); 18262fc10e5aedab9144531a4668dc7526e3caf514e1cristy if (accumulator == (MatrixInfo *) NULL) 18272fc10e5aedab9144531a4668dc7526e3caf514e1cristy ThrowImageException(ResourceLimitError,"MemoryAllocationFailed"); 18282fc10e5aedab9144531a4668dc7526e3caf514e1cristy if (NullMatrix(accumulator) == MagickFalse) 18292fc10e5aedab9144531a4668dc7526e3caf514e1cristy { 18302fc10e5aedab9144531a4668dc7526e3caf514e1cristy accumulator=DestroyMatrixInfo(accumulator); 18312fc10e5aedab9144531a4668dc7526e3caf514e1cristy ThrowImageException(ResourceLimitError,"MemoryAllocationFailed"); 18322fc10e5aedab9144531a4668dc7526e3caf514e1cristy } 18332fc10e5aedab9144531a4668dc7526e3caf514e1cristy /* 18342fc10e5aedab9144531a4668dc7526e3caf514e1cristy Populate the accumulator. 18352fc10e5aedab9144531a4668dc7526e3caf514e1cristy */ 18362fc10e5aedab9144531a4668dc7526e3caf514e1cristy status=MagickTrue; 18378fbcf1ad6a1d07a92ef39435f679143697be4edacristy progress=0; 18382fc10e5aedab9144531a4668dc7526e3caf514e1cristy center.x=(double) image->columns/2.0; 18392fc10e5aedab9144531a4668dc7526e3caf514e1cristy center.y=(double) image->rows/2.0; 18402fc10e5aedab9144531a4668dc7526e3caf514e1cristy image_view=AcquireVirtualCacheView(image,exception); 18412fc10e5aedab9144531a4668dc7526e3caf514e1cristy for (y=0; y < (ssize_t) image->rows; y++) 18422fc10e5aedab9144531a4668dc7526e3caf514e1cristy { 18432fc10e5aedab9144531a4668dc7526e3caf514e1cristy register const Quantum 184405d2ff7ebf21f659f5b11e45afb294e152f4330cdirk *magick_restrict p; 18452fc10e5aedab9144531a4668dc7526e3caf514e1cristy 18462fc10e5aedab9144531a4668dc7526e3caf514e1cristy register ssize_t 18472fc10e5aedab9144531a4668dc7526e3caf514e1cristy x; 18482fc10e5aedab9144531a4668dc7526e3caf514e1cristy 18492fc10e5aedab9144531a4668dc7526e3caf514e1cristy if (status == MagickFalse) 18502fc10e5aedab9144531a4668dc7526e3caf514e1cristy continue; 18512fc10e5aedab9144531a4668dc7526e3caf514e1cristy p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception); 18522fc10e5aedab9144531a4668dc7526e3caf514e1cristy if (p == (Quantum *) NULL) 18532fc10e5aedab9144531a4668dc7526e3caf514e1cristy { 18542fc10e5aedab9144531a4668dc7526e3caf514e1cristy status=MagickFalse; 18552fc10e5aedab9144531a4668dc7526e3caf514e1cristy continue; 18562fc10e5aedab9144531a4668dc7526e3caf514e1cristy } 18572fc10e5aedab9144531a4668dc7526e3caf514e1cristy for (x=0; x < (ssize_t) image->columns; x++) 18582fc10e5aedab9144531a4668dc7526e3caf514e1cristy { 18592e03529bdd5a322e00e9b1d4655181c6f09ca768cristy if (GetPixelIntensity(image,p) > (QuantumRange/2.0)) 18602fc10e5aedab9144531a4668dc7526e3caf514e1cristy { 18612fc10e5aedab9144531a4668dc7526e3caf514e1cristy register ssize_t 18622fc10e5aedab9144531a4668dc7526e3caf514e1cristy i; 18632fc10e5aedab9144531a4668dc7526e3caf514e1cristy 18642fc10e5aedab9144531a4668dc7526e3caf514e1cristy for (i=0; i < 180; i++) 18652fc10e5aedab9144531a4668dc7526e3caf514e1cristy { 18662fc10e5aedab9144531a4668dc7526e3caf514e1cristy double 18672fc10e5aedab9144531a4668dc7526e3caf514e1cristy count, 18682fc10e5aedab9144531a4668dc7526e3caf514e1cristy radius; 18692fc10e5aedab9144531a4668dc7526e3caf514e1cristy 18702fc10e5aedab9144531a4668dc7526e3caf514e1cristy radius=(((double) x-center.x)*cos(DegreesToRadians((double) i)))+ 18712fc10e5aedab9144531a4668dc7526e3caf514e1cristy (((double) y-center.y)*sin(DegreesToRadians((double) i))); 18722fc10e5aedab9144531a4668dc7526e3caf514e1cristy (void) GetMatrixElement(accumulator,i,(ssize_t) 18732fc10e5aedab9144531a4668dc7526e3caf514e1cristy MagickRound(radius+hough_height),&count); 18742fc10e5aedab9144531a4668dc7526e3caf514e1cristy count++; 18752fc10e5aedab9144531a4668dc7526e3caf514e1cristy (void) SetMatrixElement(accumulator,i,(ssize_t) 18762fc10e5aedab9144531a4668dc7526e3caf514e1cristy MagickRound(radius+hough_height),&count); 18772fc10e5aedab9144531a4668dc7526e3caf514e1cristy } 18782fc10e5aedab9144531a4668dc7526e3caf514e1cristy } 18792fc10e5aedab9144531a4668dc7526e3caf514e1cristy p+=GetPixelChannels(image); 18802fc10e5aedab9144531a4668dc7526e3caf514e1cristy } 18818fbcf1ad6a1d07a92ef39435f679143697be4edacristy if (image->progress_monitor != (MagickProgressMonitor) NULL) 18828fbcf1ad6a1d07a92ef39435f679143697be4edacristy { 18838fbcf1ad6a1d07a92ef39435f679143697be4edacristy MagickBooleanType 18848fbcf1ad6a1d07a92ef39435f679143697be4edacristy proceed; 18858fbcf1ad6a1d07a92ef39435f679143697be4edacristy 18868fbcf1ad6a1d07a92ef39435f679143697be4edacristy#if defined(MAGICKCORE_OPENMP_SUPPORT) 18878fbcf1ad6a1d07a92ef39435f679143697be4edacristy #pragma omp critical (MagickCore_CannyEdgeImage) 18888fbcf1ad6a1d07a92ef39435f679143697be4edacristy#endif 18898fbcf1ad6a1d07a92ef39435f679143697be4edacristy proceed=SetImageProgress(image,CannyEdgeImageTag,progress++, 18908fbcf1ad6a1d07a92ef39435f679143697be4edacristy image->rows); 18918fbcf1ad6a1d07a92ef39435f679143697be4edacristy if (proceed == MagickFalse) 18928fbcf1ad6a1d07a92ef39435f679143697be4edacristy status=MagickFalse; 18938fbcf1ad6a1d07a92ef39435f679143697be4edacristy } 18942fc10e5aedab9144531a4668dc7526e3caf514e1cristy } 18952fc10e5aedab9144531a4668dc7526e3caf514e1cristy image_view=DestroyCacheView(image_view); 18962fc10e5aedab9144531a4668dc7526e3caf514e1cristy if (status == MagickFalse) 18972fc10e5aedab9144531a4668dc7526e3caf514e1cristy { 18982fc10e5aedab9144531a4668dc7526e3caf514e1cristy accumulator=DestroyMatrixInfo(accumulator); 18992fc10e5aedab9144531a4668dc7526e3caf514e1cristy return((Image *) NULL); 19002fc10e5aedab9144531a4668dc7526e3caf514e1cristy } 19012fc10e5aedab9144531a4668dc7526e3caf514e1cristy /* 19022fc10e5aedab9144531a4668dc7526e3caf514e1cristy Generate line segments from accumulator. 1903e18977973bff5866de9aa6ed097aea40e27570d6cristy */ 19042fc10e5aedab9144531a4668dc7526e3caf514e1cristy file=AcquireUniqueFileResource(path); 19052fc10e5aedab9144531a4668dc7526e3caf514e1cristy if (file == -1) 19062fc10e5aedab9144531a4668dc7526e3caf514e1cristy { 19072fc10e5aedab9144531a4668dc7526e3caf514e1cristy accumulator=DestroyMatrixInfo(accumulator); 19082fc10e5aedab9144531a4668dc7526e3caf514e1cristy return((Image *) NULL); 19092fc10e5aedab9144531a4668dc7526e3caf514e1cristy } 1910151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy (void) FormatLocaleString(message,MagickPathExtent, 19112fc10e5aedab9144531a4668dc7526e3caf514e1cristy "# Hough line transform: %.20gx%.20g%+.20g\n",(double) width, 19122fc10e5aedab9144531a4668dc7526e3caf514e1cristy (double) height,(double) threshold); 191396498423d48af3032b4ad554b12e347e0231eb45cristy if (write(file,message,strlen(message)) != (ssize_t) strlen(message)) 1914233483c36e4f75e4337766b87cae1ab13d8b92a8cristy status=MagickFalse; 1915151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy (void) FormatLocaleString(message,MagickPathExtent,"viewbox 0 0 %.20g %.20g\n", 19162fc10e5aedab9144531a4668dc7526e3caf514e1cristy (double) image->columns,(double) image->rows); 191796498423d48af3032b4ad554b12e347e0231eb45cristy if (write(file,message,strlen(message)) != (ssize_t) strlen(message)) 1918233483c36e4f75e4337766b87cae1ab13d8b92a8cristy status=MagickFalse; 19192fc10e5aedab9144531a4668dc7526e3caf514e1cristy line_count=image->columns > image->rows ? image->columns/4 : image->rows/4; 19202fc10e5aedab9144531a4668dc7526e3caf514e1cristy if (threshold != 0) 19212fc10e5aedab9144531a4668dc7526e3caf514e1cristy line_count=threshold; 19222fc10e5aedab9144531a4668dc7526e3caf514e1cristy for (y=0; y < (ssize_t) accumulator_height; y++) 19233a82f25dfc8e47ea3049f3a474a8c79ebc268926cristy { 19242fc10e5aedab9144531a4668dc7526e3caf514e1cristy register ssize_t 19252fc10e5aedab9144531a4668dc7526e3caf514e1cristy x; 1926564a56979706a30a3d0f920fd5f538a408efd4f1cristy 19272fc10e5aedab9144531a4668dc7526e3caf514e1cristy for (x=0; x < (ssize_t) accumulator_width; x++) 19283a82f25dfc8e47ea3049f3a474a8c79ebc268926cristy { 19292fc10e5aedab9144531a4668dc7526e3caf514e1cristy double 19302fc10e5aedab9144531a4668dc7526e3caf514e1cristy count; 19313a82f25dfc8e47ea3049f3a474a8c79ebc268926cristy 19322fc10e5aedab9144531a4668dc7526e3caf514e1cristy (void) GetMatrixElement(accumulator,x,y,&count); 19332fc10e5aedab9144531a4668dc7526e3caf514e1cristy if (count >= (double) line_count) 19342fc10e5aedab9144531a4668dc7526e3caf514e1cristy { 19352fc10e5aedab9144531a4668dc7526e3caf514e1cristy double 19362fc10e5aedab9144531a4668dc7526e3caf514e1cristy maxima; 1937bd82207b3816471fba4de916fca7336f38b70493cristy 19382fc10e5aedab9144531a4668dc7526e3caf514e1cristy SegmentInfo 19392fc10e5aedab9144531a4668dc7526e3caf514e1cristy line; 19402fc10e5aedab9144531a4668dc7526e3caf514e1cristy 19412fc10e5aedab9144531a4668dc7526e3caf514e1cristy ssize_t 19422fc10e5aedab9144531a4668dc7526e3caf514e1cristy v; 1943bd82207b3816471fba4de916fca7336f38b70493cristy 19443a82f25dfc8e47ea3049f3a474a8c79ebc268926cristy /* 19452fc10e5aedab9144531a4668dc7526e3caf514e1cristy Is point a local maxima? 19463a82f25dfc8e47ea3049f3a474a8c79ebc268926cristy */ 19472fc10e5aedab9144531a4668dc7526e3caf514e1cristy maxima=count; 19482494e3d5cea70ebef8e12498b10bc2e24da4803fcristy for (v=(-((ssize_t) height/2)); v <= (((ssize_t) height/2)); v++) 19492fc10e5aedab9144531a4668dc7526e3caf514e1cristy { 19502fc10e5aedab9144531a4668dc7526e3caf514e1cristy ssize_t 19512fc10e5aedab9144531a4668dc7526e3caf514e1cristy u; 19522fc10e5aedab9144531a4668dc7526e3caf514e1cristy 19532494e3d5cea70ebef8e12498b10bc2e24da4803fcristy for (u=(-((ssize_t) width/2)); u <= (((ssize_t) width/2)); u++) 19543a82f25dfc8e47ea3049f3a474a8c79ebc268926cristy { 19552fc10e5aedab9144531a4668dc7526e3caf514e1cristy if ((u != 0) || (v !=0)) 19562fc10e5aedab9144531a4668dc7526e3caf514e1cristy { 19572fc10e5aedab9144531a4668dc7526e3caf514e1cristy (void) GetMatrixElement(accumulator,x+u,y+v,&count); 19582fc10e5aedab9144531a4668dc7526e3caf514e1cristy if (count > maxima) 19592fc10e5aedab9144531a4668dc7526e3caf514e1cristy { 19602fc10e5aedab9144531a4668dc7526e3caf514e1cristy maxima=count; 19612fc10e5aedab9144531a4668dc7526e3caf514e1cristy break; 19622fc10e5aedab9144531a4668dc7526e3caf514e1cristy } 19632fc10e5aedab9144531a4668dc7526e3caf514e1cristy } 19643a82f25dfc8e47ea3049f3a474a8c79ebc268926cristy } 19652fc10e5aedab9144531a4668dc7526e3caf514e1cristy if (u < (ssize_t) (width/2)) 19662fc10e5aedab9144531a4668dc7526e3caf514e1cristy break; 19672fc10e5aedab9144531a4668dc7526e3caf514e1cristy } 19682fc10e5aedab9144531a4668dc7526e3caf514e1cristy (void) GetMatrixElement(accumulator,x,y,&count); 19692fc10e5aedab9144531a4668dc7526e3caf514e1cristy if (maxima > count) 19702fc10e5aedab9144531a4668dc7526e3caf514e1cristy continue; 19712fc10e5aedab9144531a4668dc7526e3caf514e1cristy if ((x >= 45) && (x <= 135)) 19722fc10e5aedab9144531a4668dc7526e3caf514e1cristy { 19732fc10e5aedab9144531a4668dc7526e3caf514e1cristy /* 19742fc10e5aedab9144531a4668dc7526e3caf514e1cristy y = (r-x cos(t))/sin(t) 19752fc10e5aedab9144531a4668dc7526e3caf514e1cristy */ 19762fc10e5aedab9144531a4668dc7526e3caf514e1cristy line.x1=0.0; 19772fc10e5aedab9144531a4668dc7526e3caf514e1cristy line.y1=((double) (y-(accumulator_height/2.0))-((line.x1- 19782fc10e5aedab9144531a4668dc7526e3caf514e1cristy (image->columns/2.0))*cos(DegreesToRadians((double) x))))/ 19792fc10e5aedab9144531a4668dc7526e3caf514e1cristy sin(DegreesToRadians((double) x))+(image->rows/2.0); 19802fc10e5aedab9144531a4668dc7526e3caf514e1cristy line.x2=(double) image->columns; 19812fc10e5aedab9144531a4668dc7526e3caf514e1cristy line.y2=((double) (y-(accumulator_height/2.0))-((line.x2- 19822fc10e5aedab9144531a4668dc7526e3caf514e1cristy (image->columns/2.0))*cos(DegreesToRadians((double) x))))/ 19832fc10e5aedab9144531a4668dc7526e3caf514e1cristy sin(DegreesToRadians((double) x))+(image->rows/2.0); 19842fc10e5aedab9144531a4668dc7526e3caf514e1cristy } 19852fc10e5aedab9144531a4668dc7526e3caf514e1cristy else 19862fc10e5aedab9144531a4668dc7526e3caf514e1cristy { 19872fc10e5aedab9144531a4668dc7526e3caf514e1cristy /* 19882fc10e5aedab9144531a4668dc7526e3caf514e1cristy x = (r-y cos(t))/sin(t) 19892fc10e5aedab9144531a4668dc7526e3caf514e1cristy */ 19902fc10e5aedab9144531a4668dc7526e3caf514e1cristy line.y1=0.0; 19912fc10e5aedab9144531a4668dc7526e3caf514e1cristy line.x1=((double) (y-(accumulator_height/2.0))-((line.y1- 19922fc10e5aedab9144531a4668dc7526e3caf514e1cristy (image->rows/2.0))*sin(DegreesToRadians((double) x))))/ 19932fc10e5aedab9144531a4668dc7526e3caf514e1cristy cos(DegreesToRadians((double) x))+(image->columns/2.0); 19942fc10e5aedab9144531a4668dc7526e3caf514e1cristy line.y2=(double) image->rows; 19952fc10e5aedab9144531a4668dc7526e3caf514e1cristy line.x2=((double) (y-(accumulator_height/2.0))-((line.y2- 19962fc10e5aedab9144531a4668dc7526e3caf514e1cristy (image->rows/2.0))*sin(DegreesToRadians((double) x))))/ 19972fc10e5aedab9144531a4668dc7526e3caf514e1cristy cos(DegreesToRadians((double) x))+(image->columns/2.0); 19982fc10e5aedab9144531a4668dc7526e3caf514e1cristy } 1999151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy (void) FormatLocaleString(message,MagickPathExtent, 20002fc10e5aedab9144531a4668dc7526e3caf514e1cristy "line %g,%g %g,%g # %g\n",line.x1,line.y1,line.x2,line.y2,maxima); 200196498423d48af3032b4ad554b12e347e0231eb45cristy if (write(file,message,strlen(message)) != (ssize_t) strlen(message)) 2002233483c36e4f75e4337766b87cae1ab13d8b92a8cristy status=MagickFalse; 20033a82f25dfc8e47ea3049f3a474a8c79ebc268926cristy } 20043a82f25dfc8e47ea3049f3a474a8c79ebc268926cristy } 20053a82f25dfc8e47ea3049f3a474a8c79ebc268926cristy } 20062fc10e5aedab9144531a4668dc7526e3caf514e1cristy (void) close(file); 20077e9726d27d1b1e079b9b94b78f5ffd49352fcc91cristy /* 20082fc10e5aedab9144531a4668dc7526e3caf514e1cristy Render lines to image canvas. 2009f2bf2c76eb0f9a013d0a4dd51d4b86d3d714ddf2cristy */ 20102fc10e5aedab9144531a4668dc7526e3caf514e1cristy image_info=AcquireImageInfo(); 20112fc10e5aedab9144531a4668dc7526e3caf514e1cristy image_info->background_color=image->background_color; 2012151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy (void) FormatLocaleString(image_info->filename,MagickPathExtent,"mvg:%s",path); 20132fc10e5aedab9144531a4668dc7526e3caf514e1cristy artifact=GetImageArtifact(image,"background"); 20142fc10e5aedab9144531a4668dc7526e3caf514e1cristy if (artifact != (const char *) NULL) 20152fc10e5aedab9144531a4668dc7526e3caf514e1cristy (void) SetImageOption(image_info,"background",artifact); 20162fc10e5aedab9144531a4668dc7526e3caf514e1cristy artifact=GetImageArtifact(image,"fill"); 20172fc10e5aedab9144531a4668dc7526e3caf514e1cristy if (artifact != (const char *) NULL) 20182fc10e5aedab9144531a4668dc7526e3caf514e1cristy (void) SetImageOption(image_info,"fill",artifact); 20192fc10e5aedab9144531a4668dc7526e3caf514e1cristy artifact=GetImageArtifact(image,"stroke"); 20202fc10e5aedab9144531a4668dc7526e3caf514e1cristy if (artifact != (const char *) NULL) 20212fc10e5aedab9144531a4668dc7526e3caf514e1cristy (void) SetImageOption(image_info,"stroke",artifact); 20222fc10e5aedab9144531a4668dc7526e3caf514e1cristy artifact=GetImageArtifact(image,"strokewidth"); 20232fc10e5aedab9144531a4668dc7526e3caf514e1cristy if (artifact != (const char *) NULL) 20242fc10e5aedab9144531a4668dc7526e3caf514e1cristy (void) SetImageOption(image_info,"strokewidth",artifact); 20252fc10e5aedab9144531a4668dc7526e3caf514e1cristy lines_image=ReadImage(image_info,exception); 20262fc10e5aedab9144531a4668dc7526e3caf514e1cristy artifact=GetImageArtifact(image,"hough-lines:accumulator"); 20272fc10e5aedab9144531a4668dc7526e3caf514e1cristy if ((lines_image != (Image *) NULL) && 20282fc10e5aedab9144531a4668dc7526e3caf514e1cristy (IsStringTrue(artifact) != MagickFalse)) 20292fc10e5aedab9144531a4668dc7526e3caf514e1cristy { 20302fc10e5aedab9144531a4668dc7526e3caf514e1cristy Image 20312fc10e5aedab9144531a4668dc7526e3caf514e1cristy *accumulator_image; 20322fc10e5aedab9144531a4668dc7526e3caf514e1cristy 20332fc10e5aedab9144531a4668dc7526e3caf514e1cristy accumulator_image=MatrixToImage(accumulator,exception); 20342fc10e5aedab9144531a4668dc7526e3caf514e1cristy if (accumulator_image != (Image *) NULL) 20352fc10e5aedab9144531a4668dc7526e3caf514e1cristy AppendImageToList(&lines_image,accumulator_image); 20362fc10e5aedab9144531a4668dc7526e3caf514e1cristy } 20372fc10e5aedab9144531a4668dc7526e3caf514e1cristy /* 20382fc10e5aedab9144531a4668dc7526e3caf514e1cristy Free resources. 20392fc10e5aedab9144531a4668dc7526e3caf514e1cristy */ 20402fc10e5aedab9144531a4668dc7526e3caf514e1cristy accumulator=DestroyMatrixInfo(accumulator); 20412fc10e5aedab9144531a4668dc7526e3caf514e1cristy image_info=DestroyImageInfo(image_info); 20422fc10e5aedab9144531a4668dc7526e3caf514e1cristy (void) RelinquishUniqueFileResource(path); 20432fc10e5aedab9144531a4668dc7526e3caf514e1cristy return(GetFirstImageInList(lines_image)); 20442fc10e5aedab9144531a4668dc7526e3caf514e1cristy} 20452fc10e5aedab9144531a4668dc7526e3caf514e1cristy 20462fc10e5aedab9144531a4668dc7526e3caf514e1cristy/* 20472fc10e5aedab9144531a4668dc7526e3caf514e1cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 20482fc10e5aedab9144531a4668dc7526e3caf514e1cristy% % 20492fc10e5aedab9144531a4668dc7526e3caf514e1cristy% % 20502fc10e5aedab9144531a4668dc7526e3caf514e1cristy% % 20512fc10e5aedab9144531a4668dc7526e3caf514e1cristy% M e a n S h i f t I m a g e % 20522fc10e5aedab9144531a4668dc7526e3caf514e1cristy% % 20532fc10e5aedab9144531a4668dc7526e3caf514e1cristy% % 20542fc10e5aedab9144531a4668dc7526e3caf514e1cristy% % 20552fc10e5aedab9144531a4668dc7526e3caf514e1cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 20562fc10e5aedab9144531a4668dc7526e3caf514e1cristy% 2057c904cab8ecc6ca7aa6a24d3a0f74991d23494829cristy% MeanShiftImage() delineate arbitrarily shaped clusters in the image. For 2058c904cab8ecc6ca7aa6a24d3a0f74991d23494829cristy% each pixel, it visits all the pixels in the neighborhood specified by 2059c904cab8ecc6ca7aa6a24d3a0f74991d23494829cristy% the window centered at the pixel and excludes those that are outside the 2060c904cab8ecc6ca7aa6a24d3a0f74991d23494829cristy% radius=(window-1)/2 surrounding the pixel. From those pixels, it finds those 2061c904cab8ecc6ca7aa6a24d3a0f74991d23494829cristy% that are within the specified color distance from the current mean, and 2062c904cab8ecc6ca7aa6a24d3a0f74991d23494829cristy% computes a new x,y centroid from those coordinates and a new mean. This new 2063c904cab8ecc6ca7aa6a24d3a0f74991d23494829cristy% x,y centroid is used as the center for a new window. This process iterates 2064c904cab8ecc6ca7aa6a24d3a0f74991d23494829cristy% until it converges and the final mean is replaces the (original window 2065c904cab8ecc6ca7aa6a24d3a0f74991d23494829cristy% center) pixel value. It repeats this process for the next pixel, etc., 2066c904cab8ecc6ca7aa6a24d3a0f74991d23494829cristy% until it processes all pixels in the image. Results are typically better with 2067c904cab8ecc6ca7aa6a24d3a0f74991d23494829cristy% colorspaces other than sRGB. We recommend YIQ, YUV or YCbCr. 20682fc10e5aedab9144531a4668dc7526e3caf514e1cristy% 20692fc10e5aedab9144531a4668dc7526e3caf514e1cristy% The format of the MeanShiftImage method is: 20702fc10e5aedab9144531a4668dc7526e3caf514e1cristy% 20712fc10e5aedab9144531a4668dc7526e3caf514e1cristy% Image *MeanShiftImage(const Image *image,const size_t width, 20726aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy% const size_t height,const double color_distance, 20736aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy% ExceptionInfo *exception) 20742fc10e5aedab9144531a4668dc7526e3caf514e1cristy% 20752fc10e5aedab9144531a4668dc7526e3caf514e1cristy% A description of each parameter follows: 20762fc10e5aedab9144531a4668dc7526e3caf514e1cristy% 20772fc10e5aedab9144531a4668dc7526e3caf514e1cristy% o image: the image. 20782fc10e5aedab9144531a4668dc7526e3caf514e1cristy% 2079d70bd6ca959a16d8a10f4b2bc0988e91cbcad980cristy% o width, height: find pixels in this neighborhood. 20802fc10e5aedab9144531a4668dc7526e3caf514e1cristy% 20816aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy% o color_distance: the color distance. 20822fc10e5aedab9144531a4668dc7526e3caf514e1cristy% 20832fc10e5aedab9144531a4668dc7526e3caf514e1cristy% o exception: return any errors or warnings in this structure. 20842fc10e5aedab9144531a4668dc7526e3caf514e1cristy% 20852fc10e5aedab9144531a4668dc7526e3caf514e1cristy*/ 20862fc10e5aedab9144531a4668dc7526e3caf514e1cristyMagickExport Image *MeanShiftImage(const Image *image,const size_t width, 20876aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy const size_t height,const double color_distance,ExceptionInfo *exception) 20882fc10e5aedab9144531a4668dc7526e3caf514e1cristy{ 20896aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy#define MaxMeanShiftIterations 100 20904c8a3ecf917f56f107f2a7477fb60139d2861f3dcristy#define MeanShiftImageTag "MeanShift/Image" 20916aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy 20926aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy CacheView 20936aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy *image_view, 20946aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy *mean_view, 20956aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy *pixel_view; 20966aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy 20976aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy Image 20986aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy *mean_image; 20996aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy 21006aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy MagickBooleanType 21016aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy status; 21026aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy 21034c8a3ecf917f56f107f2a7477fb60139d2861f3dcristy MagickOffsetType 21044c8a3ecf917f56f107f2a7477fb60139d2861f3dcristy progress; 21054c8a3ecf917f56f107f2a7477fb60139d2861f3dcristy 21066aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy ssize_t 21076aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy y; 21086aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy 21096aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy assert(image != (const Image *) NULL); 2110e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy assert(image->signature == MagickCoreSignature); 21116aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy if (image->debug != MagickFalse) 21126aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 21136aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy assert(exception != (ExceptionInfo *) NULL); 2114e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy assert(exception->signature == MagickCoreSignature); 21156aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy mean_image=CloneImage(image,image->columns,image->rows,MagickTrue,exception); 21166aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy if (mean_image == (Image *) NULL) 21176aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy return((Image *) NULL); 21186aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy if (SetImageStorageClass(mean_image,DirectClass,exception) == MagickFalse) 21196aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy { 21206aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy mean_image=DestroyImage(mean_image); 21216aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy return((Image *) NULL); 21226aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy } 21236aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy status=MagickTrue; 21244c8a3ecf917f56f107f2a7477fb60139d2861f3dcristy progress=0; 21256aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy image_view=AcquireVirtualCacheView(image,exception); 21266aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy pixel_view=AcquireVirtualCacheView(image,exception); 21276aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy mean_view=AcquireAuthenticCacheView(mean_image,exception); 21286aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy#if defined(MAGICKCORE_OPENMP_SUPPORT) 21294c8a3ecf917f56f107f2a7477fb60139d2861f3dcristy #pragma omp parallel for schedule(static,4) shared(status,progress) \ 21306aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy magick_threads(mean_image,mean_image,mean_image->rows,1) 21316aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy#endif 21326aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy for (y=0; y < (ssize_t) mean_image->rows; y++) 21336aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy { 21346aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy register const Quantum 213505d2ff7ebf21f659f5b11e45afb294e152f4330cdirk *magick_restrict p; 21366aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy 21376aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy register Quantum 213805d2ff7ebf21f659f5b11e45afb294e152f4330cdirk *magick_restrict q; 21396aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy 21406aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy register ssize_t 21416aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy x; 21426aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy 21436aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy if (status == MagickFalse) 21446aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy continue; 21456aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception); 21466aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy q=GetCacheViewAuthenticPixels(mean_view,0,y,mean_image->columns,1, 21476aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy exception); 21486aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL)) 21496aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy { 21506aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy status=MagickFalse; 21516aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy continue; 21526aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy } 21536aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy for (x=0; x < (ssize_t) mean_image->columns; x++) 21546aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy { 21556aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy PixelInfo 21566aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy mean_pixel, 21576aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy previous_pixel; 21586aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy 21596aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy PointInfo 21606aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy mean_location, 21616aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy previous_location; 21626aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy 21636aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy register ssize_t 21646aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy i; 21656aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy 21666aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy GetPixelInfo(image,&mean_pixel); 21676aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy GetPixelInfoPixel(image,p,&mean_pixel); 21686aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy mean_location.x=(double) x; 21696aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy mean_location.y=(double) y; 21706aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy for (i=0; i < MaxMeanShiftIterations; i++) 21716aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy { 21726aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy double 21736aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy distance, 21746aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy gamma; 21756aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy 21766aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy PixelInfo 21776aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy sum_pixel; 21786aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy 21796aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy PointInfo 21806aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy sum_location; 21816aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy 21826aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy ssize_t 21836aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy count, 21846aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy v; 21856aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy 21866aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy sum_location.x=0.0; 21876aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy sum_location.y=0.0; 21886aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy GetPixelInfo(image,&sum_pixel); 2189f89d1dd0b5189cf4df3163fc495f0493f8ddcc7ecristy previous_location=mean_location; 21906aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy previous_pixel=mean_pixel; 21916aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy count=0; 21922494e3d5cea70ebef8e12498b10bc2e24da4803fcristy for (v=(-((ssize_t) height/2)); v <= (((ssize_t) height/2)); v++) 21936aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy { 21946aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy ssize_t 21956aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy u; 21966aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy 21972494e3d5cea70ebef8e12498b10bc2e24da4803fcristy for (u=(-((ssize_t) width/2)); u <= (((ssize_t) width/2)); u++) 21986aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy { 2199e5ecaa83494b57d5fd8956f8b4931d58cfd6e8fccristy if ((v*v+u*u) <= (ssize_t) ((width/2)*(height/2))) 22006aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy { 2201983aa7cfdd9f51bc2309c5b1cbe50c6c3ac23993cristy PixelInfo 2202983aa7cfdd9f51bc2309c5b1cbe50c6c3ac23993cristy pixel; 2203983aa7cfdd9f51bc2309c5b1cbe50c6c3ac23993cristy 2204983aa7cfdd9f51bc2309c5b1cbe50c6c3ac23993cristy status=GetOneCacheViewVirtualPixelInfo(pixel_view,(ssize_t) 22058c2a8442c506836270be8c418c87f031400edf1bcristy MagickRound(mean_location.x+u),(ssize_t) MagickRound( 22068c2a8442c506836270be8c418c87f031400edf1bcristy mean_location.y+v),&pixel,exception); 2207d70bd6ca959a16d8a10f4b2bc0988e91cbcad980cristy distance=(mean_pixel.red-pixel.red)*(mean_pixel.red-pixel.red)+ 2208d70bd6ca959a16d8a10f4b2bc0988e91cbcad980cristy (mean_pixel.green-pixel.green)*(mean_pixel.green-pixel.green)+ 2209d70bd6ca959a16d8a10f4b2bc0988e91cbcad980cristy (mean_pixel.blue-pixel.blue)*(mean_pixel.blue-pixel.blue); 2210983aa7cfdd9f51bc2309c5b1cbe50c6c3ac23993cristy if (distance <= (color_distance*color_distance)) 2211983aa7cfdd9f51bc2309c5b1cbe50c6c3ac23993cristy { 2212983aa7cfdd9f51bc2309c5b1cbe50c6c3ac23993cristy sum_location.x+=mean_location.x+u; 2213983aa7cfdd9f51bc2309c5b1cbe50c6c3ac23993cristy sum_location.y+=mean_location.y+v; 2214983aa7cfdd9f51bc2309c5b1cbe50c6c3ac23993cristy sum_pixel.red+=pixel.red; 2215983aa7cfdd9f51bc2309c5b1cbe50c6c3ac23993cristy sum_pixel.green+=pixel.green; 2216983aa7cfdd9f51bc2309c5b1cbe50c6c3ac23993cristy sum_pixel.blue+=pixel.blue; 2217983aa7cfdd9f51bc2309c5b1cbe50c6c3ac23993cristy sum_pixel.alpha+=pixel.alpha; 2218983aa7cfdd9f51bc2309c5b1cbe50c6c3ac23993cristy count++; 2219983aa7cfdd9f51bc2309c5b1cbe50c6c3ac23993cristy } 22206aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy } 22216aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy } 22226aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy } 22236aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy gamma=1.0/count; 22248c2a8442c506836270be8c418c87f031400edf1bcristy mean_location.x=gamma*sum_location.x; 22258c2a8442c506836270be8c418c87f031400edf1bcristy mean_location.y=gamma*sum_location.y; 22266aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy mean_pixel.red=gamma*sum_pixel.red; 22276aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy mean_pixel.green=gamma*sum_pixel.green; 22286aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy mean_pixel.blue=gamma*sum_pixel.blue; 22296aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy mean_pixel.alpha=gamma*sum_pixel.alpha; 22306aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy distance=(mean_location.x-previous_location.x)* 22316aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy (mean_location.x-previous_location.x)+ 22326aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy (mean_location.y-previous_location.y)* 22336aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy (mean_location.y-previous_location.y)+ 223421a2b741c3102c64fd63164026da2c5b785ec6f5cristy 255.0*QuantumScale*(mean_pixel.red-previous_pixel.red)* 223521a2b741c3102c64fd63164026da2c5b785ec6f5cristy 255.0*QuantumScale*(mean_pixel.red-previous_pixel.red)+ 223621a2b741c3102c64fd63164026da2c5b785ec6f5cristy 255.0*QuantumScale*(mean_pixel.green-previous_pixel.green)* 223721a2b741c3102c64fd63164026da2c5b785ec6f5cristy 255.0*QuantumScale*(mean_pixel.green-previous_pixel.green)+ 223821a2b741c3102c64fd63164026da2c5b785ec6f5cristy 255.0*QuantumScale*(mean_pixel.blue-previous_pixel.blue)* 223921a2b741c3102c64fd63164026da2c5b785ec6f5cristy 255.0*QuantumScale*(mean_pixel.blue-previous_pixel.blue); 2240d70bd6ca959a16d8a10f4b2bc0988e91cbcad980cristy if (distance <= 3.0) 22416aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy break; 22426aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy } 22436aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy SetPixelRed(mean_image,ClampToQuantum(mean_pixel.red),q); 22446aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy SetPixelGreen(mean_image,ClampToQuantum(mean_pixel.green),q); 22456aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy SetPixelBlue(mean_image,ClampToQuantum(mean_pixel.blue),q); 22466aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy SetPixelAlpha(mean_image,ClampToQuantum(mean_pixel.alpha),q); 22476aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy p+=GetPixelChannels(image); 22486aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy q+=GetPixelChannels(mean_image); 22496aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy } 22506aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy if (SyncCacheViewAuthenticPixels(mean_view,exception) == MagickFalse) 22516aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy status=MagickFalse; 22524c8a3ecf917f56f107f2a7477fb60139d2861f3dcristy if (image->progress_monitor != (MagickProgressMonitor) NULL) 22534c8a3ecf917f56f107f2a7477fb60139d2861f3dcristy { 22544c8a3ecf917f56f107f2a7477fb60139d2861f3dcristy MagickBooleanType 22554c8a3ecf917f56f107f2a7477fb60139d2861f3dcristy proceed; 22564c8a3ecf917f56f107f2a7477fb60139d2861f3dcristy 22574c8a3ecf917f56f107f2a7477fb60139d2861f3dcristy#if defined(MAGICKCORE_OPENMP_SUPPORT) 22584c8a3ecf917f56f107f2a7477fb60139d2861f3dcristy #pragma omp critical (MagickCore_MeanShiftImage) 22594c8a3ecf917f56f107f2a7477fb60139d2861f3dcristy#endif 22604c8a3ecf917f56f107f2a7477fb60139d2861f3dcristy proceed=SetImageProgress(image,MeanShiftImageTag,progress++, 22614c8a3ecf917f56f107f2a7477fb60139d2861f3dcristy image->rows); 22624c8a3ecf917f56f107f2a7477fb60139d2861f3dcristy if (proceed == MagickFalse) 22634c8a3ecf917f56f107f2a7477fb60139d2861f3dcristy status=MagickFalse; 22644c8a3ecf917f56f107f2a7477fb60139d2861f3dcristy } 22656aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy } 22666aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy mean_view=DestroyCacheView(mean_view); 22676aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy pixel_view=DestroyCacheView(pixel_view); 22686aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy image_view=DestroyCacheView(image_view); 22696aa40d3dfec558e9b5f4eae34b4cbd7f14944182cristy return(mean_image); 22703e2860cb0796fe77659325ec3d540d8766d54f49cristy} 2271