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 an image. 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 following text to a file called ROIMask.java. Make sure
that the jar file xinapse5.jar is in your
classpath, then compile it with the javac command:
javac ROIMask.java
This will create a file called ROIMask.class. To run the programme, type (for example):java ROIMask image
where image is the name of an image on which you have also drawn some ROIs, and saved them to a file called image.roi.
import java.util.*;
import java.io.*;
import com.xinapse.util.Twiddler;
import com.xinapse.loadableimage.*;
import com.xinapse.multisliceimage.*;
import com.xinapse.multisliceimage.roi.*;
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 MultiSliceImage instance from the supplied file name.
MultiSliceImage im = null;
try {
im = MultiSliceImage.getInstance(imageName, "r");
}
catch (MultiSliceImageException msiE) {
System.err.println("Error reading input image: " + msiE.getMessage());
System.exit(-1);
}
catch (java.io.IOException ioE) {
System.err.println("Error processing input image: " + ioE.getMessage());
System.exit(-1);
}
// Create an output image just like the input image.
MultiSliceImage outputIm = null;
try {
outputIm = (MultiSliceImage) im.clone();
}
catch (CloneNotSupportedException cnsE) {
System.err.println("Error: " + cnsE.getMessage());
System.exit(-1);
}
try {
int nRows = im.getNRows();
int nCols = im.getNCols();
int nSlices = im.getTotalNSlices();
PixelDataType dataType = im.getPixelDataType();
float pixelXSize = im.getPixelXSize();
float pixelYSize = im.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.
int slice = roi.getSlice();
if (slice >= 0 && slice < nSlices) {
// Get the correpsonding image slice.
Object slicePix = im.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, 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.
ComplexMode.MAGNITUDE);
// Put the masked data to the output image.
outputIm.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 (ParameterNotSetException pnsE) {
System.err.println("Error: " + pnsE.getMessage());
System.exit(-1);
}
catch (ROIException roiE) {
System.err.println("Error: " + roiE.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 {
outputIm.write(ImageName.addSuffix(imageName, "Masked"));
outputIm.close();
System.out.println("Created output image: " + ImageName.addSuffix(imageName, "Masked"));
}
catch (MultiSliceImageException msiE) {
System.err.println("Error writing output image: " + msiE.getMessage());
System.exit(-1);
}
catch (InvalidImageException iiE) {
System.err.println("Error closing output image: " + iiE.getMessage());
System.exit(-1);
}
}
}