{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "## thinning Ops" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "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": "e58164ae-16a1-48ac-8826-0c3801db9500", "version_major": 2, "version_minor": 0 }, "method": "display_data" }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "net.imagej.ImageJ@1fed040c" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "//load ImageJ\n", "%classpath config resolver imagej.public https://maven.imagej.net/content/groups/public\n", "%classpath add mvn net.imagej imagej 2.0.0-rc-67\n", "\n", "//create ImageJ object\n", "ij = new net.imagej.ImageJ()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This op performs [morphological thinning](https://en.wikipedia.org/wiki/Thinning_(morphology)) on any binary image. If you are not familiar with the concept of thinning, check out [skeletonization](https://en.wikipedia.org/wiki/Topological_skeleton), a very similar concept. Let's see how the `Op` is called:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Available operations:\n", "\t(RandomAccessibleInterval out?) =\n", "\tnet.imagej.ops.morphology.thin.ThinGuoHall(\n", "\t\tRandomAccessibleInterval out?,\n", "\t\tRandomAccessibleInterval in)" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "ij.op().help(\"thinGuoHall\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The thinning `Ops` are pretty straight forward, where all we need is an input image (as well as a preallocated output, if you have one).\n", "\n", "We need to get a binary image to perform any morphological operations. Let's get a grayscale image and then binarize it using [the Huang Threshold Op](../threshold/threshold.ipynb#Huang-Thresholding):" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[INFO] Verifying GIF format\n", "[INFO] Reading dimensions\n", "[INFO] Reading data blocks\n" ] }, { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAOgAAAAvCAYAAADpRIZ0AAADi0lEQVR42u2d2XJEIQhE5/9/Oqk8ppKrzdKA3p4qHlLJKKIHwS2fz+fz1fX5qVsiOUEaGelRQJ0uEaQGQCsVUGdLBCnMSJ0S6mCJQDVzUqOEOlUiSF2McJVQR0oEaogRnhLqPAkyht4MKVA2R4GqxkbKyNTlMK9M1cv6vVsmiSsBzY7ds4zUAcbExbms+nc/s20iQIMGyRwAHZB3tZ2lF1sPloPsBPX6ELf70+Gxpx0OqXBqrIF+Qvj/uhx08mdKrs0IJ1k5e1VbBOiQVbFMwLoArQA9S5+qvD9jDAnQwsZOLEuAnglo1TgToMMB9WxbMMPuypXvQbdFyp3T6wA9tawB5zxb1gCGXecSoAL0rK2WjvpPWLlXDvpCQKu3hqy6MBbbJoyv7rUAAfqisiIhHQLntFM4E+smOq/Wg8ACtEmnyCzMGg/VkGZGIEQ+Zp6DvAHQrA5l6NMBKGOhKGNsRfuVzEVd0t41W3eWlbmtwLwo3LmCyjpYYtkLndB2CNBOxbLLnlIWs8yTAZ2w5XLAm1x3GYYBFKvtE8qb4CzetN3jCMnP2IO67dMV0k2c0Ye8/dNeZ2ibRTJjqyGjrKEPNH/dcuw0c6VZgErSniSZ9GTMRSIjCMwacASoAJU0htWCU4BKBr8e2JinCVCJIB20silAJYJVYApQif61gUSASiQCVCKRsACdHIqcHjrdEOYx9kS7ysjcOioBdPqAPz2/OcG2qP0FKG631wF648wkQO+1Gw1Q5ObJ7oa65yGqCKDITRmvzuhgXX0HffsncjWKWcdTP1jrenpuZNXfiF0tjsRiK8uYXI1BtH3/1P/8hdXTGLvKouWgxkDz1F3daHtWf+f9HWKvnU1Q21rqsADq0WMFmseu6OyG9ocFULStjvrXDUd+XnWo53eeHBTR8aluxCt7nMhuIEVsUmF3z1hAbeSB2gKaZQb12Nzr2BzRYgzQ3WXsndKWS8iWnCYCqDcsR5wH22lNcIxIHz/1l9eu1pQpG1DkUQJP5JcCaIYnz1jI8ALq0csafjIArYpc0LZl6GGZXbwO3QMoEtJm5tEUQBHPkZWDWgZsZg6akR9ZQiFLeGeJXDxOIAIhqqPFIViAyZhBrWPBCihtBrW+uZO1iovMmJmruJF2ejwtI8RF6/DkkpEQF+1DBApWiOu5audp3x9AqzbodXha9rr9xNVRZ3F1s0H2srZb4+C3fAMmUUCVELkfMAAAAABJRU5ErkJggg==" }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import net.imglib2.FinalInterval\n", "\n", "input_full = ij.scifio().datasetIO().open(\"http://imagej.net/images/logo.gif\")\n", "\n", "//input_full has 3 channels. We only need one.\n", "input = ij.op().run(\"hyperSliceView\", input_full, 2, 0)\n", "\n", "//invert the image so that the blobs are \"on\" and the background \"off\"\n", "inverted = ij.op().run(\"create.img\", input)\n", "ij.op().run(\"invert\", inverted, input)\n", "\n", "binary = ij.op().run(\"threshold.huang\", inverted)\n", "\n", "ij.notebook().display(binary)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now that we have our image, let's thin it using all four of the thinning `Op`s so that we can see the difference between each one:" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAOgAAAAvCAYAAADpRIZ0AAADbklEQVR42u2dy66kMAwF+f+fntFdtDS6GsCP49hJV0tn1RCC48rb4bqu609GP79sGgidrCQjAIoQgCIEoACKEIACKEIAihCAAihCAIrQx18+PwDdANBvLLCsnSbYLJKf3/8rfWeKXY5uQVVGrkqno+DfntuRr7f8VPuKtTKYAuqxXVyvke+ujxTW3fUrC17x7h3l8b/rlHDuNgQ7fgx6V+De1s1z3WogVK11BajRND/3KPKTtQmAbjTB8G8aWTAq3l/l0BPyMuVdOru8XzWLq261puVpEhgKx570Hl2tKYACaHnLpZoP6Fol6GxNv6qLe3panomq6mWGyIRb5Rg48pvQNQbQgwGNOl1167Vq/bF7rZcWFEBHdnEPWUM8wT8AdJoNVo3dnrrQh+zCOWF+QrdU0b2r5pS0VqWzA6Ar8lM1hhXlW+eMlaD+nlGcmlZ2g4Hi/uje2MkBEF0bMAZsjtAbaEXrlN3dUpWWau3Qu6QRrVB3i1Lq6Kl0+f4roOpavaI1UV5X9cyKbXuRWV3PkORpp1XXkkf23ZX+vLD3uC78y/KCSmfObN9TpaW4X+nsqpZ50mz3qoqhImLKBGhHOFXVBFPFIvUOjrrL5Axxv4uXWRCnAAApgKLD1h6BFEARgAIoOu/MI7q4AIo2gnbyZgMARYDqWMLY5aQ9AEVfCS82AVCEABQhBKAIIQugO4wfdh3vMDbrC0ofHox9DqB3M4YAumf+ABRAkfj0hR0OWjuwYrMHMkfjExVxjVZA7/KsylckZM4bXheNdawK77OcQOF91tuOJUsZRkMCVeGOlnSswfIPz7+/4cnp32InLYXr+cCOBdDqfFnTy7y39TgWz/tFn2G9/sleFltWvIfHl6IferL6W8ZPLzVIb7Wj5b/IJJG11cpWBJFjQqwOnu3GV9g9Y2dPHiOwqcCK2tzTUnsqRTmgd+BYnD17wJUaUEu+vAenVQEasXt1xWgt44iNPEOHDkCtdvLcdym7ZFln7AQ0ki9ry1MBz8pKQNUjiECo7s1EAc0MKTyVzFJAq8eg2TGqeoxouc7j8NGupxeqzKl/akAzlV3EdpkKKwJooGHJjzsys4XVhwRXzC6ru7iZ2dXo16wt5aLq2US6xp1d3OiSU/aQupv71q0TsW6JvdhxNWwvbueHU3d2UuBEP/oLtXqHYnsLFdUAAAAASUVORK5CYII=" }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "guoHall = ij.op().run(\"thinGuoHall\", null, binary)\n", "\n", "ij.notebook().display(guoHall)" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAOgAAAAvCAYAAADpRIZ0AAADV0lEQVR42u2dyXLEIAxE+f+fnlRuOUyMlhYI81zVl0zMItEggYTHGOMTxe+TeR+AG5DkCQQFAIICAEEhKAAQFIICAEEBgKAQFAAICsC3B4I2J+htyrqZbLfq+DUrqHJ2rShnxwCzPqvbE5G5qp2eB4JuGgweMkWU9Z+SVyk+2vcubfqmg9UyWamvq33QJ6J4Taxv/6coSzF7K2b/v++qrQhFW1a3oQNRr9kk6mi2Vihetdp0aItKxjusEgi6sb6uZSmJsXsS60bOQ8ctBIWg8/d3+cQVpu2OjTUI+kKCZlauqj7N2qXeQVU8h7sbELQjQRWDs7JPK442du/ANvHjIejbVtAOJnLnie+w8QFBuw2k3aZZp4ifnUcjHXzooTS/IOhZxyxRP/NUsnjHcpMjON1ZZCVZVUKrLKvDpoQqNrZjfPQOHzcTpCFqZ02QQKWJkI3WqSpLVWZEzk8hjtHY2K5JDDuiirLRaiUEVR5Wq2JhKwVXoYQq2SmJbDnY37Wb3C02dxajXdDfddkbnjM0heCj5SnLqhgYJ/r71e6PhTids68eCbpD+R5TbMfGVdVKcErua7eV7+IcY5KPwXoCnTRZQVBwzerJVTkQFEBQCAref8dQxywdCApAkT+KzwlBQTOS3njNJgQFrczg7rfqQVAAAAQFAIICACAo54rIZFcZh+mjf6NP34SAoO8k6CK99h9A1d/6AOuDz0/X3cL2D3O+ofXTCZGcxlkaWibh2JuGpOiPNUk8k1dY0b9IcHukrqeLpK0yicpOkZJmlUN2PAyPgLxXZcyUYv3AkeXvMxPY+p2Q2XsWmXgHo0VenmACZR2WsWENaniS5ZNevXL1TPjRS609yf8zmU3qjykh2vlImZb8TEt5lruIZm2OXLRVJZNVcq8eG57JLqKbqKyyBI0ucKEV1LNyZd+L2PtKglaauCryZOSenRgVOv7vPZXrsJqg1gUk8JW+PEEVv2Ud8gxBK9oV8beiq9GqOir1ryCX2sqrMP0DFkgtQaN+goKgVh+0ol1RgkYH4Io6vP6VdyL06vkkgiYWllzlHpOw8kIn1e5ixW/eTRmr2W81H9W75xVmuGVCsJjJ3n6pv7xecNviurMizi2RFwEdjUL9MscG5F1CUDA+P5uxL9ZxB7xYAAAAAElFTkSuQmCC" }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "hilditch = ij.op().run(\"thinHilditch\", null, binary)\n", "\n", "ij.notebook().display(hilditch)" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAOgAAAAvCAYAAADpRIZ0AAADY0lEQVR42u2d0W7DIAxF8/8/vWkPk6apScC+15jkVPJTWiCGY4wx9DiO4ysqPx/l9xDkaSJgxF85ggBoWJY3AEGA1AUokCKIlREARRAARRAABVAEAVAARRJj5f8HQBsD+raOeipokXHypj5fBqhSyR1h7dCeu0+HwXbXnrPfuHTSDf5HAJqFVdlZ/3+3quNH6qts12h73IZ8F+O6fB+0QgFXdYyCMwOYsqxK3arAmJkFR8pYAWcnV3oZoJUvrrTKERfNBat61le6kFljoTZkyv4GUPOLZut2lbW6U5VQZCBT6FdVRrf1+mMBVa8rlAO5E6CO+qPu7UqDM9MOxdIHQBusZ94K6KhBc+ki8lGusRf2x17JCW8CVD0wHYG5CheyygAqgmOGdjN7MoP2zgxbGYxUBtrKAO28J/iE2bMCUIc79xRAFeP797flLu6KdC1XZLJLWWqrnQ14vA3QT/24cosqDOiVj+6aUTvt7XUva2aAAegRDiYVt9WTXuVcC63KjnEaqmjA5er7d892W4eqPR91vSad+bNkHFYzc4rCWZZyj/Uu+TyTp7xDJLlqb1RRr/Gd/e6qI1/WOYiVwKkCDtUZMSrj4m7vXT2udhT2x1He8X/rUgZalBE4197iLmdf1W1cMb4ect6Uw8dI/+2jFwtKQOogAlAARRrvbQMogCKNA1EACqBI40ARegVQpFH0lVsbARRZ5ALvdrMegCIIAqAIAqAIgvQBtPN6Yfe1DGuxXjc/dD+svyWgOwcgMH4Amk6W33GAMzPVDTL2RJe1f/ym9ejB4MizWUCr2hU5kvYplS6rE9X7zRxEjhxUP3s2UmZUr5HUxsjRxFFmRt/v5Lv3uZhXlV799qqcmfzP2Ze8GhCRNo8MmplnEX3N5M9Gn0XydFW6VOg8cpVJNA95hplkf+Q6IfrykYEyCuCVhZs1BqP3/KzQSXdAR9uo0LlDV9lbOrI6kgF6Bs6d4rMurgtQtWtcZbQ6GsbZNkb1Gl0yKQEd0VNgyVHjxqgsngvQyD2m7tlCNdMLrbm1/2f72e3RqD2J0XV0S0Bn/505o0DHulm93gJQnV4d7uc2gGYihk4X1x3Fdbi4Edc/63Zm11jRumb/G6WLizsSxZ+daG6juE84qc/NBmQXkYvLgANQAC2Vb4IDB/CIv8PqAAAAAElFTkSuQmCC" }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "morphological = ij.op().run(\"thinMorphological\", null, binary)\n", "\n", "ij.notebook().display(morphological)" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAOgAAAAvCAYAAADpRIZ0AAADZ0lEQVR42u2d3XLEIAiF9/1fup3edTpNws8B0Xw7c26aBlnkKCK6n8/n82XBz8f6vwC8EUUcgaAAQFAAICgEBQCCAgAgKAAQFIKCBY58oj9B0Jc79N1ngk6dxJxki6MJWmlolaxVDmBts1OvK50sunb16cpB6zUzaLS9/zow2mF3jjgpDOwYPLyzZOWAe5rPbkvQyEflwEpZ1euzKeS8spuKnNPXusygSVlZontlRZ0p+m5FH0V0URNFEU11RT0Q9CBZVzIVpFg5m0/xg8g6GYJC0JZZS6nDynVfxcx7LEF3jedPJWhVCJcJUysImvlkE17bzaDd6fyTZWWdsqpvLFsYHfuQK/c1o0mpESFu5yyizABOk1Uxcq/KmG4UMpYmpcasQTtmEVVbU2VBUAhamiTqnEXU2bwJsqpCK+Ug9BaSKkL1kVncqtS1ckCYKmu1TpY+VSVmJq9FVdne8dss6rKu6sW7WtbKDXmvrMqa2eqkUWeddraKqoWgmcqYinjeK7tLluK7R06HRGfCrm2pKURVVHotOFXUdxJkVaH4ClmK8GzVEbNdNvJXh95N6Iv31QXtVSdPKk6x7OIkU4ruwS+Cdo8yVxvt6hF18jrqzQSFqAVJIsC9OhVbZxAVgoKhBAUQFGyw3wggKHCWC3YVnwAIChaUwB221QFBwd6khYgQFAAICgCAoAAACAoABF2SmGDzn4KIYTcf1BJ0en3ozmViEPRMgjb163wH6r7fFPSc6aQkMkFQz48Q3YWf0WcRgl7pq9TrTt+7d9Q26bD7X/2V/X93mslq8+jN8Vl7WDhzZzNn+3YDeW4oeHrP8wtklr8/lao9Gc2i15P+1mcRe3mWAco2LL7hPfPrIWjErp4BP7p08lyV4rnU7Z/2Y50Q/fJRmU/VKhZ5ljttn3SO3FZeYZOuNjp8wzPYRfomaqssQaMTXGgGtRRWPylifS8S7ysJWhniVg5aVQSt6OOr91RLh26CWicQ73sSgiqeZRfkGYJW6BVZb0Vno642KvtfQS51lFcR+gcikFqCRtcJCoJa16AVekUJGnXAjja86yvvQOjt550ImphYco0/hanKbKIiq7bimTcpYw37raNypo3sIOXR0Xp9aDYbm7kPS+3Lhvf69orYt8ReFHQMKvXjnCD2gqA5fAPcClypFqRbggAAAABJRU5ErkJggg==" }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "zhangSuen = ij.op().run(\"thinZhangSuen\", null, binary)\n", "\n", "ij.notebook().display(zhangSuen)" ] } ], "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": false, "sideBar": false, "skip_h1_title": false, "title_cell": "Table of Contents", "title_sidebar": "Contents", "toc_cell": false, "toc_position": {}, "toc_section_display": false, "toc_window_display": false } }, "nbformat": 4, "nbformat_minor": 2 }