Está en la página 1de 26

Automation of image analysis tasks with ImageJ and MRI Cell Image Analyzer

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.

1.1 The ImageJ macro language Hello World


A short introduction to the ImageJ macro language can be found on
http://rsb.info.nih.gov/ij/developer/macro/macros.html and a list of functions available in the macro
language on http://rsb.info.nih.gov/ij/developer/macro/functions.html. As dictated by tradition, the
first thing we will do is to write a macro that prints out Hello World! .
Use Plugins>New to create a new macro. In the dialog enter the name Hello World and select
the type macro.

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!");
}

Text 1: The hello world


macro.
Let's add a second hello world macro that draws the text into an image. Edit the hello world file as
shown in Text 2.
macro "Hello World [f11]" {
print("Hello World!");
}
macro "Hello World 2 [f12]" {
newImage("Welcome", "8-bit White", 800, 150, 1);
setFont("Serif", 100, "antialiased");
setColor(255,255,0);
drawString("Hello world!", 150, 100);
}

Text 2: A graphical hello world has been added.


Save the new macro, install it and run it.

1.2 Integrating macros into the ImageJ interface.


1.2.1 Startup macros
Macros defined in the file StartupMacros.txt in the macros folder will be automatically installed
when ImageJ is started. They will appear in the Plugins>Macros menu and the keyboard shortcuts
will be working as well. Copy the two Hello World macros into the StartupMacros.txt file.
If StartupMacros.txt contains a macro named AutoRun, this macro will be automatically executed
each time ImageJ is started.
macro 'AutoRun' {
run("Hello World 2");
}

Text 3: Automatically running a


command when ImageJ starts up.

1.2.2 Macros as plugins


One way to add our macro command permanently to ImageJ is to add it as a plugin. Files that are in
the plugin folder or in one of its subfolders and that contain an underscore in their name are
regarded as plugins and appear in the Plugins menu. For this usage each macro has to be in its own
file and the shortcut keys defined within the macro are not taken into account. However a shortcut
for the plugin can be defined afterwards. Create a subfolder mri-workshop in the plugins folder,
create a file Hello_World.txt containing the first macro and a file Hello_World_2.txt containing the
second macro. After you restarted ImageJ you find a menu entry Plugins>mri-workshop containing
volker.baecker@mri.cnrs.fr

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.

1.2.3 Macros as menu items


Using the file IJProps.txt in the ij.jar in the ImageJ base-folder, you can change and add menu
items. You can modify the context menu that opens when you right-click on an image and almost
all submenus, like for example Process>Filters.
Make a copy of IJProps.txt with a different name. If after a modification of IJProps ImageJ doesn't
come up anymore you rename the copy back to IJProps.txt. Open the file IJProps.txt and try to
install the Hello World 2 macro in the File>New submenu. Be careful to give it a different name
from the name it has in the Plugins>MRI-workshop menu, otherwise you will create an endless
loop when you call it from its new place. The command you need, to call the macro is
ij.plugin.Hotkeys("Hello World 2"). The command names in the ImageJ menus must be unique,
since they can directly be called from a macro using the run command. If you want to place the
same command in different menus, you can add spaces behind the name for all but the first menu.

# Plugins installed in the File/New submenu


new01="Image...[n]",ij.plugin.Commands("new")
new02="Text Window[N]",ij.plugin.NewPlugin("text")
new03="Internal Clipboard",ij.plugin.Clipboard("show")
new04="System Clipboard[V]",ij.plugin.Clipboard("showsys")
new05=new06="Hello World 2 ",ij.plugin.Hotkeys("Hello World 2")

Text 4: Adding a command that calls a macro to the File>New menu.

volker.baecker@mri.cnrs.fr

5/26

Automation of image analysis tasks with ImageJ and MRI Cell Image Analyzer

Illustration 2: The macro command appears in the


File>New menu.

1.2.4 Calling macros from action bars


