Let's see...

This commit is contained in:
cubernetes 2023-08-11 02:49:49 +02:00
parent b0d21d30a3
commit 15b53cd262
4 changed files with 104 additions and 84 deletions

85
game.py
View File

@ -2,39 +2,12 @@
import sys import sys
import random import random
from time import sleep
from enum import Enum
from typing import NoReturn, Generator
from types import ModuleType
from subprocess import Popen
import numpy as np import numpy as np
import mediapipe as mp
import cv2 import cv2
from cv2 import VideoCapture from cv2 import VideoCapture
class FingerType(Enum): from utils import *
BASE = 0
BASE_RIGHT = 1
THUMB_BASE = 2
THUMB_KNUCKLE_1 = 3
THUMB_TIP = 4
INDEX_BASE = 5
INDEX_KNUCKLE_1 = 6
INDEX_KNUCKLE_2 = 7
INDEX_TIP = 8
MIDDLE_BASE = 9
MIDDLE_KNUCKLE_1 = 10
MIDDLE_KNUCKLE_2 = 11
MIDDLE_TIP = 12
RING_BASE = 13
RING_KNUCKLE_1 = 14
RING_KNUCKLE_2 = 15
RING_TIP = 16
PINKY_BASE = 17
PINKY_KNUCKLE_1 = 18
PINKY_KNUCKLE_2 = 19
PINKY_TIP = 20
def get_42_img( def get_42_img(
img_path: str, img_path: str,
@ -65,9 +38,6 @@ def get_42_img(
return img return img
mp_hands = mp.solutions.hands
mp_draw: ModuleType = mp.solutions.drawing_utils
img42_side_len = 70 img42_side_len = 70
img42: np.ndarray = get_42_img( img42: np.ndarray = get_42_img(
"./assets/img/42.png", "./assets/img/42.png",
@ -118,27 +88,6 @@ def add_directional_triangle(
return apex_vertex return apex_vertex
def get_finger_positions(
frame: np.ndarray,
hands: mp.solutions.hands.Hands,
add_landmarks: bool=False,
) -> Generator[list[tuple[int, int, int]], None, None]:
height, width = frame.shape[:2]
img_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
results = hands.process(img_rgb)
if results.multi_hand_landmarks:
for hand_landmarks in results.multi_hand_landmarks:
positions = []
for id, lm in enumerate(hand_landmarks.landmark):
x = int(lm.x * width)
y = int(lm.y * height)
positions.append((FingerType(id), x, y))
yield positions
if add_landmarks:
mp_draw.draw_landmarks(frame, hand_landmarks, mp_hands.HAND_CONNECTIONS)
def show_frame(frame: np.ndarray, to_stdout: bool=False) -> None: def show_frame(frame: np.ndarray, to_stdout: bool=False) -> None:
if to_stdout: if to_stdout:
sys.stdout.buffer.write(frame.tobytes()) sys.stdout.buffer.write(frame.tobytes())
@ -146,25 +95,7 @@ def show_frame(frame: np.ndarray, to_stdout: bool=False) -> None:
cv2.imshow("Image", frame) cv2.imshow("Image", frame)
cv2.waitKey(1) cv2.waitKey(1)
def collect_sfx() -> None: def main() -> int:
Popen(['paplay', './assets/sfx/collect.mp3'])
def start_sfx() -> None:
Popen(['paplay', './assets/sfx/start.mp3'])
def show_matrix(term_dev: str) -> None:
Popen(['sh', '-c', '2>/dev/null tmatrix 1>"' + term_dev + '"'])
def found_hands() -> bool:
capture: VideoCapture = cv2.VideoCapture(0)
hands = mp_hands.Hands(max_num_hands=1)
success, frame = capture.read()
if not success:
return False
return list(get_finger_positions(frame, hands)) != []
def game_loop() -> int:
start_sfx() start_sfx()
capture: VideoCapture = cv2.VideoCapture(0) capture: VideoCapture = cv2.VideoCapture(0)
@ -214,15 +145,5 @@ def game_loop() -> int:
show_frame(frame, to_stdout=(not sys.stdout.isatty())) show_frame(frame, to_stdout=(not sys.stdout.isatty()))
i += 1 i += 1
def main() -> NoReturn:
if len(sys.argv) != 2:
print(f'Usage: {sys.argv[0]} TERMINAL_DEVICE')
sys.exit(1)
show_matrix(sys.argv[1])
while True:
if found_hands():
game_loop()
sleep(1)
if __name__ == '__main__': if __name__ == '__main__':
main() sys.exit(main())

25
start.py Normal file
View File

@ -0,0 +1,25 @@
#!/usr/bin/env python3
import sys
from time import sleep
from typing import NoReturn
from utils import *
def start_game() -> int:
proc = Popen(['./game.py'])
proc.communicate()
return proc.returncode
def main() -> NoReturn:
if len(sys.argv) != 2:
print(f'Usage: {sys.argv[0]} TERMINAL_DEVICE')
sys.exit(1)
show_matrix(sys.argv[1])
while True:
if found_hands():
start_game()
sleep(1)
if __name__ == '__main__':
main()

View File

@ -6,7 +6,6 @@
TERM_FONT='SauceCodePro Nerd Font Mono' TERM_FONT='SauceCodePro Nerd Font Mono'
TERM_FONT_SIZE='10' TERM_FONT_SIZE='10'
OUT_TERM='xterm-mono' OUT_TERM='xterm-mono'
TERM_DEV="$(tty)"
xterm \ xterm \
-bg black \ -bg black \
-fg white \ -fg white \
@ -14,7 +13,7 @@ xterm \
-fa "${TERM_FONT}" \ -fa "${TERM_FONT}" \
-fs "${TERM_FONT_SIZE}" \ -fs "${TERM_FONT_SIZE}" \
-e '{ -e '{
./game.py "'"${TERM_DEV}"'" | ./game.py |
2>/dev/null ffmpeg -y \ 2>/dev/null ffmpeg -y \
-f rawvideo \ -f rawvideo \
-s 640x480 \ -s 640x480 \

75
utils.py Normal file
View File

@ -0,0 +1,75 @@
from enum import Enum
from subprocess import Popen
from typing import Generator
from types import ModuleType
import numpy as np
import mediapipe as mp
import cv2
from cv2 import VideoCapture
mp_hands = mp.solutions.hands
mp_draw: ModuleType = mp.solutions.drawing_utils
class FingerType(Enum):
BASE = 0
BASE_RIGHT = 1
THUMB_BASE = 2
THUMB_KNUCKLE_1 = 3
THUMB_TIP = 4
INDEX_BASE = 5
INDEX_KNUCKLE_1 = 6
INDEX_KNUCKLE_2 = 7
INDEX_TIP = 8
MIDDLE_BASE = 9
MIDDLE_KNUCKLE_1 = 10
MIDDLE_KNUCKLE_2 = 11
MIDDLE_TIP = 12
RING_BASE = 13
RING_KNUCKLE_1 = 14
RING_KNUCKLE_2 = 15
RING_TIP = 16
PINKY_BASE = 17
PINKY_KNUCKLE_1 = 18
PINKY_KNUCKLE_2 = 19
PINKY_TIP = 20
def collect_sfx() -> None:
Popen(['paplay', './assets/sfx/collect.mp3'])
def start_sfx() -> None:
Popen(['paplay', './assets/sfx/start.mp3'])
def show_matrix(term_dev: str) -> None:
Popen(['sh', '-c', '2>/dev/null tmatrix 1>"' + term_dev + '"'])
def found_hands() -> bool:
capture: VideoCapture = cv2.VideoCapture(0)
hands = mp_hands.Hands(max_num_hands=1)
success, frame = capture.read()
if not success:
return False
return list(get_finger_positions(frame, hands)) != []
def get_finger_positions(
frame: np.ndarray,
hands: mp.solutions.hands.Hands,
add_landmarks: bool=False,
) -> Generator[list[tuple[int, int, int]], None, None]:
height, width = frame.shape[:2]
img_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
results = hands.process(img_rgb)
if results.multi_hand_landmarks:
for hand_landmarks in results.multi_hand_landmarks:
positions = []
for id, lm in enumerate(hand_landmarks.landmark):
x = int(lm.x * width)
y = int(lm.y * height)
positions.append((FingerType(id), x, y))
yield positions
if add_landmarks:
mp_draw.draw_landmarks(frame, hand_landmarks, mp_hands.HAND_CONNECTIONS)