"Fossies" - the Fresh Open Source Software Archive

Member "scikit-image-0.19.3/skimage/future/manual_segmentation.py" (12 Jun 2022, 7344 Bytes) of package /linux/misc/scikit-image-0.19.3.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Python source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. For more information about "manual_segmentation.py" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 0.19.2_vs_0.19.3.

    1 from functools import reduce
    2 import numpy as np
    3 from ..draw import polygon
    4 from .._shared.version_requirements import require
    5 
    6 
    7 LEFT_CLICK = 1
    8 RIGHT_CLICK = 3
    9 
   10 
   11 def _mask_from_vertices(vertices, shape, label):
   12     mask = np.zeros(shape, dtype=int)
   13     pr = [y for x, y in vertices]
   14     pc = [x for x, y in vertices]
   15     rr, cc = polygon(pr, pc, shape)
   16     mask[rr, cc] = label
   17     return mask
   18 
   19 
   20 @require("matplotlib", ">=3.0.3")
   21 def _draw_polygon(ax, vertices, alpha=0.4):
   22     from matplotlib.patches import Polygon
   23     from matplotlib.collections import PatchCollection
   24     import matplotlib.pyplot as plt
   25 
   26     polygon = Polygon(vertices, closed=True)
   27     p = PatchCollection([polygon], match_original=True, alpha=alpha)
   28     polygon_object = ax.add_collection(p)
   29     plt.draw()
   30     return polygon_object
   31 
   32 
   33 @require("matplotlib", ">=3.0.3")
   34 def manual_polygon_segmentation(image, alpha=0.4, return_all=False):
   35     """Return a label image based on polygon selections made with the mouse.
   36 
   37     Parameters
   38     ----------
   39     image : (M, N[, 3]) array
   40         Grayscale or RGB image.
   41 
   42     alpha : float, optional
   43         Transparency value for polygons drawn over the image.
   44 
   45     return_all : bool, optional
   46         If True, an array containing each separate polygon drawn is returned.
   47         (The polygons may overlap.) If False (default), latter polygons
   48         "overwrite" earlier ones where they overlap.
   49 
   50     Returns
   51     -------
   52     labels : array of int, shape ([Q, ]M, N)
   53         The segmented regions. If mode is `'separate'`, the leading dimension
   54         of the array corresponds to the number of regions that the user drew.
   55 
   56     Notes
   57     -----
   58     Use left click to select the vertices of the polygon
   59     and right click to confirm the selection once all vertices are selected.
   60 
   61     Examples
   62     --------
   63     >>> from skimage import data, future, io
   64     >>> camera = data.camera()
   65     >>> mask = future.manual_polygon_segmentation(camera)  # doctest: +SKIP
   66     >>> io.imshow(mask)  # doctest: +SKIP
   67     >>> io.show()  # doctest: +SKIP
   68     """
   69     import matplotlib
   70     import matplotlib.pyplot as plt
   71 
   72     list_of_vertex_lists = []
   73     polygons_drawn = []
   74 
   75     temp_list = []
   76     preview_polygon_drawn = []
   77 
   78     if image.ndim not in (2, 3):
   79         raise ValueError('Only 2D grayscale or RGB images are supported.')
   80 
   81     fig, ax = plt.subplots()
   82     fig.subplots_adjust(bottom=0.2)
   83     ax.imshow(image, cmap="gray")
   84     ax.set_axis_off()
   85 
   86     def _undo(*args, **kwargs):
   87         if list_of_vertex_lists:
   88             list_of_vertex_lists.pop()
   89             # Remove last polygon from list of polygons...
   90             last_poly = polygons_drawn.pop()
   91             # ... then from the plot
   92             last_poly.remove()
   93             fig.canvas.draw_idle()
   94 
   95     undo_pos = fig.add_axes([0.85, 0.05, 0.075, 0.075])
   96     undo_button = matplotlib.widgets.Button(undo_pos, u'\u27F2')
   97     undo_button.on_clicked(_undo)
   98 
   99     def _extend_polygon(event):
  100         # Do not record click events outside axis or in undo button
  101         if event.inaxes is None or event.inaxes is undo_pos:
  102             return
  103         # Do not record click events when toolbar is active
  104         if ax.get_navigate_mode():
  105             return
  106 
  107         if event.button == LEFT_CLICK:  # Select vertex
  108             temp_list.append([event.xdata, event.ydata])
  109             # Remove previously drawn preview polygon if any.
  110             if preview_polygon_drawn:
  111                 poly = preview_polygon_drawn.pop()
  112                 poly.remove()
  113 
  114             # Preview polygon with selected vertices.
  115             polygon = _draw_polygon(ax, temp_list, alpha=(alpha / 1.4))
  116             preview_polygon_drawn.append(polygon)
  117 
  118         elif event.button == RIGHT_CLICK:  # Confirm the selection
  119             if not temp_list:
  120                 return
  121 
  122             # Store the vertices of the polygon as shown in preview.
  123             # Redraw polygon and store it in polygons_drawn so that
  124             # `_undo` works correctly.
  125             list_of_vertex_lists.append(temp_list[:])
  126             polygon_object = _draw_polygon(ax, temp_list, alpha=alpha)
  127             polygons_drawn.append(polygon_object)
  128 
  129             # Empty the temporary variables.
  130             preview_poly = preview_polygon_drawn.pop()
  131             preview_poly.remove()
  132             del temp_list[:]
  133 
  134             plt.draw()
  135 
  136     fig.canvas.mpl_connect('button_press_event', _extend_polygon)
  137 
  138     plt.show(block=True)
  139 
  140     labels = (_mask_from_vertices(vertices, image.shape[:2], i)
  141               for i, vertices in enumerate(list_of_vertex_lists, start=1))
  142     if return_all:
  143         return np.stack(labels)
  144     else:
  145         return reduce(np.maximum, labels, np.broadcast_to(0, image.shape[:2]))
  146 
  147 
  148 @require("matplotlib", ">=3.0.3")
  149 def manual_lasso_segmentation(image, alpha=0.4, return_all=False):
  150     """Return a label image based on freeform selections made with the mouse.
  151 
  152     Parameters
  153     ----------
  154     image : (M, N[, 3]) array
  155         Grayscale or RGB image.
  156 
  157     alpha : float, optional
  158         Transparency value for polygons drawn over the image.
  159 
  160     return_all : bool, optional
  161         If True, an array containing each separate polygon drawn is returned.
  162         (The polygons may overlap.) If False (default), latter polygons
  163         "overwrite" earlier ones where they overlap.
  164 
  165     Returns
  166     -------
  167     labels : array of int, shape ([Q, ]M, N)
  168         The segmented regions. If mode is `'separate'`, the leading dimension
  169         of the array corresponds to the number of regions that the user drew.
  170 
  171     Notes
  172     -----
  173     Press and hold the left mouse button to draw around each object.
  174 
  175     Examples
  176     --------
  177     >>> from skimage import data, future, io
  178     >>> camera = data.camera()
  179     >>> mask = future.manual_lasso_segmentation(camera)  # doctest: +SKIP
  180     >>> io.imshow(mask)  # doctest: +SKIP
  181     >>> io.show()  # doctest: +SKIP
  182     """
  183     import matplotlib
  184     import matplotlib.pyplot as plt
  185 
  186     list_of_vertex_lists = []
  187     polygons_drawn = []
  188 
  189     if image.ndim not in (2, 3):
  190         raise ValueError('Only 2D grayscale or RGB images are supported.')
  191 
  192     fig, ax = plt.subplots()
  193     fig.subplots_adjust(bottom=0.2)
  194     ax.imshow(image, cmap="gray")
  195     ax.set_axis_off()
  196 
  197     def _undo(*args, **kwargs):
  198         if list_of_vertex_lists:
  199             list_of_vertex_lists.pop()
  200             # Remove last polygon from list of polygons...
  201             last_poly = polygons_drawn.pop()
  202             # ... then from the plot
  203             last_poly.remove()
  204             fig.canvas.draw_idle()
  205 
  206     undo_pos = fig.add_axes([0.85, 0.05, 0.075, 0.075])
  207     undo_button = matplotlib.widgets.Button(undo_pos, u'\u27F2')
  208     undo_button.on_clicked(_undo)
  209 
  210     def _on_lasso_selection(vertices):
  211         if len(vertices) < 3:
  212             return
  213         list_of_vertex_lists.append(vertices)
  214         polygon_object = _draw_polygon(ax, vertices, alpha=alpha)
  215         polygons_drawn.append(polygon_object)
  216         plt.draw()
  217 
  218     matplotlib.widgets.LassoSelector(ax, _on_lasso_selection)
  219 
  220     plt.show(block=True)
  221 
  222     labels = (_mask_from_vertices(vertices, image.shape[:2], i)
  223               for i, vertices in enumerate(list_of_vertex_lists, start=1))
  224     if return_all:
  225         return np.stack(labels)
  226     else:
  227         return reduce(np.maximum, labels, np.broadcast_to(0, image.shape[:2]))