#!/usr/bin/env python # coding: utf-8 ###overlay 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]] # due to python indexing, need to add 1 to max # else accessing will be 1px in the box, not out 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 # clamp value ch[ch < vmin] = vmin ch = (ch - vmin) / (vmax - vmin + 1.0e-16) # take RGB from RGBA heat map 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)) # get list of instances inst_list.remove(0) # remove background 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) # get single object 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 ) # only has 1 instance per map, no need to check #contour detected by opencv #print(contours_crop) contours_crop = np.squeeze( contours_crop[0][0].astype("int32") ) # * opencv protocol format may break if len(contours_crop.shape) == 1: contours_crop = contours_crop.reshape(1,-1) #print(contours_crop.shape) contours_crop += np.asarray([[x1, y1]]) # index correction if type_map is not None: type_map_crop = type_map[y1:y2, x1:x2] type_id = np.unique(type_map_crop).max() # non-zero 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 # In[ ]: