;+ ; :NAME: ; FIND_CLUSTER_CENTERS ; ; :PURPOSE: ; This function will find the centroid coordinates for clusters ; located throughout a provided image. The clusters will first ; be refined by thresholding the provided image using the ; supplied digital count threshold value. ; ; :CATEGORY: ; Image Processing. ; ; :CALLING SEQUENCE: ; Result = $ ; FIND_CLUSTER_CENTERS( image, $ ; threshold ) ; ; :RETURN VALUE: ; This function will return a 2xN array of cluster centroid values ; that have been located in the thresholded version of the image ; provided. ; ; :INPUTS: ; image: ; An array containing the clusters of points for which the ; centroid coordinates are to be found. ; threshold: ; A scalar defining the digital count threshold to be used ; in the creation of the binary version of the provided array. ; ; :KEYWORD PARAMETERS: ; NONE ; ; :RETURN VALUE: ; This function returns a 2xn array containing the cluster center coordinates ; for the clusters identified by this routine. ; ; :SIDE EFFECTS: ; None ; ; :REQUIRES: ; FILL_REGIN ; FIND_CENTER ; ; REFERENCE: ; Gonzalez, R.C. and R.E. Woods, Digital Image Processing, ; Third Edition, Prentice Hall, Upper Saddle River, New Jersey, ; 2007 (ISBN: 0131687288X / ISBN-13: 978-0131687288) ; ; MODIFICATION HISTORY: ; Written by: Philip Salvaggio ; March, 2007 Original code ; September, 2008 Converted to a general-purpose routine (Carl Salvaggio) ;- FUNCTION FIND_CLUSTER_CENTERS, image, threshold, RUNAWAY_LIMIT=runawayLimit ;+ ; If not provided by the calling module, set the maximum size (in pixels) ; of the growth region ;- IF NOT KEYWORD_SET( runawayLimit ) THEN runawayLimit = 100 ;+ ; Determine the dimensions of the provided cluster image ;- dimensions = SIZE( image, /DIMENSIONS ) numberSamples = dimensions[0] numberLines = dimensions[1] ;+ ; Threshold the array to create a binary version of the provided ; cluster image ;- thresholdedImage = BYTARR( numberSamples, numberLines ) thresholdedImage[ WHERE( image GE threshold ) ] = 1B ;+ ; Create a binary-boundary image outlining each cluster in the thresholded ; data array using the technique described by Gonzalez (2007) ;- structuringElement = [ [ 1, 1, 1 ], $ [ 1, 1, 1 ], $ [ 1, 1, 1 ] ] boundaryImage = thresholdedImage XOR DILATE( thresholdedImage, structuringElement ) ;+ ; Make an outline around the entire image to prevents runaways ;- boundaryImage[*,0] = 1 boundaryImage[*,numberLines-1] = 1 boundaryImage[0,*] = 1 boundaryImage[numberSamples-1,*] = 1 ;+ ; Create a version of the thresholded image with a one pixel wide ; black outline surrounding the entire image to be used to prevent ; growth runaway at the borders of the image ;- boundaryRemovedThresholdedImage = BYTARR( numberSamples, numberLines ) boundaryRemovedThresholdedImage[1:numberSamples-2,1:numberLines-2] = $ thresholdedImage[1:numberSamples-2,1:numberLines-2] ;+ ; Determine all locations of pixels within clusters to determine ; possible locations for the start of region growth ;- whiteIndices = WHERE( boundaryRemovedThresholdedImage ) ;+ ; Iterate through each possible cluster origin and grow/fill the region ; that contains each origin point ;- firstCenter = 1 structuringElement = [ [ 0, 1, 0 ], $ [ 1, 1, 1 ], $ [ 0, 1, 0 ] ] FOR i=0L, N_ELEMENTS( whiteIndices )-1 DO BEGIN indices = ARRAY_INDICES( boundaryRemovedThresholdedImage, whiteIndices[i] ) IF ( boundaryRemovedThresholdedImage[indices[0],indices[1]] ) THEN BEGIN filledImage = FILL_REGION( boundaryImage, indices, runawayLimit, STATUS=notRunaway ) ;+ ; Once a region is filled, remove it from the set of regions/clusters to be ; examined by removing it from the boundary-removed thresholded image (that is, ; setting all the locations in the current cluster to zero ;- boundaryRemovedThresholdedImage = boundaryRemovedThresholdedImage XOR $ ( DILATE( filledImage, structuringElement ) AND $ boundaryRemovedThresholdedImage ) ;+ ; If a runaway condition was not encountered for the growth of the current ; cluster, then compute and record the centroid coordinate, otherwise, move ; on to the next cluster ;- IF ( notRunaway ) THEN BEGIN center = FIND_CENTER( filledImage ) IF ( firstCenter ) THEN BEGIN centers = [ [ center[0], center[1] ] ] firstCenter = 0 ENDIF ELSE BEGIN centers = [ centers, [ center[0], center[1] ] ] ENDELSE ENDIF ENDIF ENDFOR ;+ ; Reconfigure the centroid coordinate array into a 2xN format and ; return to the calling module ;- RETURN, REFORM( centers, 2, N_ELEMENTS( centers )/2 ) END