Hockey-Vision / Examples /render_numbers.py
alexrhaigh
Add examples and more info about models
4a01c1b
Raw History Blame Contribute Delete
2.73 kB
"""Draw the number model's example video: every player's box, the jersey digits read this frame,
and a "#63 Z. Ostapchuk" tag on each player whose number has been read.
python CV_Models/Examples/render_numbers.py <clip>.mp4 <run_models output>/detections.json out.mp4
The detections must come from run_models.py with the number model (and --teams for names).
"""
import json
import sys
from pathlib import Path
import cv2
sys.path.insert(0, str(Path(__file__).resolve().parents[2])) # the repo root, for video_io
from video_io import FrameReader # noqa: E402
# BGR per player model class: San Jose teal, Montreal red, referees grey.
TEAM_COLORS = {
"team_a_player": (140, 120, 0), "goalie_a": (140, 120, 0),
"team_b_player": (40, 30, 200), "goalie_b": (40, 30, 200),
"referee": (130, 130, 130),
}
DIGIT_COLOR = (0, 215, 255)
def short_name(name):
"""'Zack Ostapchuk' -> 'Z. Ostapchuk'."""
first, _, last = name.partition(" ")
return f"{first[0]}. {last}" if last else name
def draw_tag(img, text, box, color):
x1, y1, x2, _ = box
scale, thickness = img.shape[1] / 2400, max(1, img.shape[1] // 960)
(tw, th), base = cv2.getTextSize(text, cv2.FONT_HERSHEY_SIMPLEX, scale, thickness)
x = int(max(0, min(img.shape[1] - tw - 8, (x1 + x2) / 2 - tw / 2)))
y = int(max(th + base + 8, y1 - 6))
cv2.rectangle(img, (x - 4, y - th - base - 4), (x + tw + 4, y + 2), color, -1)
cv2.rectangle(img, (x - 4, y - th - base - 4), (x + tw + 4, y + 2), (255, 255, 255), 1)
cv2.putText(img, text, (x, y - base), cv2.FONT_HERSHEY_SIMPLEX, scale, (255, 255, 255), thickness,
cv2.LINE_AA)
def draw(frame, det):
line = max(1, frame.shape[1] // 800)
for d in det["number"]:
x1, y1, x2, y2 = map(int, d["box_xyxy"])
cv2.rectangle(frame, (x1, y1), (x2, y2), DIGIT_COLOR, line)
for p in det["player"]:
color = TEAM_COLORS.get(p["class"], (200, 200, 200))
x1, y1, x2, y2 = map(int, p["box_xyxy"])
cv2.rectangle(frame, (x1, y1), (x2, y2), color, line)
if p.get("jersey_number"):
name = p.get("player_name")
draw_tag(frame, f"#{p['jersey_number']}" + (f" {short_name(name)}" if name else ""),
p["box_xyxy"], color)
return frame
def main():
video, detections, out = sys.argv[1:4]
frames = json.loads(open(detections).read())
reader = FrameReader(video, len(frames))
writer = cv2.VideoWriter(out, cv2.VideoWriter_fourcc(*"mp4v"), reader.fps, (reader.width, reader.height))
for frame, f in zip(reader, frames):
writer.write(draw(frame, f["detections"]))
writer.release()
reader.close()
if __name__ == "__main__":
main()