Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Workshop:
Automation of image analysis tasks with ImageJ
and MRI Cell Image Analyzer
Montpellier RIO Imaging
Volker Baecker
14.03.2008
volker.baecker@mri.cnrs.fr
1/26
Automation of image analysis tasks with ImageJ and MRI Cell Image Analyzer
Table of Contents
1. Introduction......................................................................................................................................3
1.1 The ImageJ macro language Hello World..............................................................................3
1.2 Integrating macros into the ImageJ interface.............................................................................4
1.2.1 Startup macros....................................................................................................................4
1.2.2 Macros as plugins...............................................................................................................4
1.2.3 Macros as menu items........................................................................................................5
1.2.4 Calling macros from action bars........................................................................................6
1.2.5 Running macros from toolsets...........................................................................................7
2. Writing an image type converter batch............................................................................................9
2.1 Using the ImageJ macro language.............................................................................................9
2.1.1 Macro recorder and Multiple Image Processor..................................................................9
2.1.2 Programming the loop .....................................................................................................10
2.2 Using MRI Visual Scripting....................................................................................................12
3. Measuring intensities inside and outside a masked region.............................................................13
3.1 Getting the basic steps from the macro recorder.....................................................................14
3.2 Resetting the results table........................................................................................................14
3.3 Adding the loop and loading images belonging together........................................................15
3.4 Closing images no longer needed and freeing memory...........................................................16
3.5 Saving the results.....................................................................................................................16
4. Interactive visual scripts.................................................................................................................17
5. Measuring perpendicular segments along a line............................................................................18
6. Writing a 2d region growing segmentation tool macro..................................................................22
volker.baecker@mri.cnrs.fr
2/26
Automation of image analysis tasks with ImageJ and MRI Cell Image Analyzer
1. Introduction
In this workshop you will learn how to automate image analysis tasks using ImageJ. There are three
mechanisms that allow to create automated procedures in ImageJ. Maybe the most simple is the
MRI Visual Scripting plugin that allows to create applications from existing operations using drag
and drop. The second one is the ImageJ macro language. The third possibilty is to write and
integrate custom plugins. In this workshop we will only talk about the first two possibilties, the
visual scripting and the ImageJ macro language.
Once a custom procedure has been created it can be integrated into ImageJ in different ways. It can
appear as a menu item, or as a button and a keyboard shortcut can be associated with it.
Illustration 1: Creating a
new macro.
In the text editor enter command print( Hello World );. You can run the macro using
Macros>Run Macro or by pressing ctrl+r. Create a folder workshop-macros and save the macro
using File>Save As.
You can use Plugins>Macros>Run to run any saved macro. Or you can use Plugins>Macros>Install
to put the macro into the Macros menu during one session (until you close ImageJ).
Open the Hello World macro again, using Plugins>Edit. We will now define a keyboard shortcut to
run the macro. There can be multiple macros in the same textfile. In this case each macro starts with
the keyword macro, followed by the name of the macro in quotation marks. After the name but still
within the quotation marks you can define a keyboard shortcut in brackets, for example [f11]. The
body of the macro must then be surrounded with the brackets { and }. Save the modified macro and
reinstall it. For the keyboard shortcut to work, an ImageJ window must have the focus. Click on the
ImageJ launcher window and press f11.
volker.baecker@mri.cnrs.fr
3/26
Automation of image analysis tasks with ImageJ and MRI Cell Image Analyzer
macro "Hello World [f11]" {
print("Hello World!");
}
4/26
Automation of image analysis tasks with ImageJ and MRI Cell Image Analyzer
the two macros. You can define the keyboard shortcuts using Plugins>Shortcuts>Create Shortcut.
Select the Hello World plugin from the list and enter f11 as shortcut key. This will create an entry
in the file IJ_Prefs.txt in the ImageJ base-folder and the shortcuts will remain when you restart
ImageJ.
volker.baecker@mri.cnrs.fr
5/26
Automation of image analysis tasks with ImageJ and MRI Cell Image Analyzer
label = the tooltip text that will be displayed when the mouse pointer is over the button
volker.baecker@mri.cnrs.fr
6/26
Automation of image analysis tasks with ImageJ and MRI Cell Image Analyzer
run_macro_file (run a macro file from the macros folder or one of its subfolders)
install_macro (install a macro file from the macros folder or one of its subfolders)
arg = the name of the macro file or the macro command string
After you made changes save the macro and run it using Macros>Run Macro. The macro will be
saved to plugins\ActionBar. After you restarted ImageJ it will appear in the corresponding menu.
Each action bar has a subfolder in the folder plugins\ActionBar\icons. Put the icons you want to use
into this folder.
// Action Bar description file :Hello_
run("Action Bar","/plugins/ActionBar/Hello_.txt");
exit();
<line>
<button> 1 line 1
label=Hello World
icon=Hello_/globe.png
action=run_macro_string
arg=run("Hello World");
<button> 2 line 1
label=Hello World 2
icon=Hello_/globe.png
action=run_macro_string
arg=run("Hello World 2")
</line>
// end of file
Illustration 4:
The resulting
action bar.
7/26
Automation of image analysis tasks with ImageJ and MRI Cell Image Analyzer
character and a definition of the icon image to be displayed on the button. You can find a
description of the syntax for defining the icon images here:
http://rsb.info.nih.gov/ij/developer/macro/macros.html
You can create the icon from an image using the Image to tool icon macro from:
http://rsb.info.nih.gov/ij/macros/tools/. The image must have a size of 16x16 pixel and it must not
contain more than 16 colors. Download the macro and put it into plugins>utilities, then restart
ImageJ. Load the globe.png image and convert it to an 8-bit color image with 16 colors, then start
the plugin.
macro "Unused Tool - C037" { }
macro "Hello World Action Tool C68bD6bD6cD7bD8aD8bD9aD9bDa1C347D00D04D06D07D10D11D14D20D
21D2dD30D31D40D41D50D60D70CcddD25D29D2aD35D43D44D49D4cD52
D76D81D94Da3DabDbaDc4Dc6Dc8C712D3eDaeDcdDdbDdcDe9DeaCbbcD
26D28D33D42D5bD62D78D83D85D91D92D93D95DacDb5DbbC569D09D2c
D51D6eD7eD80D8eD90Da0Db1DbdDc1Dc2DccDd2Dd3De4De5De6De7De8
CeeeD34D45D4bD53D54D55D5aD64D65D71D98Da4Da9DaaDb3Db6Db8Db
9Dc5C9bcD17D18D24D2bD3cD59D5dD69D9dDa5Db2Dc3Dc7DcaDd5Dd9C
569D05D08D12D13D15D1cD22D23D32D4eD5eD7cD8cD9cD9eCdefD36D3
bD46D47D56D57D61D63D66D67D73D74D75Da2Ca00D8fD9fDafDbeDbfD
ceDcfDddDdeDdfDebDecDeeDefDf5Df6Df7Df8Df9DfaDfbDffCbcdD27
D37D38D48D58D68D6dD72D77D7dD82D84D8dDd6Dd7Dd8C78aD0aD16D1
aD1bD3dD4dD5cDadDc9Dd4DdaCfffD39D3aD4aD86D87D88D96D97Da6D
a7Da8Db4Db7C8acD19D6aD79D7aD89D99DbcDcb"
{
print("Hello World!");
}
macro "Hello World 2 Action Tool C68bD6bD6cD7bD8aD8bD9aD9bDa1C347D00D04D06D07D10D11D14D20D
21D2dD30D31D40D41D50D60D70CcddD25D29D2aD35D43D44D49D4cD52
D76D81D94Da3DabDbaDc4Dc6Dc8C712D3eDaeDcdDdbDdcDe9DeaCbbcD
26D28D33D42D5bD62D78D83D85D91D92D93D95DacDb5DbbC569D09D2c
D51D6eD7eD80D8eD90Da0Db1DbdDc1Dc2DccDd2Dd3De4De5De6De7De8
CeeeD34D45D4bD53D54D55D5aD64D65D71D98Da4Da9DaaDb3Db6Db8Db
9Dc5C9bcD17D18D24D2bD3cD59D5dD69D9dDa5Db2Dc3Dc7DcaDd5Dd9C
569D05D08D12D13D15D1cD22D23D32D4eD5eD7cD8cD9cD9eCdefD36D3
bD46D47D56D57D61D63D66D67D73D74D75Da2Ca00D8fD9fDafDbeDbfD
ceDcfDddDdeDdfDebDecDeeDefDf5Df6Df7Df8Df9DfaDfbDffCbcdD27
D37D38D48D58D68D6dD72D77D7dD82D84D8dDd6Dd7Dd8C78aD0aD16D1
aD1bD3dD4dD5cDadDc9Dd4DdaCfffD39D3aD4aD86D87D88D96D97Da6D
a7Da8Db4Db7C8acD19D6aD79D7aD89D99DbcDcb"
{
newImage("Welcome", "8-bit White", 800, 150, 1);
setFont("Serif", 100, "antialiased");
setColor(255,255,0);
drawString("Hello world!", 150, 100);
}
volker.baecker@mri.cnrs.fr
8/26
Automation of image analysis tasks with ImageJ and MRI Cell Image Analyzer
volker.baecker@mri.cnrs.fr
9/26
Automation of image analysis tasks with ImageJ and MRI Cell Image Analyzer
volker.baecker@mri.cnrs.fr
10/26
Automation of image analysis tasks with ImageJ and MRI Cell Image Analyzer
The open command opens loads the image. Then the convertion is run. The absolute output path is
calculated in a similar way as the input path and the converted image is saved.
Save and run the macro. It works but it has some problems:
if there is a file in the folder that is not an image the macro will stop with an error
in the end we don't know what has been done by the macro
The first problem can be solved with the command setBatchMode(<boolean>). Call it with true
before the loop to activate the batch mode and with false after the loop to deactivate the batch
mode.
To solve the second problem we will check if the file extension corresponds to an image file type.
In order not to mess up our code we will write a function that checks the file extension and call it
from our main loop.
function isImage(filename) {
extensions = newArray("tif", "tiff", "jpg", "bmp");
result = false;
for (i=0; i<extensions.length; i++) {
if (endsWith(toLowerCase(filename), "." + extensions[i]))
result = true;
}
return result;
}
Text 8: The isImage function answers true if the file has tif, tiff, jpg or bmp as extension.
To solve the third problem we can use the integrated showProgress(<current>,<total>) function.
However we need to count the number of images among the files in the folder first. To do this we
write a second function.
function countImages(array) {
result = 0;
for (i=0; i<array.length; i++) {
if (isImage(array[i])) result++;
}
return result;
}
volker.baecker@mri.cnrs.fr
11/26
Automation of image analysis tasks with ImageJ and MRI Cell Image Analyzer
inputFolder = getDirectory("8-bit converter - Choose the input folder!");
outputFolder = getDirectory("8-bit converter - Choose the output folder!");
setBatchMode(true);
images = getFileList(inputFolder);
imageCount = countImages(images);
notice = "converted: \n";
for (i=0; i<images.length; i++) {
showProgress(i, imageCount);
inputPath = inputFolder + images[i];
if (isImage(inputPath)) {
open(inputPath);
run("8-bit");
outputPath = outputFolder + images[i];
save(outputPath);
close();
notice = notice + outputPath + "\n";
}
}
setBatchMode(false);
print(notice);
exit();
Text 10: The modified macro using the functions defined above.
volker.baecker@mri.cnrs.fr
12/26
Automation of image analysis tasks with ImageJ and MRI Cell Image Analyzer
To create the loop add either the operation for each image do or the operation for each image
in list do to the beginning of the application and the operation foreach image end to the end of the
application. Connect the end operation with the do operation. Connect the open image operation
with the do operation. The open operation will then get the filename from the do operation
in each iteration of the loop.
Both do operations let the user select a number of files by either selecting all the files or by
selecting a folder. If a folder is selected all images in the folder and in all subfolders will be used.
The second do operation gives the user the possibility to eliminate files from the list. This way he
can add in a root folder and then remove the images that should not be treated.
Run the application and select 3 or 4 RGB images.
Now remove the show image operation from the application by clicking on the white cross in
the upper right corner. Replace it with the save image operation and connect its input image
parameter to the convert image operation. Connect its path parameter either to the do operation
or to the open image operation. Open the options of the save image operation. We need to
tell the operation where to save the result. You can either use the browse button to select an output
folder or you put a name in the output folder field and select create in source folder . Use for
example converted as output folder and select create in source folder .
We should now save the application. Right click in the top area of the application tile and select
save as from the context menu. Create a new folder workshop in the _applications folder and
save the application there. There will now be a menu item workshop containing the convert to
8-bit application in the applications>applications menu.
13/26
Automation of image analysis tasks with ImageJ and MRI Cell Image Analyzer
You will learn how to:
save measurement result in a way that they can be opened with a spreadsheet program
afterwards
Text 12: Setting the measurements and clearing the results table.
volker.baecker@mri.cnrs.fr
14/26
Automation of image analysis tasks with ImageJ and MRI Cell Image Analyzer
Text 15: Getting all filenames containing a text from a list of filenames.
Now write a loop around the processing part of the macro that opens all nuclei images and the
corresponding cytoplasm images. Use the replace function to create the cytoplasm image filename
from the nuclei image filename.
volker.baecker@mri.cnrs.fr
15/26
Automation of image analysis tasks with ImageJ and MRI Cell Image Analyzer
for (i=0; i<nucleiImages.length;i++) {
inputPath = inputFolder + nucleiImages[i];
open(inputPath);
setAutoThreshold();
run("Convert to Mask");
run("Fill Holes");
run("Analyze Particles...", "size=800-Infinity circularity=0.00-1.00
show=Masks");
run("Create Selection");
open(inputFolder + replace(nucleiImages[i], nucleiName, cytoplasmName));
call("operations.Operation.run", "find and subtract background",
"1; 1; 2; 0.05");
run("Restore Selection");
run("Measure");
run("Make Inverse");
run("Measure");
}
volker.baecker@mri.cnrs.fr
16/26
Automation of image analysis tasks with ImageJ and MRI Cell Image Analyzer
Use the File.open(<filename>) function to create a new text file. You can write into the file using
print(<file>, <text>). Separate columns with a tabulator by using \t and rows by a newline using
\n .
function reportResults(filename) {
reportFile = File.open(filename);
headerLine = "filename\tinside intensity\toutside intensity\tratio\n";
print(reportFile, headerLine);
for (i=0; i<nucleiImages.length; i++) {
line = nucleiImages[i] + "\t";
int1 = getResult("IntDen", i+0);
int2 = getResult("IntDen", i+1);
line = line + int1 + "\t";
line = line + int2 + "\t";
line = line + (int2 / int1);
line = line + "\n";
print(reportFile, line);
}
File.close(reportFile);
}
volker.baecker@mri.cnrs.fr
17/26
Automation of image analysis tasks with ImageJ and MRI Cell Image Analyzer
volker.baecker@mri.cnrs.fr
18/26
Automation of image analysis tasks with ImageJ and MRI Cell Image Analyzer
We will first do the work and then care about the user input. In a first version we just use variables
to define the distance and length. First we have to make sure that the image has a line selection and
display an error message if it has none.
distance = 200;
radius = 50;
getLine(x1, y1, x2, y2, lineWidth);
if (x1 == -1) {
exit("this macro needs a line selection");
}
Text 19: If there is no line selection the macro quits and displays an
error message.
We will calculate a perpendicular line segment and move it along the line selection. We define the
four coordinates of the line segment as global variables. Since we are working in radians when
calculating angles we define the constant pi as a global variable as well.
We can create a perpendicular line segment in the start point of the line selection in the following
way:
Create a horizontal line segment of the desired size with its middle point in 0,0.
Calculate the angle alpha of the line selection with the x axis. The angle is the atan of the
gradient. And the gradient is (y2-y1) / (x2-x1).
move the middle point of the line segment to the start point of the line selection.
We implement the described algorithm in a function called newPerpendicularLineSeg that takes the
start and end point of the line selection and the radius of the new segment as input parameters.
Call the new function and try it by drawing the line segment into the image. Use drawLine to draw
the segment and updateDisplay to make the change visible.
volker.baecker@mri.cnrs.fr
19/26
Automation of image analysis tasks with ImageJ and MRI Cell Image Analyzer
var
var
var
var
var
segXs;
segYs;
segXe;
segYe;
pi = 3.14159265;
=
=
=
=
- radius;
0;
radius;
0;
segXs
segXs
segXe
segXe
+
+
sin(angle)
cos(angle)
sin(angle)
cos(angle)
*
*
*
*
segYs;
segYs;
segYe;
segYe;
=
=
=
=
segXsNew
segYsNew
segXeNew
segYeNew
+
+
+
+
xs;
ys;
xs;
ys;
volker.baecker@mri.cnrs.fr
20/26
Automation of image analysis tasks with ImageJ and MRI Cell Image Analyzer
function moveLineSeg(x1, y1, x2, y2, distance) {
dx = x2 x1;
dy = y2 y1;
n = sqrt((dx*dx) + (dy*dy));
xInc = (dx / n) * distance;
yInc = (dy / n) * distance;
segXs = segXs + xInc;
segYs = segYs + yInc;
segXe = segXe + xInc;
segYe = segYe + yInc;
}
Text 21: Move the line segment along the line selection by distance.
function intersects(x1, y1, x2, y2) {
result = false;
den = (segYe-segYs)*(x2-x1) (segXe-segXs)*(y2-y1);
ua = ((segXe-segXs)*(y1-segYs) - (segYe-segYs)*(x1-segXe)) / den;
ub = ((x2-x1)*(y1-segYs)-(y2-y1)*(x1-segXs)) / den;
if (ua>=-1 && ub>-1 && ua<=1 && ub<=1) result = true;
return result;
}
Text 23: The main loop, drawing line sgments along the line selection.
Before we replace the drawing with creating a selection and measuring it we create a dialog that lets
the user enter the distance between the line segments and the radius of the line.
Dialog.create("measure perpendicular line segments");
Dialog.addNumber("distance: ", 100);
Dialog.addNumber("radius: ", 50);
Dialog.show();
distance = Dialog.getNumber();
radius
= Dialog.getNumber();
volker.baecker@mri.cnrs.fr
21/26
Automation of image analysis tasks with ImageJ and MRI Cell Image Analyzer
newPerpendicularLineSeg(x1, y1, x2, y2, radius);
while(intersects(x1, y1, x2, y2)) {
makeLine(segXs,segYs, segXe, segYe);
roiManager("Add");
updateDisplay();
moveLineSeg(x1, y1, x2, y2, distance);
}
exit();
Text 25: Creating the selections and adding them to the roi manager.
currentRegionSize = 0;
currentRegionIntDen = 0;
threshold = 10;
queue;
mask;
inputImage;
iteration = 0;
Text 26: The global variables for the region grow macro.
Since the variables will keep their values after the macro ran, we have to initialize them at the
beginning. In the same time we remove an existing selection from the image.
function initialize() {
run("Select None");
currentRegionSize = 0;
currentRegionIntDen = 0;
iteration = 0;
}
22/26
Automation of image analysis tasks with ImageJ and MRI Cell Image Analyzer
default have the value it has been initialized with in the beginning and the user will be able to
change it by double clicking the tool icon. To achive this we have to add a macro with the same
name as our tool but with the word Options added.
macro "Region Growing Tool Options" {
threshold = getNumber("threshold delta:", threshold);
}
Text 28: This macro allows the user to set the threshold by double clicking
the tool icon.
In the region growing tool we first call the initialize method. Then we get the current image and the
current cursor location, i.e. the point on which the user clicked. We switch to batch mode and create
the mask that will keep track of the points already visited.
Since there are no dynamic data structures available in the scripting language we will model the
queue as a string. We initialize the queue with the point the user clicked on and call the function
growRegion.
macro "Region Growing Tool - C0a0L18f8L818f" {
initialize();
inputImage = getImageID();
getCursorLoc(x, y, z, flags);
setBatchMode(true);
newImage("mask", "8-bit", getWidth(), getHeight(), nSlices);
mask = getImageID();
selectImage(inputImage);
queue = "" + x + "," + y + ";";
growRegion();
volker.baecker@mri.cnrs.fr
23/26
Automation of image analysis tasks with ImageJ and MRI Cell Image Analyzer
function growRegion() {
while(lengthOf(queue)!=0) {
showStatus("queue: " + lengthOf(queue));
points = split(queue, ";");
point = split(points[0], ",");
removeFirst();
addToSelection(point, 50);
currentRegionSize++;
currentRegionIntDen = currentRegionIntDen +
getPixel(parseInt(point[0]),parseInt(point[1]));
testAndAddNeighbor(point, -1, 0);
testAndAddNeighbor(point, 1, 0);
testAndAddNeighbor(point, 0, -1);
testAndAddNeighbor(point, 0, 1);
iteration++;
}
}
Text 30: Grow region runs as long as there are points in the queue.
testAndAddNeighbors first checks if the pixel has been examined before. Pixels that have already
been checked will be marked with a value 100 in the mask when they will not be part of the result
region and a value 50 if they are accepted in the result region. If the ccordinates are out of the image
region the function returns as well.
Then the function checks if the intensity of the pixel lies within the the interval defined by the
current average intensity plus/minus the threshold. If this is the case the point will be added to the
result region, otherwise he will be marked as already checked. In the first case the point will be
added to the queue, as well, to avoid that the same point gets into the queue multiple times.
volker.baecker@mri.cnrs.fr
24/26
Automation of image analysis tasks with ImageJ and MRI Cell Image Analyzer
function testAndAddNeighbor(point, xoff, yoff) {
neighborX =
parseInt(point[0]) + xoff;
neighborY = parseInt(point[1]) + yoff;
if (alreadyTested(neighborX, neighborY)) return;
if (neighborX<0 || neighborX>getWidth()-1) return;
if (neighborY<0 || neighborY>getHeight()-1) return;
neighborInt = getPixel(neighborX, neighborY);
average = currentRegionIntDen / currentRegionSize;
if (neighborInt>average-threshold && neighborInt<average+threshold) {
addToQueue(neighborX, neighborY);
point = newArray(2);
point[0] = neighborX;
point[1] = neighborY;
addToSelection(point, 50);
} else {
point = newArray(2);
point[0] = neighborX;
point[1] = neighborY;
addToSelection(point, 100);
}
}
function addToQueue(x, y) {
queue = queue + x + "," + y + ";";
}
function alreadyTested(x,y) {
result = false;
selectImage(mask);
if (getPixel(x,y)==50 || getPixel(x,y)==100) result = true;
selectImage(inputImage);
return result;
}
25/26
Automation of image analysis tasks with ImageJ and MRI Cell Image Analyzer
slower when not in batch mode.
volker.baecker@mri.cnrs.fr
26/26