The Action Bar plugin from Jerome Mutterer
(http://imagejdocu.tudor.lu/Members/jmutterer/Action_Bar/) allows to create toolbars with custom
buttons for which the commands can be configured. Start it from Plugins>Action Bar>Action Bar.
Create an action bar with one row and two buttons. Use Hello_ as name of the action bar.

Illustration 3: The Action Bar plugin.


After you pressed OK the macro editor will be opened and you can edit the action bar.

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

icon = the icon image for the button

action = one of the following possibilities:

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)

run_macro_string (a macro command string)

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

Text 5: The definition of the Hello action bar.

Illustration 4:
The resulting
action bar.

Illustration 5: Another action bar.

1.2.5 Running macros from toolsets


The rightmost button in the ImageJ launcher window switches between different sets of tools that
can be activated or run using the buttons after the color picker tool. You can create your own
toolsets. Create a file Hello World.txt in the folder macros/toolsets. A toolset macro must either
contain Tool or Action Tool in its name. In the first case, if you click the button the current tool
changes and active tool is called each time the user clicks into an image. In the second case the
macro is called directly when the button is pressed. The name of the macro must be followed by a
volker.baecker@mri.cnrs.fr

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);
}

Text 6: Defining a toolset for the ImageJ toolbar.


Restart ImageJ and click on the >> button. You find a new menu item Hello World . Select it
and two buttons with the globe icon appear on the toolbar.

volker.baecker@mri.cnrs.fr

8/26

Automation of image analysis tasks with ImageJ and MRI Cell Image Analyzer

Illustration 6: The Hello World toolset appears in the ImageJ toolbar.

2. Writing an image type converter batch


Our first task will be to write an automatic image type converter. The converter shall take a folder
of 16-bit greyscale or RGB-color images as input and convert each image to an 8-bit greyscale
image.

2.1 Using the ImageJ macro language


2.1.1 Macro recorder and Multiple Image Processor
We first need to know the command to convert an image to 8bit. The macro recorder writes all
actions executed by ImageJ to a text file that you can install and run as a macro afterwards. Start the
recording from Plugins>Macros>Record. Open an rgb or 16-bit greyscale image and convert it to 8bit. In the recorder window you'll find the command run("8-bit");. Using the run command you can
call all ImageJ menu item commands from a macro.
Remove everything except for the convertion command from the recorder window. Enter the name
of the macro: Convert to 8-bit and press the create button. Revert the opened image (ctrl+r) and
run the macro from macros>run macro. If everything works as expected save the macro into the
macro folder.

Illustration 7: The convert to


8-bit macro.
You can now use the Multiple Image Processor plugin from
http://ciar.rcm.upr.edu/projects/imageprocessor/multiples to apply the macro to all images in a
folder. Run the plugin from plugins>utilities>Multiple Image Processor.

volker.baecker@mri.cnrs.fr

9/26

Automation of image analysis tasks with ImageJ and MRI Cell Image Analyzer

Illustration 8: The Multiple Image Processor


plugin.
Choose plant (manual) as input folder and work/out as output folder. Select the macro file and
press ok. Each image in the folder will be opened, displayed and converted and the result will be
written to the output folder.
The macro can of course contain any sequence of commands.

2.1.2 Programming the loop


We might need more control of the processing as is provided by the Multiple Image Processor .
We're going to write the processing loop for all images in a folder ourselves now.
inputFolder = getDirectory("8-bit converter - Choose the input folder!");
outputFolder = getDirectory("8-bit converter - Choose the output folder!");
images = getFileList(inputFolder);
for (i=0; i<images.length; i++) {
inputPath = inputFolder + images[i];
open(inputPath);
run("8-bit");
outputPath = outputFolder + images[i];
save(outputPath);
close();
}

Text 7: A first version of the convert to 8 bit macro.


