Welcome to the ImageJ tutorial series. These notebooks offer a hands-on series of lessons for learning ImageJ.
For a quick demo of what ImageJ can do, ___just scroll down___!
To dive in to the tutorials, click the links below. If ImageJ is new to you, please try the "Using ImageJ" notebooks first.
For a thorough academic overview of the ImageJ software stack, including its features, history, motivation and goals, see:
Rueden CT et al. "ImageJ2: ImageJ for the next generation of scientific image data." BMC Bioinformatics 18:529 (29 November 2017).
Learn more about ImageJ at imagej.net. Learn more about Jupyter Notebook at jupyter.org.
See also scikit-image tutorial notebooks and SimpleITK tutorial notebooks.
Feedback is very welcome! Please share your ideas on the ImageJ Forum!
The first section is only necessary if you want to run ImageJ commands from Jupyter notebooks. In order to run the notebook, please install Anaconda from its website. Afterwards, please install the BeakerX kernel from the Anaconda command line:
conda install -c conda-forge ipywidgets beakerx
Find out more about BeakerX
If you are running from within the ImageJ/Fiji script editor, you don't need the first code snippet. It is to tell the notebook to download and install ImageJ from the remote repository.
%classpath config resolver imagej.public https://maven.imagej.net/content/groups/public
%%classpath add mvn
net.imagej imagej 2.0.0-rc-71
net.imagej imagej-notebook 0.7.1
Added new repo: imagej.public
Now that ImageJ functionality is available to the notebook, we create an ImageJ gateway.
In order to use ImageJ, you need a variable ij
which offers you all the functionality. In ImageJs script editor, just add a line
#@ ImageJ ij
In Jupyter notebooks, you can call this:
ij = new net.imagej.ImageJ()
"ImageJ v${ij.getVersion()} is ready to go."
ImageJ v2.0.0-rc-71 is ready to go.
For further details, see the Fundamentals of ImageJ notebook.
You can open images from local files as well as remote URLs.
// image = ij.io().open("https://imagej.net/images/lymp.tif")
image = ij.io().open("C:/structure/data/lymp.tif")
histogram = ij.op().image().histogram(image)
binaryImage = ij.op().threshold().huang(image)
import net.imglib2.algorithm.labeling.ConnectedComponents;
ij.op().labeling().cca(image, ConnectedComponents.StructuringElement.EIGHT_CONNECTED);
java.lang.IllegalArgumentException: Unsupported image type: net.imglib2.roi.labeling.LabelingType at net.imagej.notebook.image.RAIToHTMLConverter.lambda$convert$0(RAIToHTMLConverter.java:71) at net.imagej.notebook.DefaultNotebookService.lambda$initialize$3(DefaultNotebookService.java:107) at net.imagej.notebook.BeakerX$1.display(BeakerX.java:64) at jupyter.Displayers.display(Displayers.java:62) at com.twosigma.beakerx.MIMEContainerFactory.createMIMEContainersFromObject(MIMEContainerFactory.java:84) at com.twosigma.beakerx.MIMEContainerFactory.createMIMEContainers(MIMEContainerFactory.java:46) at com.twosigma.beakerx.kernel.msg.MessageCreator.createFinishResult(MessageCreator.java:265) at com.twosigma.beakerx.kernel.msg.MessageCreator.createFinish(MessageCreator.java:181) at com.twosigma.beakerx.kernel.msg.MessageCreator.createMessage(MessageCreator.java:172) at com.twosigma.beakerx.kernel.threads.ExecutionResultSender.update(ExecutionResultSender.java:45) at com.twosigma.beakerx.jvm.object.SimpleEvaluationObject.finished(SimpleEvaluationObject.java:72) at com.twosigma.beakerx.kernel.CodeFrame.handleResult(CodeFrame.java:40) at com.twosigma.beakerx.kernel.PlainCode.executeLastFrame(PlainCode.java:50) at com.twosigma.beakerx.kernel.Code.execute(Code.java:90) at com.twosigma.beakerx.kernel.handler.ExecuteRequestHandler.handleMsg(ExecuteRequestHandler.java:63) at com.twosigma.beakerx.kernel.handler.ExecuteRequestHandler.handle(ExecuteRequestHandler.java:51) at com.twosigma.beakerx.kernel.handler.ExecuteRequestHandler.handle(ExecuteRequestHandler.java:39) at com.twosigma.beakerx.socket.KernelSocketsZMQ.handleShell(KernelSocketsZMQ.java:195) at com.twosigma.beakerx.socket.KernelSocketsZMQ.run(KernelSocketsZMQ.java:170)
eyes32 = ij.op().convert().float32(eyes)
eyes.firstElement().getClass().getName()
net.imglib2.type.numeric.integer.UnsignedByteType
eyes32.firstElement().getClass().getName()
net.imglib2.type.numeric.real.FloatType
import net.imglib2.algorithm.neighborhood.HyperSphereShape
median = ij.op().run("create.img", eyes32)
neighborhood = new HyperSphereShape(4)
ij.op().run("filter.median", median, eyes32, neighborhood)
dogFormula = "gauss(image, sigma1) - gauss(image, sigma2)"
dog = ij.op().eval(dogFormula, [
"image": eyes32,
"sigma1": [20, 20],
"sigma2": [4, 4]
])
topHat = ij.op().morphology().topHat(eyes, [neighborhood])
blackTopHat = ij.op().morphology().blackTopHat(eyes, [neighborhood])
ij.notebook().display(["median":median, "topHat":topHat, "blackTopHat":blackTopHat])
median | |
topHat | |
blackTopHat |
ij.notebook().display([["median":median, "topHat":topHat, "blackTopHat":blackTopHat]])
median | topHat | blackTopHat |
---|---|---|
Define a lowpass filtering function, operating in the Fourier domain:
import net.imglib2.util.Util
lowpass = { fft, radius ->
// Declare an array to hold the current position of the cursor.
pos = new long[fft.numDimensions()]
// Define origin as 0,0.
long[] origin = [0, 0]
// Define a 2nd 'origin' at bottom left of image.
// This is a bit of a hack. We want to draw a circle around the origin,
// since the origin is at 0,0 - the circle will 'reflect' to the bottom.
long[] origin2 = [0, fft.dimension(1)]
// Loop through all pixels.
cursor = fft.localizingCursor()
while (cursor.hasNext()) {
cursor.fwd()
cursor.localize(pos)
// Calculate distance from 0,0 and bottom left corner
// (so we can form the reflected semi-circle).
dist = Util.distance(origin, pos)
dist2 = Util.distance(origin2, pos)
// If distance is above radius (cutoff frequency) set value of FFT to zero.
if (dist > radius && dist2 > radius)
cursor.get().setZero()
}
}
script1555623045556$_run_closure1@32f8615d
Perform a fast Fourier transform (FFT) on the image, run the lowpass filter, then invert the FFT:
import net.imglib2.type.numeric.real.FloatType
// Perform fft of the input.
fft = ij.op().filter().fft(image)
// Filter it.
lowpass(fft, radius=10)
// Reverse the FFT.
inverse = ij.op().run("create.img", image, new FloatType())
ij.op().filter().ifft(inverse, fft)
// Display the result.
ij.notebook().display([["image":image, "lowpass":inverse]])
image | lowpass |
---|---|