Upload overlay.py
Browse files- overlay.py +116 -0
overlay.py
ADDED
@@ -0,0 +1,116 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/usr/bin/env python
|
2 |
+
# coding: utf-8
|
3 |
+
|
4 |
+
###overlay
|
5 |
+
import cv2
|
6 |
+
import math
|
7 |
+
import random
|
8 |
+
import colorsys
|
9 |
+
import numpy as np
|
10 |
+
import itertools
|
11 |
+
import matplotlib.pyplot as plt
|
12 |
+
from matplotlib import cm
|
13 |
+
import os
|
14 |
+
import scipy.io as io
|
15 |
+
def get_bounding_box(img):
|
16 |
+
"""Get bounding box coordinate information."""
|
17 |
+
rows = np.any(img, axis=1)
|
18 |
+
cols = np.any(img, axis=0)
|
19 |
+
rmin, rmax = np.where(rows)[0][[0, -1]]
|
20 |
+
cmin, cmax = np.where(cols)[0][[0, -1]]
|
21 |
+
# due to python indexing, need to add 1 to max
|
22 |
+
# else accessing will be 1px in the box, not out
|
23 |
+
rmax += 1
|
24 |
+
cmax += 1
|
25 |
+
return [rmin, rmax, cmin, cmax]
|
26 |
+
####
|
27 |
+
def colorize(ch, vmin, vmax):
|
28 |
+
"""Will clamp value value outside the provided range to vmax and vmin."""
|
29 |
+
cmap = plt.get_cmap("jet")
|
30 |
+
ch = np.squeeze(ch.astype("float32"))
|
31 |
+
vmin = vmin if vmin is not None else ch.min()
|
32 |
+
vmax = vmax if vmax is not None else ch.max()
|
33 |
+
ch[ch > vmax] = vmax # clamp value
|
34 |
+
ch[ch < vmin] = vmin
|
35 |
+
ch = (ch - vmin) / (vmax - vmin + 1.0e-16)
|
36 |
+
# take RGB from RGBA heat map
|
37 |
+
ch_cmap = (cmap(ch)[..., :3] * 255).astype("uint8")
|
38 |
+
return ch_cmap
|
39 |
+
|
40 |
+
|
41 |
+
####
|
42 |
+
def random_colors(N, bright=True):
|
43 |
+
"""Generate random colors.
|
44 |
+
|
45 |
+
To get visually distinct colors, generate them in HSV space then
|
46 |
+
convert to RGB.
|
47 |
+
"""
|
48 |
+
brightness = 1.0 if bright else 0.7
|
49 |
+
hsv = [(i / N, 1, brightness) for i in range(N)]
|
50 |
+
colors = list(map(lambda c: colorsys.hsv_to_rgb(*c), hsv))
|
51 |
+
random.shuffle(colors)
|
52 |
+
return colors
|
53 |
+
|
54 |
+
|
55 |
+
####
|
56 |
+
def visualize_instances_map(
|
57 |
+
input_image, inst_map, type_map=None, type_colour=None, line_thickness=2
|
58 |
+
):
|
59 |
+
"""Overlays segmentation results on image as contours.
|
60 |
+
|
61 |
+
Args:
|
62 |
+
input_image: input image
|
63 |
+
inst_map: instance mask with unique value for every object
|
64 |
+
type_map: type mask with unique value for every class
|
65 |
+
type_colour: a dict of {type : colour} , `type` is from 0-N
|
66 |
+
and `colour` is a tuple of (R, G, B)
|
67 |
+
line_thickness: line thickness of contours
|
68 |
+
|
69 |
+
Returns:
|
70 |
+
overlay: output image with segmentation overlay as contours
|
71 |
+
"""
|
72 |
+
overlay = np.copy((input_image).astype(np.uint8))
|
73 |
+
|
74 |
+
inst_list = list(np.unique(inst_map)) # get list of instances
|
75 |
+
inst_list.remove(0) # remove background
|
76 |
+
|
77 |
+
inst_rng_colors = random_colors(len(inst_list))
|
78 |
+
inst_rng_colors = np.array(inst_rng_colors) * 255
|
79 |
+
inst_rng_colors = inst_rng_colors.astype(np.uint8)
|
80 |
+
|
81 |
+
for inst_idx, inst_id in enumerate(inst_list):
|
82 |
+
inst_map_mask = np.array(inst_map == inst_id, np.uint8) # get single object
|
83 |
+
y1, y2, x1, x2 = get_bounding_box(inst_map_mask)
|
84 |
+
y1 = y1 - 2 if y1 - 2 >= 0 else y1
|
85 |
+
x1 = x1 - 2 if x1 - 2 >= 0 else x1
|
86 |
+
x2 = x2 + 2 if x2 + 2 <= inst_map.shape[1] - 1 else x2
|
87 |
+
y2 = y2 + 2 if y2 + 2 <= inst_map.shape[0] - 1 else y2
|
88 |
+
inst_map_crop = inst_map_mask[y1:y2, x1:x2]
|
89 |
+
contours_crop = cv2.findContours(
|
90 |
+
inst_map_crop, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE
|
91 |
+
)
|
92 |
+
# only has 1 instance per map, no need to check #contour detected by opencv
|
93 |
+
#print(contours_crop)
|
94 |
+
contours_crop = np.squeeze(
|
95 |
+
contours_crop[0][0].astype("int32")
|
96 |
+
) # * opencv protocol format may break
|
97 |
+
|
98 |
+
if len(contours_crop.shape) == 1:
|
99 |
+
contours_crop = contours_crop.reshape(1,-1)
|
100 |
+
#print(contours_crop.shape)
|
101 |
+
contours_crop += np.asarray([[x1, y1]]) # index correction
|
102 |
+
if type_map is not None:
|
103 |
+
type_map_crop = type_map[y1:y2, x1:x2]
|
104 |
+
type_id = np.unique(type_map_crop).max() # non-zero
|
105 |
+
inst_colour = type_colour[type_id]
|
106 |
+
else:
|
107 |
+
inst_colour = (inst_rng_colors[inst_idx]).tolist()
|
108 |
+
cv2.drawContours(overlay, [contours_crop], -1, inst_colour, line_thickness)
|
109 |
+
return overlay
|
110 |
+
|
111 |
+
|
112 |
+
# In[ ]:
|
113 |
+
|
114 |
+
|
115 |
+
|
116 |
+
|