-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathutil.py
120 lines (99 loc) · 4.58 KB
/
util.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# Draw bounding box
from PIL import Image, ImageColor, ImageDraw, ImageFont, ImageOps
import numpy as np
def draw_bounding_box_on_image(image,
ymin,
xmin,
ymax,
xmax,
color,
font,
thickness=4,
display_str_list=()):
"""
Adds a bounding box to an image.
Args:
image -- the image object
ymin -- bounding box coordinate
xmin -- bounding box coordinate
ymax -- bounding box coordinate
xmax -- bounding box coordinate
color -- color for the bounding box edges
font -- font for class label
thickness -- edge thickness of the bounding box
display_str_list -- class labels for each object detected
Returns:
No return. The function modifies the `image` argument
that gets passed into this function
"""
draw = ImageDraw.Draw(image)
im_width, im_height = image.size
# scale the bounding box coordinates to the height and width of the image
(left, right, top, bottom) = (xmin * im_width, xmax * im_width,
ymin * im_height, ymax * im_height)
# define the four edges of the detection box
draw.line([(left, top), (left, bottom), (right, bottom), (right, top),
(left, top)],
width=thickness,
fill=color)
# If the total height of the display strings added to the top of the bounding
# box exceeds the top of the image, stack the strings below the bounding box
# instead of above.
display_str_heights = [font.getsize(ds)[1] for ds in display_str_list]
# Each display_str has a top and bottom margin of 0.05x.
total_display_str_height = (1 + 2 * 0.05) * sum(display_str_heights)
if top > total_display_str_height:
text_bottom = top
else:
text_bottom = top + total_display_str_height
# Reverse list and print from bottom to top.
for display_str in display_str_list[::-1]:
text_width, text_height = font.getsize(display_str)
margin = np.ceil(0.05 * text_height)
draw.rectangle([(left, text_bottom - text_height - 2 * margin),
(left + text_width, text_bottom)],
fill=color)
draw.text((left + margin, text_bottom - text_height - margin),
display_str,
fill="black",
font=font)
text_bottom -= text_height - 2 * margin
def draw_boxes(image, boxes, class_names, scores, max_boxes=10, min_score=0.1):
"""
Overlay labeled boxes on an image with formatted scores and label names.
Args:
image -- the image as a numpy array
boxes -- list of detection boxes
class_names -- list of classes for each detected object
scores -- numbers showing the model's confidence in detecting that object
max_boxes -- maximum detection boxes to overlay on the image (default is 10)
min_score -- minimum score required to display a bounding box
Returns:
image -- the image after detection boxes and classes are overlaid on the original image.
"""
colors = list(ImageColor.colormap.values())
try:
font = ImageFont.truetype("/usr/share/fonts/truetype/liberation/LiberationSansNarrow-Regular.ttf",
25)
except IOError:
print("Font not found, using default font.")
font = ImageFont.load_default()
for i in range(min(boxes.shape[0], max_boxes)):
# only display detection boxes that have the minimum score or higher
if scores[i] >= min_score:
ymin, xmin, ymax, xmax = tuple(boxes[i])
display_str = "{}: {}%".format(class_names[i].decode("ascii"),
int(100 * scores[i]))
color = colors[hash(class_names[i]) % len(colors)]
image_pil = Image.fromarray(np.uint8(image)).convert("RGB")
# draw one bounding box and overlay the class labels onto the image
draw_bounding_box_on_image(image_pil,
ymin,
xmin,
ymax,
xmax,
color,
font,
display_str_list=[display_str])
np.copyto(image, np.array(image_pil))
return image