diff contours.py @ 2:b74693340624 draft

planemo upload for repository https://github.com/BMCV/galaxy-image-analysis/tree/master/tools/overlay_images/ commit 71dae1df58f579b84d4f9d92fb0dd509c02dd48f
author imgteam
date Thu, 10 Aug 2023 07:29:34 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contours.py	Thu Aug 10 07:29:34 2023 +0000
@@ -0,0 +1,49 @@
+"""
+Copyright (c) 2017-2023 Leonid Kostrykin, Biomedical Computer Vision Group, Heidelberg University.
+
+Distributed under the MIT license.
+See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
+"""
+
+import numpy as np
+import skimage.morphology as morph
+
+
+class ContourPaint:
+    """Yields masks corresponding to contours of objects.
+
+    :param fg_mask: Binary mask of the image foreground. Any contour never overlaps the image foreground except of those image regions corresponding to the contoured object itself.
+    :param thickness: The thickness of the contour (width, in pixels).
+    :param where: The position of the contour (``inner``, ``center``, or ``outer``).
+    """
+
+    def __init__(self, fg_mask, thickness, where='center'):
+        assert where in ('inner', 'center', 'outer')
+        self.fg_mask = fg_mask
+        self.where = where
+        self.thickness = thickness
+        if where == 'inner':
+            self.selem_inner = morph.disk(self.thickness)
+            self.selem_outer = None
+        elif where == 'center':
+            self.selem_inner = morph.disk(self.thickness - self.thickness // 2)
+            self.selem_outer = morph.disk(self.thickness // 2)
+        elif where == 'outer':
+            self.selem_inner = None
+            self.selem_outer = morph.disk(self.thickness)
+
+    def get_contour_mask(self, mask):
+        """Returns the binary mask of the contour of an object.
+
+        :param mask: Binary mask of an object.
+        :return: Binary mask of the contour
+        """
+        if self.selem_inner is not None:
+            inner_contour = np.logical_xor(mask, morph.binary_erosion(mask, self.selem_inner))
+        else:
+            inner_contour = np.zeros(mask.shape, bool)
+        if self.selem_outer is not None:
+            outer_contour = np.logical_and(np.logical_not(self.fg_mask), morph.binary_dilation(mask, self.selem_outer))
+        else:
+            outer_contour = np.zeros(mask.shape, bool)
+        return np.logical_or(inner_contour, outer_contour)