{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# ImageJ Tutorials and Demo\n",
"\n",
"Welcome to the ImageJ tutorial series. These notebooks offer a hands-on series of lessons for learning ImageJ.\n",
"\n",
"* For a quick demo of what ImageJ can do, ___just scroll down___!\n",
"\n",
"* To dive in to the tutorials, click the links below. If ImageJ is new to you, please try the \"Using ImageJ\" notebooks first.\n",
"\n",
"* For a thorough academic overview of the ImageJ software stack, including its features, history, motivation and goals, see:\n",
" > Rueden CT et al. \"[ImageJ2: ImageJ for the next generation of scientific image data](https://doi.org/10.1186%2Fs12859-017-1934-z).\" _BMC Bioinformatics_ __18:529__ (29 November 2017).\n",
" \n",
"* Learn more about ImageJ at [imagej.net](https://imagej.net/). Learn more about Jupyter Notebook at [jupyter.org](https://jupyter.org/).\n",
" \n",
"* See also [scikit-image tutorial notebooks](https://github.com/scikit-image/skimage-tutorials) and [SimpleITK tutorial notebooks](https://github.com/InsightSoftwareConsortium/SimpleITK-Notebooks).\n",
"\n",
"Feedback is very welcome! Please share your ideas on the [Image.sc Forum](https://forum.image.sc/)!"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"
\n",
"\n",
"
\n",
"
Using ImageJ
\n",
"
\n",
" - Fundamentals of ImageJ
\n",
" - ImageJ Ops
\n",
" - ImgLib2 Basics
\n",
" - Tables
\n",
" - Mixed World: Using ImageJ 1.x
\n",
" - ImageJ with Python Kernel
\n",
" - Calling Scripts from Scripts
\n",
"
\n",
"
\n",
"
\n",
"
Extending ImageJ
\n",
"
\n",
" - IOPlugins - Data Input and Output
\n",
" - Ops - Image Algorithms
\n",
"
\n",
"
Advanced Topics
\n",
"
\n",
" - SciJava in Detail
\n",
" - ImgLib2 in Detail
\n",
" - Using Special Ops
\n",
"
\n",
"
\n",
"
\n",
""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## ImageJ Demo"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"First, we tell the notebook to download and install ImageJ from the remote repository."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"scrolled": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Added new repo: scijava.public\n"
]
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "",
"version_major": 2,
"version_minor": 0
},
"method": "display_data"
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "95ac493c-41e0-4cfb-8108-4817ef4fe78b",
"version_major": 2,
"version_minor": 0
},
"method": "display_data"
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"%classpath config resolver scijava.public https://maven.scijava.org/content/groups/public\n",
"%%classpath add mvn\n",
"net.imagej imagej 2.0.0-rc-71\n",
"net.imagej imagej-notebook 0.7.1"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now that ImageJ functionality is available to the notebook, we create an ImageJ gateway."
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"scrolled": true
},
"outputs": [
{
"data": {
"text/plain": [
"ImageJ v2.0.0-rc-71 is ready to go."
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"ij = new net.imagej.ImageJ()\n",
"\"ImageJ v${ij.getVersion()} is ready to go.\""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"For further details, see the [Fundamentals of ImageJ](1-Using-ImageJ/1-Fundamentals.ipynb) notebook."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Load an image"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"You can open images from local files as well as remote URLs."
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"scrolled": false
},
"outputs": [
{
"data": {
"text/html": [
""
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"image = ij.io().open(\"https://imagej.net/images/lymp.tif\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Compute histogram"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
""
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"histogram = ij.op().image().histogram(image)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### N-dimensional crop"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[INFO] Populating metadata\n"
]
},
{
"data": {
"text/html": [
""
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"mandrill = ij.io().open(\"https://imagej.net/images/baboon.jpg\")"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
""
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"import net.imglib2.FinalInterval\n",
"min = [85, 0, 110]\n",
"len = [5, 335, 1]\n",
"bounds = FinalInterval.createMinSize(min[0], len[0], min[1], len[1], min[2], len[2])\n",
"eyes = ij.op().transform().crop(mandrill, bounds, true)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Type conversion"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
""
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"eyes32 = ij.op().convert().float32(eyes)"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"net.imglib2.type.numeric.integer.UnsignedByteType"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"eyes.firstElement().getClass().getName()"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"net.imglib2.type.numeric.real.FloatType"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"eyes32.firstElement().getClass().getName()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Median filter with circular neighborhood"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
""
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"import net.imglib2.algorithm.neighborhood.HyperSphereShape\n",
"median = ij.op().run(\"create.img\", eyes32)\n",
"neighborhood = new HyperSphereShape(4)\n",
"ij.op().run(\"filter.median\", median, eyes32, neighborhood)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Difference of Gaussians formula"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
""
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"dogFormula = \"gauss(image, sigma1) - gauss(image, sigma2)\"\n",
"dog = ij.op().eval(dogFormula, [\n",
" \"image\": eyes32,\n",
" \"sigma1\": [20, 20],\n",
" \"sigma2\": [4, 4]\n",
"])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Grayscale morphology operators"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
""
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"topHat = ij.op().morphology().topHat(eyes, [neighborhood])"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
""
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"blackTopHat = ij.op().morphology().blackTopHat(eyes, [neighborhood])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Display multiple images at once"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
""
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"ij.notebook().display([\"median\":median, \"topHat\":topHat, \"blackTopHat\":blackTopHat])"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
""
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"ij.notebook().display([[\"median\":median, \"topHat\":topHat, \"blackTopHat\":blackTopHat]])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Fourier transform with lowpass filter"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Define a lowpass filtering function, operating in the Fourier domain:"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"script1555623045556$_run_closure1@32f8615d"
]
},
"execution_count": 16,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"import net.imglib2.util.Util\n",
"\n",
"lowpass = { fft, radius ->\n",
" // Declare an array to hold the current position of the cursor.\n",
" pos = new long[fft.numDimensions()]\n",
"\n",
" // Define origin as 0,0.\n",
" long[] origin = [0, 0]\n",
"\n",
" // Define a 2nd 'origin' at bottom left of image.\n",
" // This is a bit of a hack. We want to draw a circle around the origin,\n",
" // since the origin is at 0,0 - the circle will 'reflect' to the bottom.\n",
" long[] origin2 = [0, fft.dimension(1)]\n",
"\n",
" // Loop through all pixels.\n",
" cursor = fft.localizingCursor()\n",
" while (cursor.hasNext()) {\n",
" cursor.fwd()\n",
" cursor.localize(pos)\n",
"\n",
" // Calculate distance from 0,0 and bottom left corner\n",
" // (so we can form the reflected semi-circle).\n",
" dist = Util.distance(origin, pos)\n",
" dist2 = Util.distance(origin2, pos)\n",
"\n",
" // If distance is above radius (cutoff frequency) set value of FFT to zero.\n",
" if (dist > radius && dist2 > radius)\n",
" cursor.get().setZero()\n",
" }\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Perform a fast Fourier transform (FFT) on the image, run the lowpass filter, then invert the FFT:"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {
"scrolled": false
},
"outputs": [
{
"data": {
"text/html": [
"image | lowpass |
---|
| |
"
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"import net.imglib2.type.numeric.real.FloatType\n",
"\n",
"// Perform fft of the input.\n",
"fft = ij.op().filter().fft(image)\n",
"\n",
"// Filter it.\n",
"lowpass(fft, radius=10)\n",
"\n",
"// Reverse the FFT.\n",
"inverse = ij.op().run(\"create.img\", image, new FloatType())\n",
"ij.op().filter().ifft(inverse, fft)\n",
"\n",
"// Display the result.\n",
"ij.notebook().display([[\"image\":image, \"lowpass\":inverse]])"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Groovy",
"language": "groovy",
"name": "groovy"
},
"language_info": {
"codemirror_mode": "groovy",
"file_extension": ".groovy",
"mimetype": "",
"name": "Groovy",
"nbconverter_exporter": "",
"version": "2.5.6"
},
"toc": {
"base_numbering": 1,
"nav_menu": {},
"number_sections": true,
"sideBar": true,
"skip_h1_title": true,
"title_cell": "Table of Contents",
"title_sidebar": "Contents",
"toc_cell": false,
"toc_position": {
"height": "calc(100% - 180px)",
"left": "10px",
"top": "150px",
"width": "307px"
},
"toc_section_display": true,
"toc_window_display": true
}
},
"nbformat": 4,
"nbformat_minor": 2
}