Let's see...
This commit is contained in:
parent
b0d21d30a3
commit
15b53cd262
85
game.py
85
game.py
|
@ -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())
|
||||||
|
|
|
@ -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()
|
|
@ -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 \
|
||||||
|
|
|
@ -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)
|
Loading…
Reference in New Issue