Using PyImageJ without a screen

It is an increasingly common scenario to want to do image processing on a cloud computing node (e.g. running notebooks on Binder or Google Colab). Unfortunately, the original ImageJ was only designed to be a GUI-based desktop application, so it does not natively support true headless operation, i.e. without a display attached.

Using ImageJ in headless mode

The ImageJ2 project supports headless operation for all its functions, due to its careful separation of concerns, and ImageJ2 includes a backwards compatibility layer that supports use some original ImageJ functionality while headless; the original ImageJ’s core classes are modified at runtime via Javassist.

For more information about running ImageJ and/or ImageJ2 in headless mode, please read the Running Headless and Scripting Headless pages of the ImageJ wiki.

Please note: Not all original ImageJ functions are accessible while headless: e.g., many methods of RoiManager and WindowManager do not work without a graphical environment. To work around this limitation, you can use Xvfb to run ImageJ inside a “virtual” graphical environment without a physical screen present.

Starting PyImageJ in headless mode

When you initialize PyImageJ with no arguments, it runs in headless mode by default:

import imagej
ij = imagej.init()

For clarity, you can explicitly specify headless mode by passing the mode='headless' setting:

ij = imagej.init(mode='headless')

Under the hood, the headless mode flag initializes the Java Virtual Machine with -Djava.awt.headless=true.

For more about PyImageJ initialization, see the Initialization guide.

Troubleshooting

See the Known Limitations section of the Troubleshooting guide for some further details about what does and does not work headless, and things to try when having difficulty with ImageJ’s behavior in headless mode.

Using PyImageJ with Xvfb

Workflows that require headless operation but also need to interact with ImageJ elements that are tied to the GUI, can be achieved with virtual displays. Using Xvfb we can create a virtual frame buffer for ImageJ’s GUI elemnts without displaying any screen output. On Linux systems that already have a graphical environment installed (e.g. GNOME), you only need to install xvfb.

$ sudo apt install xvfb

However on fresh Linux servers that do not have any installed environment (e.g. Ubuntu Server 20.04.3 LTS), additional X11 related packages will need to be installed for PyImageJ.

$ sudo apt install libxrender1 libxtst6 libxi6 fonts-dejavu fontconfig

After xvfb has been installed you can have xvfb create the virtual display for you and run a script with:

$ xvfb-run -a python script.py

Alternatively you can create the virtual frame buffer manually before you start your PyImageJ session:

$ export DISPLAY=:1
$ Xvfb $DISPLAY -screen 0 1400x900x16 &

In either case however, you need to initialize PyImageJ in interactive and not headless mode so the GUI can be created in the virtual display:

import imagej

ij = imagej.init(mode='interactive')

Headless Xvfb example

Here we have an example on how to run PyImageJ headlessly using imagej.init(mode='interactive') and Xvfb. In addition to Xvfb, you will also need to have scikit-image installed in your environment to run the doc/examples/blob_detection_xvfb.py example. The blob_detection_xvfb.py script is the headless version of the doc/examples/blob_detection_interactive.py example (please run blob_detection_interactive.py to view the scikit-image blob detection output).

The headless example opens the test_image.tif sample image, detects the blobs via scikit-image’s Laplacian of Gaussian algorithm, adds the blob detections to the ImageJ RoiManager, measures the ROIs and returns a panda’s dataframe of the measurement results. To run the example, run the following command to create the virtual frame buffer and run PyImageJ:

$ xvfb-run -a python blob_detection_xvfb.py

The script should print the results pandas dataframe (the data from ImageJ’s ResultsTable) with 187 detections.

log4j:WARN No appenders could be found for logger (org.bushe.swing.event.EventService).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
ImageJ2 version: 2.14.0/1.54f
Output:
         Area         Mean     Min     Max
0    1.267500  3477.416667  2219.0  5312.0
1    0.422500  2075.500000  1735.0  2529.0
2    0.422500  1957.750000  1411.0  2640.0
3    0.422500  1366.500000  1012.0  1913.0
4    0.422500  2358.500000  2100.0  2531.0
..        ...          ...     ...     ...
182  0.422500  1205.750000  1124.0  1355.0
183  7.288125  1362.840580   703.0  2551.0
184  0.422500   920.500000   830.0  1110.0
185  0.422500  1345.250000  1260.0  1432.0
186  0.422500  1097.250000   960.0  1207.0

[187 rows x 4 columns]