tl;dr I am looking for a short but complete example that shows how to apply an ImageJ filter to a Mathematica Image
through J/Link.
Fiji/ImageJ is one of the largest and most popular image processing tools. It is designed to be scriptable and can be used even interactively through a Jupyter notebook. It supports several languages such as Groovy/Python/Scala/R/Ruby/etc., but not Mathematica.
My aim is to use certain filters from ImageJ through the Ops framework. I am sure that this is possible through J/Link. Unfortunately, I don't know Java, and I'd need to go through many technical hurdles to get everything working.
I am looking for an answer that would get a typical Mathematica user (with no or minimal Java knowledge) through these technical hurdles. Assume that I downloaded the Fiji app and installed some plugins. What do I need to do to access a filter, such as median, from Mathematica, including setting up classpaths, (re)installing J/Link, and creating the required Java objects before I can call the necessary methods to run the filter?
The Groovy script to do this might look like this:
// Median filter.
median = ij.op().run("create.img", eyes32)
neighborhood = new HyperSphereShape(4)
ij.op().run("filter.median", median, eyes32, neighborhood)
Ideally, the ImageData
would be transferred from Mathematica (here it comes from the eyes32
variable which was earlier loaded from a file).
There is a closely related question on StackOverflow. My question is different because it is specifically about using the Ops API and avoiding writing and compiling Java code (if possible).
Update with current progress and issues:
The first step is to create the ij
object used in the tutorial notebooks.
Needs["JLink`"]
(* adjust the path to your Fiji *)
AddToClassPath@FileNames["/Users/szhorvat/Desktop/Fiji.app/jars/*"];
LoadJavaClass["com.wolfram.jlink.JLinkClassLoader"]
Issue 1: I can't include the crucial net.imagej.ImageJService
below without triggering an error.
context = JavaNew["org.scijava.Context",
JLinkClassLoader`classFromName /@ {
(* "net.imagej.ImageJService", *) (* including this results in an error about loading net.imagej.legacy.LegacyService — how can I fix this? *)
"net.imagej.ops.OpService",
"io.scif.SCIFIOService",
"org.scijava.io.IOService",
"org.scijava.app.StatusService"
}
]
ij = JavaNew["net.imagej.ImageJ", context]
(* JLink`Objects`vm1`JavaObject16280761535561729 *)
io = ij@io[]
(* JLink`Objects`vm1`JavaObject15342879492800513 *)
op = ij@op[]
(* JLink`Objects`vm1`JavaObject1760488337702913 *)
mandrill = io@open["http://imagej.net/images/baboon.jpg"]
(* JLink`Objects`vm1`JavaObject15612747035181057 *)
Issue 2: It is unclear to me why the following fails, even though Methods[op]
does list the run
and help
methods.
med = op@run["create.img", mandrill]
(* During evaluation of Java::nometh: No method named run defined in class net.imagej.ops.DefaultOpService. *)
(* $Failed *)
op@help["create.img"]
(* During evaluation of Java::nometh: No method named help defined in class net.imagej.ops.DefaultOpService. *)
(* $Failed *)
Final remaining task: 1. retrieve the image data from the mandrill
object 2. create a similar object directly from Mathematica using and Image
's ImageData
.