We first need to get the input and output folders from the user. This can be done with the command
getDirectory(<String>). We will store the answers in the variables inputFolder and outputFolder.
Now we need a list of the files in the input folder. The command getFileList(<dir>) can be used to
get the list.
The for loop runs from 0 to the length of the list of images 1. In each iteration the variable i is
increased by one.
The operator +, if applied to strings, concatenates two strings. In this way the absolute path of the
current input image is constructed from the input folder and the filename.

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:

each opened image is displayed, which is useless in a batch application

if there is a file in the folder that is not an image the macro will stop with an error

we can't see the progress

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;
}

Text 9: A function to count the number of images in a list of filenames.


To solve the last problem we will print out the name of each written image to a log file that will be
opened after the processing of all images finished.

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.

2.2 Using MRI Visual Scripting


We will now create the same convert to 8-bit application using MRI Visual Scripting. Select the
MRI Tools toolset and click on the Visual Scripting button.

Illustration 9: The MRI Visual


Scripting launcher.
To create a new application run Applications>new... and enter the name of the new application. A
tile representation and a box representation of the application are opened. For the moment the box is
empty. Open the list of all available operations from Operations>all. Scroll down to the convert
image type operation and drag it from the box. Click on the questionmark to get a help text for the
operation. Drop it into the application box. Click on the O-button to see the options of the
operation. The only option is the output type. Add the open image operation before the convert
image operation. Click on the P-button of the convert image type operation to connect the input of
the operation wilth the output of the open image operation. Add a show image operation at the end
of the application and connect it, then run the application on an RGB image. To run an application
click on the central button with the applications's name in the tile-representation.
The application opens a file browser and asks the user for an image. It opens the image, converts it
to 8-bit and displays it.
Now we need to add a loop and instead of showing the result image we need to save it to disk.

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.

Illustration 10: The convert to 8-bit


application as a visual script.

3. Measuring intensities inside and outside a masked region


We will now create a macro that reads in two images. One image of nuclei and one image of the
cytoplasm. The macro will create a mask from the nuclei, subtract the background in the cytoplasm
image and measure the intensities inside and outside the nuclei in the cytoplasm image.
volker.baecker@mri.cnrs.fr

13/26

Automation of image analysis tasks with ImageJ and MRI Cell Image Analyzer
You will learn how to:

open multiple images belonging together

run visual scripting operations from a macro

use the particle analyzer from a macro

add entries to a results table

save measurement result in a way that they can be opened with a spreadsheet program
afterwards

3.1 Getting the basic steps from the macro recorder


