Download src/menu.py from ayzeksalimli/hand-tracking-drawing: direct link, hf CLI and curl.
- Browser
- Download file 3.28 kB
-
https://huggingface.co/ayzeksalimli/hand-tracking-drawing/resolve/main/src/menu.py
- Command line
-
hf download hf://ayzeksalimli/hand-tracking-drawing/src/menu.py
-
curl -L -o menu.py https://huggingface.co/ayzeksalimli/hand-tracking-drawing/resolve/main/src/menu.py
3.28 kB
| """Startup mode menu.""" | |
| from __future__ import annotations | |
| import cv2 | |
| import numpy as np | |
| import ui | |
| WINDOW = "Hand Tracking Drawing" | |
| ITEMS = ( | |
| ("2d", "2D Drawing"), | |
| ("3d", "3D Drawing"), | |
| ("poses", "Poses"), | |
| ("translater", "Translater"), | |
| ) | |
| W, H = 720, 480 | |
| TOP = 150 | |
| ROW_H = 56 | |
| PAD = 60 | |
| class Menu: | |
| """Mode selection screen.""" | |
| def __init__(self) -> None: | |
| self.index = 0 | |
| self.click = -1 | |
| self.note = "" | |
| def on_mouse(self, event: int, x: int, y: int, flags: int, param) -> None: | |
| """Track hover and clicks.""" | |
| row = (y - TOP) // ROW_H | |
| if not 0 <= row < len(ITEMS) or not PAD <= x <= W - PAD: | |
| return | |
| self.index = int(row) | |
| if event == cv2.EVENT_LBUTTONDOWN: | |
| self.click = int(row) | |
| def frame(self) -> np.ndarray: | |
| """Render menu image.""" | |
| img = np.zeros((H, W, 3), dtype=np.uint8) | |
| ui.put_text(img, "HAND TRACKING DRAWING", (PAD, 54), 26, (255, 255, 255)) | |
| ui.put_text(img, "Select a mode", (PAD, 96), 17, (150, 150, 150)) | |
| for i, (_, label) in enumerate(ITEMS): | |
| y = TOP + i * ROW_H | |
| box = (PAD, y, W - PAD, y + ROW_H - 12) | |
| if i == self.index: | |
| cv2.rectangle(img, box[:2], box[2:], (45, 45, 45), -1) | |
| cv2.rectangle(img, box[:2], box[2:], (200, 200, 200), 1, cv2.LINE_AA) | |
| color = (255, 255, 255) | |
| else: | |
| cv2.rectangle(img, box[:2], box[2:], (70, 70, 70), 1, cv2.LINE_AA) | |
| color = (185, 185, 185) | |
| ui.put_text(img, f"{i + 1}) {label}", (PAD + 20, y + 12), 19, color) | |
| ui.put_text(img, "1..4 select W S move ENTER start Q quit", | |
| (PAD, H - 70), 16, (140, 140, 140)) | |
| if self.note: | |
| ui.put_text(img, self.note, (PAD, H - 42), 16, (120, 120, 230)) | |
| return img | |
| def run(self) -> str | None: | |
| """Show menu and return mode.""" | |
| cv2.namedWindow(WINDOW, cv2.WINDOW_NORMAL) | |
| cv2.resizeWindow(WINDOW, W, H) | |
| cv2.setMouseCallback(WINDOW, self.on_mouse) | |
| while True: | |
| cv2.imshow(WINDOW, self.frame()) | |
| key = cv2.waitKey(20) & 0xFF | |
| if cv2.getWindowProperty(WINDOW, cv2.WND_PROP_VISIBLE) < 1: | |
| return None | |
| chosen = -1 | |
| if self.click >= 0: | |
| chosen, self.click = self.click, -1 | |
| elif key in (ord("q"), 27): | |
| cv2.destroyWindow(WINDOW) | |
| cv2.waitKey(1) | |
| return None | |
| elif key in (ord("w"), 82): | |
| self.index = (self.index - 1) % len(ITEMS) | |
| elif key in (ord("s"), 84): | |
| self.index = (self.index + 1) % len(ITEMS) | |
| elif key in (13, 10, 32): | |
| chosen = self.index | |
| elif ord("1") <= key <= ord("0") + len(ITEMS): | |
| chosen = key - ord("1") | |
| if chosen < 0: | |
| continue | |
| self.index = chosen | |
| name = ITEMS[chosen][0] | |
| if name in ("2d", "3d", "poses"): | |
| cv2.destroyWindow(WINDOW) | |
| cv2.waitKey(1) | |
| return name | |
| self.note = f"{ITEMS[chosen][1]} is not available yet" | |