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

Extending ImageJ

\n", "
    \n", "
  1. Scripting: the easy way to extend ImageJ (incomplete)
  2. \n", "
  3. Extending ImageJ: Data Input and Output
  4. \n", "
  5. Extending ImageJ: Commands (placeholder)
  6. \n", "
  7. Extending ImageJ: Ops
  8. \n", "
  9. Extending ImageJ: Tools (placeholder)
  10. \n", "
\n", "
\n", "
\n", "
\n", "
\n", "

Advanced usage

\n", "
    \n", "
  1. SciJava in Detail
  2. \n", "
  3. ImgLib2 in Detail
  4. \n", "
\n", "
\n", "
\n", "

Advanced extensions

\n", "
    \n", "
  1. Creating a custom service (coming later)
  2. \n", "
  3. Customizing module execution (coming later)
  4. \n", "
  5. Creating a SCIFIO plugin (coming later)
  6. \n", "
\n", "
\n", "
\n", "
\n", "
\n", "
\n", "
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Installation for ImageJ in Jupyter notebooks" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "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](https://www.anaconda.com/). Afterwards, please install the BeakerX kernel from the Anaconda command line:\n", "\n", "```\n", "conda install -c conda-forge ipywidgets beakerx\n", "```\n", "\n", "Find out more about [BeakerX](http://beakerx.com/)\n", "\n", "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." ] }, { "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": "3f28609d-985b-4165-8601-66817d67d24d", "version_major": 2, "version_minor": 0 }, "method": "display_data" }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%classpath config resolver imagej.public https://maven.imagej.net/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": "markdown", "metadata": {}, "source": [ "## Using ImageJ\n", "In order to use ImageJ, you need a variable `ij` which offers you all the functionality. In ImageJs script editor, just add a line \n", "```\n", "#@ ImageJ ij\n", "```\n", "In Jupyter notebooks, you can call this:" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "scrolled": true }, "outputs": [ { "data": { "text/plain": [ "ImageJ v2.0.0-rc-71 is ready to go." ] }, "execution_count": 6, "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": 9, "metadata": { "scrolled": false }, "outputs": [ { "data": { "text/html": [ "" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "// image = ij.io().open(\"https://imagej.net/images/lymp.tif\")\n", "image = ij.io().open(\"C:/structure/data/lymp.tif\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Compute histogram" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\"Histogram\"" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "histogram = ij.op().image().histogram(image)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### A first example: Count cells" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "binaryImage = ij.op().threshold().huang(image)" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
java.lang.IllegalArgumentException: Unsupported image type: net.imglib2.roi.labeling.LabelingType\r\n",
       "\tat net.imagej.notebook.image.RAIToHTMLConverter.lambda$convert$0(RAIToHTMLConverter.java:71)\r\n",
       "\tat net.imagej.notebook.DefaultNotebookService.lambda$initialize$3(DefaultNotebookService.java:107)\r\n",
       "\tat net.imagej.notebook.BeakerX$1.display(BeakerX.java:64)\r\n",
       "\tat jupyter.Displayers.display(Displayers.java:62)\r\n",
       "\tat com.twosigma.beakerx.MIMEContainerFactory.createMIMEContainersFromObject(MIMEContainerFactory.java:84)\r\n",
       "\tat com.twosigma.beakerx.MIMEContainerFactory.createMIMEContainers(MIMEContainerFactory.java:46)\r\n",
       "\tat com.twosigma.beakerx.kernel.msg.MessageCreator.createFinishResult(MessageCreator.java:265)\r\n",
       "\tat com.twosigma.beakerx.kernel.msg.MessageCreator.createFinish(MessageCreator.java:181)\r\n",
       "\tat com.twosigma.beakerx.kernel.msg.MessageCreator.createMessage(MessageCreator.java:172)\r\n",
       "\tat com.twosigma.beakerx.kernel.threads.ExecutionResultSender.update(ExecutionResultSender.java:45)\r\n",
       "\tat com.twosigma.beakerx.jvm.object.SimpleEvaluationObject.finished(SimpleEvaluationObject.java:72)\r\n",
       "\tat com.twosigma.beakerx.kernel.CodeFrame.handleResult(CodeFrame.java:40)\r\n",
       "\tat com.twosigma.beakerx.kernel.PlainCode.executeLastFrame(PlainCode.java:50)\r\n",
       "\tat com.twosigma.beakerx.kernel.Code.execute(Code.java:90)\r\n",
       "\tat com.twosigma.beakerx.kernel.handler.ExecuteRequestHandler.handleMsg(ExecuteRequestHandler.java:63)\r\n",
       "\tat com.twosigma.beakerx.kernel.handler.ExecuteRequestHandler.handle(ExecuteRequestHandler.java:51)\r\n",
       "\tat com.twosigma.beakerx.kernel.handler.ExecuteRequestHandler.handle(ExecuteRequestHandler.java:39)\r\n",
       "\tat com.twosigma.beakerx.socket.KernelSocketsZMQ.handleShell(KernelSocketsZMQ.java:195)\r\n",
       "\tat com.twosigma.beakerx.socket.KernelSocketsZMQ.run(KernelSocketsZMQ.java:170)\r\n",
       "
" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import net.imglib2.algorithm.labeling.ConnectedComponents;\n", "ij.op().labeling().cca(image, ConnectedComponents.StructuringElement.EIGHT_CONNECTED);" ] }, { "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 }