We will execute the basic steps needed to accomplish our application and record them with the
macro recorder. You can fill in commands manually in the recorder window. You can create a
macro from the recorder window in between and run it to test your changes.
Start the macro recorder and open the image A4 dapi 1.tif . Open the threshold adjuster and
create a mask of the nuclei. For the script keep only the setAutoThreshold() and convert to mask
commands. Run fill holes to get rid of the holes in the mask. Then run the particle analyzer
to exclude the small object that is not a nucleus. Don't display the results, we are only interested in
the new mask in which objects too small are excluded. Create a selection from the mask.
Open the image A4 Rhod 1.tif . Run the find and subtract background operation. Remark that
this generates a call command in the macro recorder. The call command can be used to call any
static public java method.
call("operations.Operation.run", "find and subtract
background", "1; 1; 2; 0.05");

Text 11: Visual scripting operations are run by the call


command.
Transfer the selection to that image. Set the measurements, so that they include the integrated
density and the area and measure the selection. Invert the selection an measure again.
Now we did all the steps to get the informations we wanted.

3.2 Resetting the results table


Since later on we will build a loop to treat multiple images around our code, we should put the set
measurements command to the very top of the macro, so that it will only be run once before the
loop is entered. When the macro is run it will add measurements to a opened results table. So we
should clear the results table before writing measurements into it. To clear a results table manually
use Edit>Clear Results in the window of the results table.
run("Set Measurements...", "area mean min integrated redirect=None
decimal=3");
run("Clear Results");

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

3.3 Adding the loop and loading images belonging together


The next thing we are going to change is to add the loop to treat all images in a folder. Since now
we need two images, the nuclei and the cytoplasm, we will automatically read in the cytoplasm
image for each nuclei image.
We define two variables containing the part of the filename that identifies an image as nuclei or
cytoplasm image. Then we ask the user for the source folder. We get the file list of all files in the
source folder. Using the keyword var we define the filelist as a global variable. This way it is
directly accessible everywhere and we don't need to pass it as an argument to a function. Write a
function that counts the number of nuclei images and a function that answers an array of all images
containing a text in the name. Use the second function to get a list of all nuclei images.
nucleiName = "dapi";
cytoplasmName = "Rhod";
inputFolder = getDirectory("8-bit converter - Choose the input folder!");
var allImages;
allImages = getFileList(inputFolder);
var numberOfImages = 0;
numberOfImages = countNucleiImages();
nucleiImages = getImagesContaining(nucleiName);

Text 13: Getting a list of the nuclei images.


function countNucleiImages() {
count = 0;
for(i=0; i<allImages.length; i++) {
if (indexOf(allImages[i], nucleiName) !=-1 )
count++;
}
return count;
}

Text 14: Counting the nuclei images.


function getImagesContaining(text) {
result = newArray(numberOfImages);
index = 0;
for (i=0; i<allImages.length; i++) {
if (indexOf(allImages[i], text) != -1) {
result[index] = allImages[i];
index++;
}
}
return result;
}

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");
}

Text 16: The main processing loop.

3.4 Closing images no longer needed and freeing memory


To save memory we should close image no longer needed as soon as possible. ImageJ always works
on the active image. To apply a command to another image we can get the ID of the currently active
image with the command getImageID() . The command selectImage(id) makes the image with the
given id the active image.
Use call("java.lang.System.gc"); to initiate a garbage collection that frees memory no longer used.
This call should be the first command in the loop.

3.5 Saving the results


To save the results table we first ask the user for the output folder in the beginning of the macro.
Then when the measurements have been made the results table can be selected with
selectWindow("Results");. The results can be saved as a text file using saveAs("Measurements", ""
+ outputFolder + "results.txt");. The content will be tab separated and can be loaded into a
spreadsheet program.
selectWindow("Results");
saveAs("Measurements", "" + outputFolder + "results.txt");

Text 17: Saving the results table.


Instead of saving the results table we can write a custom report. Let us write a function that writes a
report containing:

the name of the image

the total intensity within the nuclei

the total intensity within the cytoplasm

the ratio of the two intensities

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);
}

Text 18: A function that writes a custom report.

4. Interactive visual scripts


Let us see how to put some interactivity into a visual script. We want to open a list of images one
after the other. Let the user make a rectangular selection. Threshold the region within the selection
and set find all objects in this region. The objects should be marked with a point selection. Then the
user should have the possibility to correct the point selection and to accept or reject the result.

volker.baecker@mri.cnrs.fr

17/26

Automation of image analysis tasks with ImageJ and MRI Cell Image Analyzer

Illustration 11: An interactive application.


You can use show results table instead of report measurements if you want to see the result
directly instead of writing it to a file.

5. Measuring perpendicular segments along a line


Let the user make a line selection and enter a distance d and a length l. The macro shall create line
selections in the distance d of length l along the firsth line selection and measure the intensities of
these line selections.
You will learn how to

get user input for a macro

create selections (rois) from a macro

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).

Turn the new line segment around 0,0 by 90 + alpha.

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;

newPerpendicularLineSeg(x1, y1, x2, y2, radius);


