Text overlay in Python for imagej

Hello! I need to transform the following 2 lines from imagej macro into python script and I cannot find a solution…

Blockquote
setFont(“Sanserif”, 8, “bold”)
makeText(“Test text”, 0, 0)

I tried to use this as a reference “https://imagej.nih.gov/ij/macros/python/Create_Overlay.py
but I’m failing to import what is needed and it simply cannot make it work…

This is again another nice example for the situation that Scripting is much closer to Java than ImageJ-macro coding:

You have to search/find the relevant parts of the API:
https://imagej.nih.gov/ij/developer/api/index.html

Good luck

Herbie

This is what I get when I use the text tool to display a line of text and add it to an overlay with the recorder running in “JavaScript” mode:

  overlay = new Overlay();
  imp = IJ.createImage("Untitled", "8-bit black", 300, 200, 1);
  font = new Font("SansSerif", Font.PLAIN, 18);
  roi = new TextRoi(50, 50, "Some Text", font);
  roi.setStrokeColor(new Color(1.00, 1.00, 1.00));
  overlay.add(roi);
  imp.setOverlay(overlay);
  imp.show();
  IJ.run("List Elements", "");

This is the Python version:

overlay = Overlay()
imp = IJ.createImage("Untitled", "8-bit black", 300, 200, 1)
font = Font("SansSerif", Font.PLAIN, 18)
roi = TextRoi(50, 50, "Some Text", font)
roi.setStrokeColor(Color(1.00, 1.00, 1.00))
overlay.add(roi)
imp.setOverlay(overlay)
imp.show()
IJ.run("List Elements", "")

It runs in ImageJ but not in the Fiji Script Editor, even with Edit>Auto-import enabled.

Screenshot

Hello Kiostra -

Let me answer in terms of the example jython (python) script you
linked to.

First, ImageJ is written in java so (almost) everything is done with
java classes and their methods.

Second, jython has direct access to ImageJ’s java classes, so
scripting in jython means using jython for the scaffolding and
simple (and potentially complicated) logic, but using instances
of java classes (and static methods) for the “real” work.

Third, jython, unlike java, is a weakly-typed (and duck-typed)
language so (unlike java) you only need to explicitly import
classes that you directly reference. But you do need to
import those. Just calling a method of an instance of a class
is not enough to require importing that class.

If you copy the example script you linked to, Create_Overlay.py,
into the Script Editor (File > New > Script...), and try to run
it you will get NameErrors for the classes that are referred to
directly, but not imported.

(I recall reading somewhere that in an older version of ImageJ some
(or all) of the ImageJ classes were automatically imported into jython
scripts, so maybe the example script used to work “out of the box”.)

If we scan through the script to look for possibly required imports, we
first come to IJ. To flesh out a little Herbie’s advice to search the API,
here’s one way to go about it:

A google search for

brings up (for me, the first result):

https://imagej.nih.gov/ij/developer/api/ij/IJ.html

The class IJ is in the package ij, so we need to add to the jython script:

from ij import IJ

The next directly-referenced class is Overlay. From its javadoc, we
see that it is in package ij.gui, so we add:

from ij.gui import Overlay

Next up: Font. But ImageJ doesn’t have a Font class. So, patience.

Next, TextRoi: From its javadoc:

https://imagej.nih.gov/ij/developer/api/ij/gui/TextRoi.html

we see that it is also in package ij.gui.
So:

from ij.gui import TextRoi

We also see that TextRoi's constructor takes a java.awt.Font,
so we also add:

from java.awt import Font

(Rather than manually scanning through the script to find the
classes you need import, you could also just keep trying to run
the script and fix the NameErrors reported by the jython
interpreter.)

Going through Create_Overlay.py and systematically adding
all of the necessary imports, we get this complete, runnable
script that you can paste into the Script Editor and run.
(You need to set the Script Editor’s language to Python.)

# This script demonstrates how to use an Overlay to display
# graphics and text non-destructively on an image.

# import statements added to the original

from ij import IJ
from ij.gui import Overlay
from java.awt import Font
from ij.gui import TextRoi
from java.awt import Color
from ij.gui import Roi
from ij.gui import OvalRoi
from ij.gui import Line
from ij.gui import PolygonRoi

# from ij.gui import *

imp = IJ.openImage("http://imagej.nih.gov/ij/images/blobs.gif")
overlay = Overlay()
font = Font("SanSerif", Font.PLAIN, 28)
roi = TextRoi(10, 5, "This is an overlay", font)
roi.setStrokeColor(Color.yellow)
roi.setFillColor(Color(0,0,0,0.5))  
overlay.add(roi)
roi = Roi(30,70,200,150)
roi.setStrokeColor(Color.blue)
roi.setFillColor(Color(0,0,1,0.3))
overlay.add(roi)
roi = OvalRoi(60,60,140,140)
roi.setStrokeColor(Color.green)
roi.setStrokeWidth(15)
overlay.add(roi)
roi = Line(30,70,230,230)
roi.setStrokeColor(Color.red)
roi.setStrokeWidth(18)
overlay.add(roi)
x = [18,131,148,242]
y = [167,104,232,172]
roi = PolygonRoi(x, y, len(x), Roi.POLYLINE)
roi.fitSpline()
roi.setStrokeColor(Color.blue)
roi.setStrokeWidth(12)
imp.setRoi(roi)
overlay.add(roi)
imp.setOverlay(overlay)
imp.show()

Do note that the variable imp is an instance of the class
ImagePlus. But because we don’t ever refer directly
to this class, we do not need:

from ij import ImagePlus

I’ve also illustrated a convenience. You can uncomment
the commented line:

# from ij.gui import *

This imports everything from package ij.gui (but not its subpackages),
so you can then remove all of the other

from ij.gui import ...

lines.

Thanks, mm

2 Likes