|
|
|
|
|
|
|
|
|
import cv2 |
|
import math |
|
import random |
|
import colorsys |
|
import numpy as np |
|
import itertools |
|
import matplotlib.pyplot as plt |
|
from matplotlib import cm |
|
import os |
|
import scipy.io as io |
|
def get_bounding_box(img): |
|
"""Get bounding box coordinate information.""" |
|
rows = np.any(img, axis=1) |
|
cols = np.any(img, axis=0) |
|
rmin, rmax = np.where(rows)[0][[0, -1]] |
|
cmin, cmax = np.where(cols)[0][[0, -1]] |
|
|
|
|
|
rmax += 1 |
|
cmax += 1 |
|
return [rmin, rmax, cmin, cmax] |
|
|
|
def colorize(ch, vmin, vmax): |
|
"""Will clamp value value outside the provided range to vmax and vmin.""" |
|
cmap = plt.get_cmap("jet") |
|
ch = np.squeeze(ch.astype("float32")) |
|
vmin = vmin if vmin is not None else ch.min() |
|
vmax = vmax if vmax is not None else ch.max() |
|
ch[ch > vmax] = vmax |
|
ch[ch < vmin] = vmin |
|
ch = (ch - vmin) / (vmax - vmin + 1.0e-16) |
|
|
|
ch_cmap = (cmap(ch)[..., :3] * 255).astype("uint8") |
|
return ch_cmap |
|
|
|
|
|
|
|
def random_colors(N, bright=True): |
|
"""Generate random colors. |
|
|
|
To get visually distinct colors, generate them in HSV space then |
|
convert to RGB. |
|
""" |
|
brightness = 1.0 if bright else 0.7 |
|
hsv = [(i / N, 1, brightness) for i in range(N)] |
|
colors = list(map(lambda c: colorsys.hsv_to_rgb(*c), hsv)) |
|
random.shuffle(colors) |
|
return colors |
|
|
|
|
|
|
|
def visualize_instances_map( |
|
input_image, inst_map, type_map=None, type_colour=None, line_thickness=2 |
|
): |
|
"""Overlays segmentation results on image as contours. |
|
|
|
Args: |
|
input_image: input image |
|
inst_map: instance mask with unique value for every object |
|
type_map: type mask with unique value for every class |
|
type_colour: a dict of {type : colour} , `type` is from 0-N |
|
and `colour` is a tuple of (R, G, B) |
|
line_thickness: line thickness of contours |
|
|
|
Returns: |
|
overlay: output image with segmentation overlay as contours |
|
""" |
|
overlay = np.copy((input_image).astype(np.uint8)) |
|
|
|
inst_list = list(np.unique(inst_map)) |
|
inst_list.remove(0) |
|
|
|
inst_rng_colors = random_colors(len(inst_list)) |
|
inst_rng_colors = np.array(inst_rng_colors) * 255 |
|
inst_rng_colors = inst_rng_colors.astype(np.uint8) |
|
|
|
for inst_idx, inst_id in enumerate(inst_list): |
|
inst_map_mask = np.array(inst_map == inst_id, np.uint8) |
|
y1, y2, x1, x2 = get_bounding_box(inst_map_mask) |
|
y1 = y1 - 2 if y1 - 2 >= 0 else y1 |
|
x1 = x1 - 2 if x1 - 2 >= 0 else x1 |
|
x2 = x2 + 2 if x2 + 2 <= inst_map.shape[1] - 1 else x2 |
|
y2 = y2 + 2 if y2 + 2 <= inst_map.shape[0] - 1 else y2 |
|
inst_map_crop = inst_map_mask[y1:y2, x1:x2] |
|
contours_crop = cv2.findContours( |
|
inst_map_crop, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE |
|
) |
|
|
|
|
|
contours_crop = np.squeeze( |
|
contours_crop[0][0].astype("int32") |
|
) |
|
|
|
if len(contours_crop.shape) == 1: |
|
contours_crop = contours_crop.reshape(1,-1) |
|
|
|
contours_crop += np.asarray([[x1, y1]]) |
|
if type_map is not None: |
|
type_map_crop = type_map[y1:y2, x1:x2] |
|
type_id = np.unique(type_map_crop).max() |
|
inst_colour = type_colour[type_id] |
|
else: |
|
inst_colour = (inst_rng_colors[inst_idx]).tolist() |
|
cv2.drawContours(overlay, [contours_crop], -1, inst_colour, line_thickness) |
|
return overlay |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|