drawLine(segXs,segYs, segXe, segYe);
updateDisplay() ;
exit();
function newPerpendicularLineSeg(xs, ys, xe, ye, radius) {
// create segment with middle point in 0,0, horizontal to x-axis
segXs
segYs
segXe
segYe

=
=
=
=

- radius;
0;
radius;
0;

// calculate angle alpha of line selection


m = (ye-ys) / (xe-xs);
alpha = atan(m);
// make new line segment perpendicular to line selection
angle = alpha + (pi/2);
segXsNew = cos(angle) *
segYsNew = sin(angle) *
segXeNew = cos(angle) *
segYeNew = sin(angle) *

segXs
segXs
segXe
segXe

+
+

sin(angle)
cos(angle)
sin(angle)
cos(angle)

*
*
*
*

segYs;
segYs;
segYe;
segYe;

// move new line segment to start point of line selection


segXs
segYs
segXe
segYe

=
=
=
=

segXsNew
segYsNew
segXeNew
segYeNew

+
+
+
+

xs;
ys;
xs;
ys;

Text 20: Creating a line segment perpendicular to the line selection.


Now we are going to move the line segment along the line selection in steps of the given distance
until we get behind the end of the line selection. We will write a function that moves the segment by
a given distance along the line selection. Then we will create a loop that runs while the segment and
the line selection intersect.

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 22: Test if the segment intersects the line selection.


newPerpendicularLineSeg(x1, y1, x2, y2, radius);
while(intersects(x1, y1, x2, y2)) {
drawLine(segXs,segYs, segXe, segYe);
updateDisplay() ;
moveLineSeg(x1, y1, x2, y2, distance);
}
exit();

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();

Text 24: A dialog to read in distance and radius.


To replace the drawing with the ceation of a selection use makeLine. Then instead of measuring
directly we add each selection to the roi manager. The user can then decide to measure them, to
draw them, to save them and so on. This is done with the command roiManager( Add );.

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.

6. Writing a 2d region growing segmentation tool macro


We want to create a tool that lets the user click on a point in the image and creates a selection
around this point by iteratively adding points for which the intensity doesn't differ more than a
threshold value from the current average intensity in the already selected region.
We will create the macro as a tool macro. The threshold delta value can be set by the user as an
option of the macro. We will use a data structure called a queue to manage the points for which the
neighbors have still to be checked. A queue is a structure where entries are consumed from one side
while new entries are added at the other side. We will mark the points added to the selection and the
points already rejected in a temporary image that we call mask. We count the current iteration of the
algorithm. We want use it, however a more sophisticated region growing could change the threshold
delta as a function of the iteration.
We declare the global variables to keep the described data.
var
var
var
var
var
var
var

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;
}

Text 27: Initailizing the global variables.


Remark that we do not initialize the threshold in the initialize method. The threshold will per
volker.baecker@mri.cnrs.fr

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();

Text 29: First part of the region growing macro.


Grow region will run as long as there are points in the queue left. If a point is in the queue his
neighbors still have to be examined. To give a sign of life while the macro is running we write the
current lengths of the queue to the status bar of the ImageJ launcher window.
Using the split function, we get the first point as an array of the x and y coordinates from the queue.
Using further string functions the first point is removed from the queue in the function
removeFirst(). We add the point to the result region. To do so we mark the pixel with the value 50
in the mask. We increment the region size and update the current average. We get the intensity of
the point with the function getPixel(<x>,<y>);. Then we call the function testAndAddNeighbors
for each of the 4-connected neighbors of the pixel.

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;
}

Text 31: The testAndAddNeighbor function.


Finally we threshold the mask image to get only the pixel with intensity 50. We fill holes in the
mask so that regions totally surrounded by our result region will be added to the result region. Then
we create a selection from the mask and transfer it to the input image.
selectImage(mask);
setThreshold(50, 50);
run("Convert to Mask");
run("Fill Holes");
run("Create Selection");
close();
run("Restore Selection");
setBatchMode(false);
}

Text 32: The second half of the region growing macro.


Try to run it with different threshold values on the image cells.tif. Remark that threshold values can
be floating point numbers in this case.
Change the macro to see what happens on the mask while it is created. The macro will run much
volker.baecker@mri.cnrs.fr

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

También podría gustarte