This file covers some common use cases of PyImageJ. If you still have questions, the Scientific Community Image Forum is the best place to get general help, ImageJ advice, and any other image processing tasks. Bugs can be reported to the PyImageJ GitHub issue tracker.
The ImageJ gateway is the object interface that lets you use ImageJ (see INITIALIZATION.md). This
gateway contains all of the regular ImageJ Java functions. PyImageJ also adds a module of convenience functions under
ij.py
For example, converting a numpy array to an ImageJ2 dataset.
import imagej
import numpy
array = numpy.random.rand([5, 4, 3])
ij = imagej.init()
dataset = ij.py.to_java(array)
Converting between Java and Python is done using the ij.py.to_java()
and ij.py.from_java()
functions. A table of
common data types and their converted values is listed below.
Python object | Java Object |
---|---|
numpy.ndarray |
net.imglib2.python.ReferenceGuardingRandomAccessibleInterval |
xarray.DataArray |
net.imagej.Dataset |
str |
java.lang.String |
int |
java.lang.Integer |
float |
java.lang.Float |
list |
java.util.ArrayList |
dict |
java.util.LinkedHashMap |
tuple |
java.util.ArrayList |
The function to_java
is capable of converting common Python and numpy data types into their Java/ImageJ equivalent.
There is one important nuance; converting a numpy.ndarray
or xarray.DataArray
to java creates a java object that
points to the numpy array. This means that changing the java object also changes the numpy array.
Let's take a look at lists as an example. Lists are not linked.
import imagej
ij = imagej.init()
ex_list = [1, 2, 3, 4]
java_list = ij.py.to_java(ex_list)
ex_list[0] = 4
print(java_list[0]) # This will still equal 1!
By contrast, ops can operate on numpy arrays and change them, though you need to wrap the arrays in to_java
first.
import numpy as np
arr1 = np.array([[1, 2], [3, 4]])
arr2 = np.array([[5, 6], [7, 8]])
arr_output = ij.py.new_numpy_image(arr1)
ij.op().run('multiply', ij.py.to_java(arr_output), ij.py.to_java(arr1), ij.py.to_java(arr2))
print(arr_output) # This output will be [[5, 12], [21, 32]]!
Working with ImageJ2 ops may require casting your data to different data structures in order to send it through the op. See this tutorial notebook for several examples of op usage and how to troubleshoot.
In order to use ImageJ1 macros, plugins, or other code you must initiate ImageJ with legacy supported. If in doubt,
you can check the ij.legacy().isActive()
function to see if your initialization worked properly. See
Initialization.md for a how-to on starting up PyImageJ with legacy support.
In order to use windows, you must also initialize PyImageJ with headless=False
. To work with windows, you can
either use the convenience functions available in ij.py
, use the
ImageJ2 WindowService through ij.window()
or if you are in legacy mode you can get the ImageJ1 ij.WindowManager
using the ij.py.window_manager()
function.
See the WindowManager Javadoc for the full
function list.
Current convenience functions include active_image_plus
to get the ij.ImagePlus
from the current window and
active_xarray
to convert the current window into an xarray.DataArray
.
You can also use synchronize_ij1_to_ij2
to synchronize the current data structures. See
Troubleshooting.md for an explanation of when this is needed.
You can get a list of active IJ2 windows with the following command
ij.window().getOpenWindows()
You can close any IJ2 windows through the following command.
ij.window().clear()
Running an IJ1 style macro is as simple as providing the macro code in a string and the arguments in a dictionary to
run_macro
. Modify the following code to print your name, age, and city.
import imagej
ij = imagej.init(['net.imagej:imagej', 'net.imagej:imagej-legacy'])
macro = """
#@ String name
#@ int age
#@ String city
#@output Object greeting
greeting = "Hello " + name + ". You are " + age + " years old, and live in " + city + "."
"""
args = {
'name': 'Chuckles',
'age': 13,
'city': 'Nowhere'
}
result = ij.py.run_macro(macro, args)
print(result.getOutput('greeting')) # Prints: Hello Chuckles. You are 13 years old, and live in Nowhere.
Running scripts in other languages is similar, but you also have to specify the file extension for the scripting language it is written in.
import imagej
ij = imagej.init(['net.imagej:imagej', 'net.imagej.:imagej-legacy'])
language_extension = 'ijm'
result_script = ij.py.run_script(language_extension, macro, args)
print(result_script.getOutput('greeting'))
Finally, running plugins works in the same manner as macros. You simply enter the plugin name as a string and the
arguments in a dict. For the few plugins that use IJ2 style macros (i.e., explicit booleans in the recorder), set the
optional variable ij1_style=False
.
Here is an example of using the "Mean" plugin to blur an image:
import imagej
ij = imagej.init('sc.fiji:fiji:2.0.0-pre-10')
ij.py.run_macro("""run("Blobs (25K)");""")
blobs = ij.py.active_image_plus()
ij.py.show(blobs)
plugin = 'Mean'
args = {
'block_radius_x': 10,
'block_radius_y': 10
}
ij.py.run_plugin(plugin, args)
imp = ij.py.active_image_plus()
ij.py.show(imp)
This can be used to determine the dimensions of a numpy or ImageJ image:
import imagej
import numpy as np
ij = imagej.init()
# numpy image
arr = np.zeros([10, 10])
print(ij.py.dims(arr)) # (10, 10)
# imagej image
img = ij.py.to_java(arr)
print(ij.py.dims(img)) # [10, 10]
Takes a single image argument, which can either be a numpy image or an imagej image
# create a new numpy image from a numpy image
arr2 = ij.py.new_numpy_image(arr)
print(type(arr2)) # <class `numpy.ndarray`>
# create a new numpy image from an imagej image
arr3 = ij.py.new_numpy_image(img)
print(type(arr3)) # <class `numpy.ndarra`>