Skip to content

Commit 23c5ecd

Browse files
author
spencer@primus
committed
Add detection visualization
1 parent 23af2b6 commit 23c5ecd

1 file changed

Lines changed: 96 additions & 0 deletions

File tree

avapi/visualize/tracking.py

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
import numpy as np
2+
from PIL import ImageDraw
3+
4+
5+
def draw_detections(image, detections, show_class=False, show_score=False):
6+
"""Draw detections on an image
7+
8+
Parameters
9+
----------
10+
image: :class:`PIL.Image`
11+
Image on which to draw the detections
12+
detections: : set of AVstack type
13+
A set of detections from AVstack
14+
show_class: bool
15+
Whether to draw the class of the object. Default is ``False``
16+
show_score: bool
17+
Whether to draw the score of the object. Default is ``False``
18+
19+
Returns
20+
-------
21+
: :class:`PIL.Image`
22+
Image with detections drawn
23+
"""
24+
draw = ImageDraw.Draw(image)
25+
for detection in detections:
26+
x0, y0, x1, y1 = detection.box.box2d
27+
# x0, y0, w, h = np.array(detection.state_vector).reshape(4)
28+
# x1, y1 = (x0 + w, y0 + h)
29+
draw.rectangle([x0, y0, x1, y1], outline=(0, 255, 0), width=1)
30+
class_ = detection.obj_type
31+
score = detection.score if detection.score else "N/A"
32+
# class_ = detection.metadata['class']['name']
33+
# score = round(float(detection.metadata['score']),2)
34+
if show_class and show_score:
35+
draw.text((x0, y1 + 2), "{}:{}".format(class_, score), fill=(0, 255, 0))
36+
elif show_class:
37+
draw.text((x0, y1 + 2), "{}".format(class_), fill=(0, 255, 0))
38+
elif show_score:
39+
draw.text((x0, y1 + 2), "{}".format(score), fill=(0, 255, 0))
40+
41+
del draw
42+
return image
43+
44+
45+
def draw_stonesoup_tracks(
46+
image, tracks, show_history=True, show_class=True, show_score=True
47+
):
48+
"""Draw tracks on an image
49+
50+
Parameters
51+
----------
52+
image: :class:`PIL.Image`
53+
Image on which to draw the tracks
54+
detections: : set of :class:`~.Tracks`
55+
A set of tracks generated by our :class:`~.MultiTargetTracker`
56+
show_history: bool
57+
Whether to draw the trajectory of the track. Default is ``True``
58+
show_class: bool
59+
Whether to draw the class of the object. Default is ``True``
60+
show_score: bool
61+
Whether to draw the score of the object. Default is ``True``
62+
63+
Returns
64+
-------
65+
: :class:`PIL.Image`
66+
Image with tracks drawn
67+
68+
"""
69+
draw = ImageDraw.Draw(image)
70+
for track in tracks:
71+
bboxes = np.array(
72+
[
73+
np.array(state.state_vector[[0, 2, 4, 5]]).reshape(4)
74+
for state in track.states
75+
]
76+
)
77+
x0, y0, w, h = bboxes[-1]
78+
x1 = x0 + w
79+
y1 = y0 + h
80+
draw.rectangle([x0, y0, x1, y1], outline=(255, 0, 0), width=2)
81+
82+
if show_history:
83+
pts = [(box[0] + box[2] / 2, box[1] + box[3] / 2) for box in bboxes]
84+
draw.line(pts, fill=(255, 0, 0), width=2)
85+
86+
class_ = track.metadata["class"]["name"]
87+
score = round(
88+
float(track.metadata["score"]) if track.metadata["score"] else 0.0, 2
89+
)
90+
if show_class and show_score:
91+
draw.text((x0, y1 + 2), "{}:{}".format(class_, score), fill=(255, 0, 0))
92+
elif show_class:
93+
draw.text((x0, y1 + 2), "{}".format(class_), fill=(255, 0, 0))
94+
elif show_score:
95+
draw.text((x0, y1 + 2), "{}".format(score), fill=(255, 0, 0))
96+
return image

0 commit comments

Comments
 (0)