Programmatically Defining ROIs

While most examples in this chapter use interactive methods to define ROIs, a region can also be defined programmatically. The following example uses thresholding and the CONTOUR function to programmatically trace region outlines. After the path information of the regions has been input into ROI objects, the DRAW_ROI procedure displays each region. The example then computes and returns the geometric area and perimeter of each region as well as the number of pixels making up each region when it is displayed. Complete the following steps for a detailed description of the process.

Example Code
See programdefineroi.pro in the examples/doc/image subdirectory of the IDL installation directory for code that duplicates this example. Run the example procedure by entering programdefineroi at the IDL command prompt or view the file in an IDL Editor window by entering .EDIT programdefineroi.pro.

  1. Prepare the display device and load a color table:
  2. DEVICE, DECOMPOSED = 0, RETAIN = 2 
    LOADCT, 0 
    
  3. Select and open the image file and get its dimensions:
  4. img = READ_PNG(FILEPATH('mineral.png', $ 
       SUBDIRECTORY = ['examples', 'data'])) 
    dims = SIZE(img, /DIMENSIONS) 
    
  5. Create a window and display the original image:
  6. WINDOW, 0, XSIZE = dims[0], YSIZE = dims[1] 
    TVSCL, img 
     

    The following figure displays the initial image.

    Figure 6-6: Initial Image

    imgroi06.gif

  7. Create a mask that identifies the darkest pixels, whose values are less than 50:
  8. threshImg = (img LT 50) 
    
    

    Note
    See Determining Intensity Values for Threshold and Stretch for a useful strategy to use when determining threshold values.

  9. Create and apply a 3x3 square structuring element, using the erosion and dilation operators to close gaps in the thresholded image:
  10. strucElem = REPLICATE(1, 3, 3) 
    threshImg = ERODE(DILATE(TEMPORARY(threshImg), $ 
       strucElem), strucElem) 
    
  11. Use the CONTOUR procedure to extract the boundaries of the thresholded regions. Store the path information and coordinates of the contours in the variables pathInfo and pathXY as follows:
  12. CONTOUR, threshImg, LEVEL = 1,  $ 
       XMARGIN = [0, 0], YMARGIN = [0, 0], $ 
       /NOERASE, PATH_INFO = pathInfo, PATH_XY = pathXY, $ 
       XSTYLE = 5, YSTYLE = 5, /PATH_DATA_COORDS 
     

    The PATH_INFO variable contains the path information for the contours. When used in conjunction with the PATH_XY variable, containing the coordinates of the contours, the CONTOUR procedure records the outline of closed regions. See CONTOUR in the IDL Reference Guide for full details.

  13. Display the original image in a second window and load a discrete color table:
  14. WINDOW, 2, XSIZE = dims[0], YSIZE = dims[1] 
    TVSCL, img 
    LOADCT, 12 
    
  15. Input the data of each of the contour paths into IDLanROI objects:
  16. FOR I = 0,(N_ELEMENTS(PathInfo) - 1 ) DO BEGIN & $ 
     

    Note
    The & after BEGIN and the $ allow you to use the FOR/DO loop at the IDL command line. These & and $ symbols are not required when the FOR/DO loop in placed in an IDL program as shown in ProgramDefineROI.pro in the examples/doc/image subdirectory of the IDL installation directory.

  17. Initialize oROI with the contour information of the current region:
  18.    line = [LINDGEN(PathInfo(I).N), 0] & $ 
       oROI = OBJ_NEW('IDLanROI', $ 
          (pathXY(*, pathInfo(I).OFFSET + line))[0, *], $ 
          (pathXY(*, pathInfo(I).OFFSET + line))[1, *]) & $ 
    
  19. Draw the ROI object in a Direct Graphics window using DRAW_ROI:
  20.    DRAW_ROI, oROI, COLOR = 80 & $ 
    
  21. Use the IDLanROI::ComputeMask function in conjunction with IMAGE_STATISTICS to obtain maskArea, the number of pixels covered by the region when it is displayed. The variable, maskResult, is input as the value of MASK in the second statement in order to return the maskArea:
  22.    maskResult = oROI -> ComputeMask( $ 
          DIMENSIONS = [dims[0], dims[1]]) & $ 
       IMAGE_STATISTICS, img, MASK = maskResult, $ 
          COUNT = maskArea & $ 
    
  23. Use the IDLanROI::ComputeGeometry function to return the geometric area and perimeter of each region. In the following example, SPATIAL_SCALE defines that each pixel represents 1.2 by 1.2 millimeters:
  24.    ROIStats = oROI -> ComputeGeometry( $ 
          AREA = geomArea, PERIMETER = perimeter, $ 
          SPATIAL_SCALE = [1.2, 1.2, 1.0]) & $ 
     

    Note
    The value for SPATIAL _SCALE in the previous statement is used only as an example. The actual spatial scale value is typically known based upon equipment used to gather the data.

  25. Print the statistics for each ROI when it is displayed and wait 3 seconds before proceeding to the display and analysis of the next region:
  26.    PRINT, ' ' & $ 
       PRINT, 'Region''s mask area =   ', $ 
          FIX(maskArea), ' pixels' & $ 
       PRINT, 'Region''s geometric area =   ', $ 
          FIX(geomArea), ' mm' & $ 
       PRINT, 'Region''s perimeter =    ', $ 
          FIX(perimeter),' mm' & $ 
       WAIT, 3 
    
  27. Remove each unneeded object reference after displaying the region:
  28.    OBJ_DESTROY, oROI & $ 
    
  29. End the FOR loop:
  30. ENDFOR 
     

    The outlines of the ROIs recorded by the CONTOUR function have been translated into ROI objects and displayed using DRAW_ROI. Each region's "mask area," (computed using IDLanROI::ComputeMask in conjunction with IMAGE_STATISTICS) shows the number of pixels covered by the region when it is displayed on the screen.

    Each region's geometric area and perimeter, (computed using IDLanROI::ComputeGeometry's SPATIAL_SCALE keyword) results in the following geometric area and perimeter measurements in millimeters.

    Figure 6-7: Display of Programmatically Defined Regions

    Programmatically_Defining_ROIs-15.jpg