{ "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", "
\n", "
\n", "
\n", "

Using ImageJ

\n", "
    \n", "
  1. Fundamentals of ImageJ
  2. \n", "
  3. ImageJ Ops
  4. \n", "
  5. ImgLib2 Basics
  6. \n", "
  7. Tables
  8. \n", "
  9. Mixed World: Using ImageJ 1.x
  10. \n", "
  11. ImageJ with Python Kernel
  12. \n", "
  13. Calling Scripts from Scripts
  14. \n", "
\n", "
\n", "
\n", "

Extending ImageJ

\n", "
    \n", "
  1. IOPlugins - Data Input and Output
  2. \n", "
  3. Ops - Image Algorithms
  4. \n", "
\n", "

Advanced Topics

\n", "
    \n", "
  1. SciJava in Detail
  2. \n", "
  3. ImgLib2 in Detail
  4. \n", "
  5. Using Special Ops
  6. \n", "
\n", "
\n", "
\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": [ "\"Histogram\"" ] }, "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": [ "
median
topHat
blackTopHat
" ] }, "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": [ "
mediantopHatblackTopHat
" ] }, "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": [ "
imagelowpass
" ] }, "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 }