{ "cells": [ { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "import panel as pn\n", "import xarray as xr\n", "import holoviews as hv\n", "import geoviews as gv\n", "import cartopy.crs as ccrs\n", "from earthsim.annotators import PolyAnnotator, PolyExporter, paths_to_polys\n", "from earthsim.grabcut import GrabCutPanel, SelectRegionPanel\n", "\n", "gv.extension('bokeh')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The GrabCut algorithm provides a way to annotate an image using polygons or lines to demark the foreground and background. The algorithm estimates the color distribution of the target object and that of the background using a Gaussian mixture model. This is used to construct a Markov random field over the pixel labels, with an energy function that prefers connected regions having the same label, and running a graph cut based optimization to infer their values. This procedure is repeated until convergence, resulting in an image mask denoting the foreground and background.\n", "\n", "In this example this algorithm is applied to map tiles to automatically extract a coast- and shoreline contour. First we specify a region to download the map tiles in using the `SelectRegionPanel`, then we can declare the ``GrabCutPanel`` to annotate the region and let the algorithm compute a contour. " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "select_region = SelectRegionPanel(hv.Bounds((-77.5, 34.45, -77.3, 34.75)), magnification=1)\n", "pn.Row(select_region.param, select_region.view())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The toolbar in the plot on the left contains two polygon/polyline drawing tools to annotate the image with foreground and background regions respectively. To demonstrate this process in a static notebook there are already two polygons declared, one marking the sea as the foreground and one marking the land as the background." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "background = np.array([\n", " [-77.3777271 , 34.66037492], [-77.35987035, 34.62251189], [-77.34130751, 34.64016586],\n", " [-77.35563287, 34.65360275], [-77.36083954, 34.66560481], [-77.3777271 , 34.66037492]\n", "])\n", "foreground = np.array([\n", " [-77.46585666, 34.66965009], [-77.46451121, 34.62795592], [-77.43105867, 34.64501054],\n", " [-77.41376085, 34.62573423], [-77.37886112,34.63780581], [-77.41283172, 34.6800562 ],\n", " [-77.46585666, 34.66965009]\n", "])\n", "dashboard = GrabCutPanel(select_region.get_tiff(), fg_data=[foreground], bg_data=[background], minimum_size=500, tolerance=0.001)\n", "pn.Row(dashboard.param, dashboard.view())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can trigger an update in the extracted contour by pressing the ``Update contour`` button and filter smaller contours using the ``Filter Contour`` button. To speed up the calculation we can also downsample the image before applying the Grabcut algorithm.\n", "\n", "Next we can further edit the extracted contour using the ``PolyAnnotator`` class:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "annotator = PolyAnnotator(polys=dashboard.result)\n", "annotator.panel()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Once we are done we can convert the paths to a polygon and view the result in a separate cell:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "gv.tile_sources.ESRI * paths_to_polys(annotator.poly_stream.element).options(width=500, height=500, color_index=None)" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.6.4" } }, "nbformat": 4, "nbformat_minor": 2 }