Skip to content

Commit

Permalink
Add thickness option to overlays
Browse files Browse the repository at this point in the history
  • Loading branch information
ericup committed Sep 28, 2024
1 parent fb9089b commit b95b49f
Showing 1 changed file with 15 additions and 12 deletions.
27 changes: 15 additions & 12 deletions celldetection/data/cpn.py
Original file line number Diff line number Diff line change
Expand Up @@ -243,16 +243,16 @@ def contours2boxes(contours):
return boxes


def render_contour(contour, val=1, dtype='int32', round=False, reference=None):
def render_contour(contour, val=1, dtype='int32', round=False, reference=None, thickness=-1):
if reference is None:
reference = contour
xmin, ymin = np.floor(np.min(reference, axis=0)).astype('int')
xmax, ymax = np.ceil(np.max(reference, axis=0)).astype('int')
a = np.zeros((ymax - ymin + 1, xmax - xmin + 1), dtype=dtype)
if round:
contour = contour.round()
a = cv2.drawContours(a, [np.array(contour, dtype=np.int32).reshape((-1, 1, 2))], 0, val, -1,
offset=(-xmin, -ymin))
a = cv2.drawContours(a, [np.array(contour, dtype=np.int32).reshape((-1, 1, 2))], 0, val,
thickness, offset=(-xmin, -ymin))
return a, (xmin, xmax), (ymin, ymax)


Expand Down Expand Up @@ -644,15 +644,16 @@ def sampled_sizes(self):
return self._sampled_sizes


def _add_contour_to_overlay_(counter, overlay, contour, size, hue_range, saturation_range, value_range, rounded, clip):
def _add_contour_to_overlay_(counter, overlay, contour, size, hue_range, saturation_range, value_range, rounded, clip,
thickness):

dtype = overlay.dtype
is_int = np.issubdtype(dtype, np.integer)
if rounded:
contour = np.round(contour)
if clip:
clip_contour_(contour, np.array(size) - 1)
a, (xmin, xmax), (ymin, ymax) = render_contour(contour, val=1, dtype='uint8')
a, (xmin, xmax), (ymin, ymax) = render_contour(contour, val=1, dtype='uint8', thickness=thickness)
a = a.astype(dtype)
c, = random_colors_hsv(1, hue_range=hue_range, saturation_range=saturation_range, value_range=value_range,
ubyte=is_int)
Expand All @@ -673,7 +674,7 @@ def _add_contour_to_overlay_mp_(args):
"""
(contour, overlay_shm_name, overlay_shape, counter_shm_name, counter_shape, dtype_char,
size, hue_range, saturation_range, value_range, rounded, clip, seed) = args
size, hue_range, saturation_range, value_range, rounded, clip, seed, thickness) = args

dtype = np.dtype(dtype_char)

Expand All @@ -688,7 +689,7 @@ def _add_contour_to_overlay_mp_(args):
# Add contour to overlay and counter
np.random.seed(seed) # specific seed is about 100x faster than np.random.seed(None)
_add_contour_to_overlay_(counter, overlay, contour, size, hue_range, saturation_range, value_range,
rounded, clip)
rounded, clip, thickness)
finally:
# Close shared memory (do not unlink, only the creator should unlink)
existing_overlay_shm.close()
Expand Down Expand Up @@ -724,7 +725,7 @@ def _postprocess_overlay(overlay, counter, normalize=True):

def _contours2overlay_mp(contours, size, hue_range=(0, 360), saturation_range=(60, 133),
value_range=(180, 256), rounded=True, clip=True,
intermediate_dtype='uint16', processes=None) -> np.ndarray:
intermediate_dtype='uint16', thickness=-1, processes=None) -> np.ndarray:
"""
Multiprocessing version of contours to overlay.
Expand Down Expand Up @@ -781,7 +782,8 @@ def _contours2overlay_mp(contours, size, hue_range=(0, 360), saturation_range=(6
value_range,
rounded,
clip,
seed # multiprocessing requires seeds
seed, # multiprocessing requires seeds
thickness
)
for contour, seed in zip(
contours,
Expand All @@ -807,7 +809,7 @@ def _contours2overlay_mp(contours, size, hue_range=(0, 360), saturation_range=(6


def contours2overlay(contours, size, hue_range=(0, 180), saturation_range=(60, 133), value_range=(180, 256),
rounded=True, clip=True, intermediate_dtype='uint16', processes=None):
rounded=True, clip=True, intermediate_dtype='uint16', thickness=-1, processes=None):
"""Contours to overlay.
Creates an overlay image from contours.
Expand All @@ -828,6 +830,7 @@ def contours2overlay(contours, size, hue_range=(0, 180), saturation_range=(60, 1
intermediate_dtype: Intermediate dtype. Small dtypes reduce memory consumption and speed up processing.
The dtype also limits the maximum number of overlaps. The sum of all overlapping
colors, as well as the number of overlaps, must remain below the dtypes upper limit.
thickness: Thickness of lines the contours are drawn with. If it is negative, the contour interiors are drawn.
processes: Number of processes for multiprocessing. `None` disables multiprocessing.
Negative values cause number of processes to be inferred from system CPU count and
environment (e.g. MPI, Slurm).
Expand All @@ -840,13 +843,13 @@ def contours2overlay(contours, size, hue_range=(0, 180), saturation_range=(60, 1

if processes is not None and processes not in (1, 0):
return _contours2overlay_mp(contours, size, hue_range, saturation_range, value_range, rounded, clip,
intermediate_dtype, processes)
intermediate_dtype, thickness, processes)
else:
overlay = np.zeros(tuple(size) + (4,), dtype=intermediate_dtype)
counter = np.zeros(tuple(size), dtype=intermediate_dtype)
if contours is not None:
for contour in contours:
_add_contour_to_overlay_(counter, overlay, contour, size, hue_range, saturation_range, value_range,
rounded, clip)
rounded, clip, thickness=thickness)
overlay = _postprocess_overlay(overlay, counter, normalize=contours is not None)
return overlay

0 comments on commit b95b49f

Please sign in to comment.