diff --git a/src/eyetrax/app/demo.py b/src/eyetrax/app/demo.py index a9feba2..fc5a6d5 100644 --- a/src/eyetrax/app/demo.py +++ b/src/eyetrax/app/demo.py @@ -12,6 +12,7 @@ from eyetrax.calibration import ( from eyetrax.cli import parse_common_args from eyetrax.filters import KalmanSmoother, KDESmoother, NoSmoother, make_kalman from eyetrax.gaze import GazeEstimator +from eyetrax.utils.draw import draw_cursor, make_thumbnail from eyetrax.utils.screen import get_screen_size from eyetrax.utils.video import camera, fullscreen, iter_frames @@ -85,28 +86,9 @@ def run_demo(): cv2.drawContours(canvas, contours, -1, (15, 182, 242), 5) if x_pred is not None and y_pred is not None and cursor_alpha > 0: - overlay = canvas.copy() - cv2.circle(overlay, (x_pred, y_pred), 30, (0, 0, 255), -1) - cv2.circle(overlay, (x_pred, y_pred), 25, (255, 255, 255), -1) - cv2.addWeighted( - overlay, - cursor_alpha * 0.6, - canvas, - 1 - cursor_alpha * 0.6, - 0, - canvas, - ) + draw_cursor(canvas, x_pred, y_pred, cursor_alpha) - small = cv2.resize(frame, (cam_width, cam_height)) - thumb = cv2.copyMakeBorder( - small, - BORDER, - BORDER, - BORDER, - BORDER, - cv2.BORDER_CONSTANT, - value=(255, 255, 255), - ) + thumb = make_thumbnail(frame, size=(cam_width, cam_height), border=BORDER) h, w = thumb.shape[:2] canvas[-h - MARGIN : -MARGIN, -w - MARGIN : -MARGIN] = thumb diff --git a/src/eyetrax/app/virtualcam.py b/src/eyetrax/app/virtualcam.py index 4d180fc..7db6025 100644 --- a/src/eyetrax/app/virtualcam.py +++ b/src/eyetrax/app/virtualcam.py @@ -10,6 +10,7 @@ from eyetrax.calibration import ( from eyetrax.cli import parse_common_args from eyetrax.filters import KalmanSmoother, KDESmoother, NoSmoother, make_kalman from eyetrax.gaze import GazeEstimator +from eyetrax.utils.draw import draw_cursor from eyetrax.utils.screen import get_screen_size from eyetrax.utils.video import camera, iter_frames @@ -73,7 +74,15 @@ def run_virtualcam(): if contours: cv2.drawContours(output, contours, -1, (0, 0, 255), 3) if x_pred is not None and y_pred is not None: - cv2.circle(output, (x_pred, y_pred), 10, (0, 0, 255), -1) + draw_cursor( + output, + x_pred, + y_pred, + alpha=1.0, + radius_outer=10, + radius_inner=0, + color_outer=(0, 0, 255), + ) cam.send(output) cam.sleep_until_next_frame() diff --git a/src/eyetrax/utils/draw.py b/src/eyetrax/utils/draw.py new file mode 100644 index 0000000..a6c6ad1 --- /dev/null +++ b/src/eyetrax/utils/draw.py @@ -0,0 +1,46 @@ +from __future__ import annotations + +import cv2 +import numpy as np + + +def draw_cursor( + canvas, + x: int, + y: int, + alpha: float, + *, + radius_outer: int = 30, + radius_inner: int = 25, + color_outer: tuple[int, int, int] = (0, 0, 255), + color_inner: tuple[int, int, int] = (255, 255, 255), +): + if alpha <= 0.0: + return canvas + + overlay = canvas.copy() + cv2.circle(overlay, (int(x), int(y)), radius_outer, color_outer, -1) + if radius_inner > 0: + cv2.circle(overlay, (int(x), int(y)), radius_inner, color_inner, -1) + + cv2.addWeighted(overlay, alpha * 0.6, canvas, 1 - alpha * 0.6, 0, canvas) + return canvas + + +def make_thumbnail( + frame, + *, + size: tuple[int, int] = (320, 240), + border: int = 2, + border_color: tuple[int, int, int] = (255, 255, 255), +): + img = cv2.resize(frame, size) + return cv2.copyMakeBorder( + img, + border, + border, + border, + border, + cv2.BORDER_CONSTANT, + value=border_color, + )