{
"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 [ImageJ Forum](http://forum.imagej.net/)!"
]
},
{
"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",
"
\n",
"
\n",
"
\n",
"
\n",
"\n",
"
\n",
"
\n",
"
Advanced extensions
\n",
"
\n",
" - Creating a custom service (coming later)
\n",
" - Customizing module execution (coming later)
\n",
" - Creating a SCIFIO plugin (coming later)
\n",
"
\n",
"
\n",
"
\n",
""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## ImageJ Demo"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"First, we spin up an ImageJ. For more details on how this works, see the [Fundamentals of ImageJ](1-Using-ImageJ/1-Fundamentals.ipynb) notebook."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"scrolled": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Added new repo: imagej.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": "787efcd4-df44-483d-94d2-f256df468e64",
"version_major": 2,
"version_minor": 0
},
"method": "display_data"
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"ImageJ v2.0.0-rc-71 is ready to go."
]
},
"execution_count": 1,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"%classpath config resolver imagej.public https://maven.imagej.net/content/groups/public\n",
"%classpath add mvn net.imagej imagej 2.0.0-rc-71\n",
"ij = new net.imagej.ImageJ()\n",
"\"ImageJ v${ij.getVersion()} is ready to go.\""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Load some images"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"scrolled": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[INFO] Populating metadata\n",
"[INFO] Populating metadata\n",
"[INFO] Populating metadata\n",
"[INFO] Populating metadata\n"
]
},
{
"data": {
"text/html": [
"mandrill | cells |
---|
| |
"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"sourcePath = \"https://imagej.net/images\"\n",
"//sourcePath = System.getProperty(\"user.home\") + \"/data\"\n",
"cells = ij.io().open(sourcePath + \"/FluorescentCells.jpg\")\n",
"mandrill = ij.io().open(sourcePath + \"/baboon.jpg\")\n",
"ij.notebook().display([[\"mandrill\": mandrill, \"cells\": cells]])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Compute and display per-channel histograms"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"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": "e77cfaef-3916-4d81-82ea-8c3a88243be7",
"version_major": 2,
"version_minor": 0
},
"method": "display_data"
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
""
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"%classpath add mvn org.knowm.xchart xchart 3.5.2\n",
"\n",
"import net.imglib2.FinalInterval\n",
"import org.knowm.xchart.CategoryChart\n",
"import org.knowm.xchart.CategoryChartBuilder\n",
"\n",
"// Set this to the image you want to analyze.\n",
"image = mandrill \n",
"\n",
"xLen = image.dimension(0)\n",
"yLen = image.dimension(1)\n",
"cLen = image.dimension(2)\n",
"\n",
"// Create a chart.\n",
"CategoryChart chart = new CategoryChartBuilder().width(800).height(400).\n",
" title(\"Histogram\").xAxisTitle(\"Bin\").yAxisTitle(\"Count\").build();\n",
"chart.getStyler().setPlotGridVerticalLinesVisible(false).setOverlapped(true)\n",
"\n",
"cNames = [\"red\", \"green\", \"blue\"]\n",
"colors = [new java.awt.Color(0xED4337), new java.awt.Color(0x90D860), new java.awt.Color(0x7989FF)]\n",
"for (c in 0..cLen - 1) {\n",
" // Slice the image at this channel.\n",
" slice = ij.op().transform().crop(image, FinalInterval.createMinSize(0, 0, c, xLen, yLen, 1))\n",
" // Get the histogram.\n",
" histogram = ij.op().image().histogram(slice)\n",
"\n",
" // Extract the counts and add them to the chart.\n",
" counts = []\n",
" for (value in histogram)\n",
" counts.add(value.getRealDouble())\n",
" chart.addSeries(cNames[c as int], (0..counts.size()-1), counts).setFillColor(colors[c as int])\n",
"}\n",
"org.knowm.xchart.BitmapEncoder.getBufferedImage(chart)"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"image | median | dog | topHat | blackTopHat |
---|
| | | | |
"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"import net.imglib2.FinalInterval\n",
"\n",
"// N-dimensional crop.\n",
"eyes = ij.op().transform().crop(mandrill, FinalInterval.createMinSize(85, 5, 0, 335, 110, 1), true)\n",
"\n",
"// Type conversion.\n",
"eyes32 = ij.op().convert().float32(eyes)\n",
"\n",
"// Median filter.\n",
"median = ij.op().run(\"create.img\", eyes32)\n",
"neighborhood = new HyperSphereShape(4)\n",
"ij.op().run(\"filter.median\", median, eyes32, neighborhood)\n",
"\n",
"// Difference of Gaussians.\n",
"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",
"])\n",
"\n",
"// Grayscale morphology operators.\n",
"import net.imglib2.algorithm.neighborhood.HyperSphereShape\n",
"topHat = ij.op().morphology().topHat(eyes, [neighborhood])\n",
"blackTopHat = ij.op().morphology().blackTopHat(eyes, [neighborhood])\n",
"\n",
"ij.notebook().display([[\"image\":eyes, \"median\":median, \"dog\":dog, \"topHat\":topHat, \"blackTopHat\":blackTopHat]])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Fourier transform with lowpass filter"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"scrolled": false
},
"outputs": [
{
"data": {
"text/html": [
"image | lowpass |
---|
| |
"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"import net.imglib2.util.Util\n",
"import net.imglib2.FinalDimensions\n",
"\n",
"image = cells\n",
"radius = 10\n",
"\n",
"def 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",
"}\n",
"\n",
"// Perform fft of the input.\n",
"fft = ij.op().filter().fft(image)\n",
"\n",
"// Filter it.\n",
"lowpass(fft, 10)\n",
"\n",
"// Reverse the FFT.\n",
"import net.imglib2.type.numeric.real.FloatType\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.4.3"
},
"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
}