API Example - Handling ROI Files

This example shows you how to read in ROIs from a file, and use them to mask an image. With simple changes, this could also yield statistics about the image, or write out pixel values within the ROIs. The getStats() method of the class ROI has many uses: see the A.P.I. documentation for further details.

To try out the programme, save the text below to a file called ROIMask.java. You need to make sure that the following files from the Jim installation folder are in your classpath:

For programs that use other parts of the A.P.I., you may also need to put these files from the Jim installation folder in your classpath: Then compile the program with the javac command:

javac ROIMask.java

Note: you must use javac version 17.
This will create a file called ROIMask.class. To run the programme, type (for example):

java ROIMask input-image

where input-image is the name of the image to mask. The name of the ROI file should be input-image.roi.

<--Java code Starts Here -->

import java.util.List;
import java.util.LinkedList;
import java.io.FileInputStream;
import java.io.IOException;

import com.xinapse.image.ReadableImage;
import com.xinapse.image.WritableImage;
import com.xinapse.image.ImageUtils;
import com.xinapse.image.PixelDataType;
import com.xinapse.image.ComplexMode;
import com.xinapse.image.ParameterNotSetException;
import com.xinapse.image.InvalidImageException;
import com.xinapse.multisliceimage.roi.*;
import com.xinapse.multisliceimage.ImageName;
import com.xinapse.util.Twiddler;

public class ROIMask {

  /**
     An example Java programme to mask an image using a set of ROIs as the mask.
     Demonstrates some of the A.P.I. for handling ROI files.
     

The ROI file name is assumed to be equal to the input image name, but with an extension ".roi". An output image is created with the same name as the input image, but with the suffix "Masked". */ public static void main(String argv[]) { if (argv.length != 1) { System.err.println("Usage: ROIMask image"); System.err.println(" - mask an image using ROIs as the mask."); System.exit(-1); } String imageName = argv[0]; // Create a ReadableImage instance from the supplied file name. ReadableImage inputImage = null; try { inputImage = ImageUtils.getReadableImage(imageName); } catch (InvalidImageException iiE) { System.err.println("Error reading input image: " + iiE.getMessage()); System.exit(-1); } // Create an output image just like the input image, held in memory. WritableImage outputImage = null; try { outputImage = ImageUtils.getWritableImage(inputImage); } catch (InvalidImageException iiE) { System.err.println("Error: " + iiE.getMessage()); System.exit(-1); } catch (IOException ioE) { System.err.println("Error: " + ioE.getMessage()); System.exit(-1); } try { int nRows = inputImage.getNRows(); int nCols = inputImage.getNCols(); int nSlices = inputImage.getTotalNSlices(); PixelDataType dataType = inputImage.getPixelDataType(); float pixelXSize = inputImage.getPixelXSize(); float pixelYSize = inputImage.getPixelYSize(); // Make the ROI file name by adding an extension. String roiFileName = ImageName.addExtension(imageName, "roi"); // Read the ROIs from the ROI file. List roiList = null; try { roiList = ROI.getROIs(new FileInputStream(roiFileName)); } catch (IOException ioE) { System.err.println("Error reading ROIs: " + ioE.getMessage()); System.exit(-1); } if (roiList != null) { // Use a "Twiddler" to show progress through the masking operation. System.out.print("Masking: "); Twiddler twiddler = new Twiddler(); // Process the ROIs one at a time. for (int i = 0; i < roiList.size(); i++) { ROI roi = (ROI) roiList.get(i); // Get the slice number on which this ROI is defined. // Slice numbers are indexed from zero. int slice = roi.getSlice(); if (slice >= 0 && slice < nSlices) { // Get the correpsonding image slice. Object slicePix = inputImage.getSlice(slice); // Mask the pixels using the ROI as a mask. getStats() is a multi-purpose method // that returns image statistics, masks images etc. See documentation for a full // description. // N.B. This simple approach won't have the desired effect if there's // more than one ROI per slice, but this is just a demonstration. // To do this properly, you would need to find all the ROIs in any particular slice, // and use the static method ROI.getStats(...) with a list of ROIs, and specify the // appropriate CombineMode to combine the ROIs in the list. roi.getStats(slicePix, dataType, nCols, nRows, // Since we are handling data slice-by-slice, the offset to the // first pixel in this slice is zero. 0, pixelXSize, pixelYSize, // Set all pixels outside the ROI to zero. MaskAction.MASK_OUTSIDE, // At least half a pixel must be inside a the ROI for it to be considered // as 'inside' the ROI. MaskMode.HALF, // Outside pixel intensities are set to zero. 0, // No writing of intensities. null, // Doesn't matter what the units are, since we're not writing intensities. false, // Doesn't matter what the complex mode is - unused for real images. (ComplexMode) null); // Put the masked data to the output image. outputImage.putSlice(slicePix, slice); } else { System.err.println("Warning: slice out of range for this image."); } twiddler.twiddle(); } twiddler.done(); } } catch (InvalidImageException iiE) { System.err.println("Error: " + iiE.getMessage()); System.exit(-1); } catch (IOException ioE) { System.err.println("Error: " + ioE.getMessage()); System.exit(-1); } catch (ParameterNotSetException pnsE) { System.err.println("Error: " + pnsE.getMessage()); System.exit(-1); } // Write the output image to a new file with a name like the input image, but with a // suffix "Masked". try { outputImage.write(ImageName.addSuffix(imageName, "Masked")); outputImage.close(); System.out.println("Created output image: " + ImageName.addSuffix(imageName, "Masked")); } catch (InvalidImageException iiE) { System.err.println("Error closing output image: " + iiE.getMessage()); System.exit(-1); } catch (IOException ioE) { System.err.println("Error closing output image: " + ioE.getMessage()); System.exit(-1); } System.exit(0); } }

Jim Home