Bootstrap for windows
This commit is contained in:
parent
f1638afb09
commit
e31239f7aa
|
@ -0,0 +1,5 @@
|
|||
python3 -m venv env
|
||||
.\env\bin\activate.bat
|
||||
python3 -m pip install -r requirements.txt
|
||||
echo Ready
|
||||
pause
|
|
@ -0,0 +1,105 @@
|
|||
import sys
|
||||
import time
|
||||
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 save_score(score: int) -> None:
|
||||
with open('./.score', 'w') as score_file:
|
||||
score_file.write(str(score))
|
||||
|
||||
def start_game_sfx() -> Popen:
|
||||
return
|
||||
Popen(['paplay', './assets/sound/start.mp3']).communicate()
|
||||
time.sleep(.5)
|
||||
return Popen(['paplay', './assets/sound/background_music.mp3'])
|
||||
|
||||
def collect_sfx() -> None:
|
||||
pass # Popen(['paplay', './assets/sound/collect.mp3'])
|
||||
|
||||
def lost_sfx() -> None:
|
||||
pass # Popen(['paplay', './assets/sound/lost.mp3']).communicate()
|
||||
|
||||
def show_matrix() -> None:
|
||||
pass # Popen(['cmatrix'])
|
||||
|
||||
def initiate_rick() -> None:
|
||||
return
|
||||
Popen(['paplay', './assets/sound/rick.mp3'])
|
||||
cap = cv2.VideoCapture('./assets/video/rick2.mp4')
|
||||
fps: int = int(cap.get(cv2.CAP_PROP_FPS))
|
||||
desired_delay: float = 1 / fps
|
||||
|
||||
while True:
|
||||
start_time = time.time()
|
||||
ret, frame = cap.read()
|
||||
if not ret:
|
||||
break
|
||||
sys.stdout.buffer.write(frame.tobytes())
|
||||
elapsed_time = time.time() - start_time
|
||||
remaining_delay = max(desired_delay - elapsed_time, 0)
|
||||
time.sleep(remaining_delay)
|
||||
cap.release()
|
||||
|
||||
|
||||
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)
|
11
game.py
11
game.py
|
@ -22,8 +22,6 @@ def get_42_img(
|
|||
if len(img.shape) in [1, 2]:
|
||||
img = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
|
||||
|
||||
img = cv2.flip(img, 1)
|
||||
|
||||
img_height, img_width = img.shape[:2]
|
||||
img = img[
|
||||
margin_top:img_height-margin_bottom,
|
||||
|
@ -70,7 +68,7 @@ def add_directional_triangle(
|
|||
|
||||
# normalize
|
||||
norm = np.linalg.norm(dir_vector)
|
||||
dir_vector /= norm
|
||||
dir_vector /= (norm or 1)
|
||||
|
||||
# TODO: Fix type issue
|
||||
side_len *= norm / 15
|
||||
|
@ -96,6 +94,8 @@ def show_frame(frame: np.ndarray, to_stdout: bool=False) -> None:
|
|||
if to_stdout:
|
||||
sys.stdout.buffer.write(frame.tobytes())
|
||||
else:
|
||||
cv2.namedWindow("Image", cv2.WND_PROP_FULLSCREEN)
|
||||
cv2.setWindowProperty("Image", cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN)
|
||||
cv2.imshow("Image", frame)
|
||||
cv2.waitKey(1)
|
||||
|
||||
|
@ -103,7 +103,7 @@ def main() -> int:
|
|||
music = start_game_sfx()
|
||||
|
||||
capture: cv2.VideoCapture = cv2.VideoCapture(0)
|
||||
hands: mp.solutions.hands.Hands = mp_hands.Hands(max_num_hands=1)
|
||||
hands: mp.solutions.hands.Hands = mp_hands.Hands(max_num_hands=2)
|
||||
collected_42: bool = True
|
||||
noise_42img: int = 5
|
||||
img42_x: int = -img42_side_len - 1 - noise_42img
|
||||
|
@ -114,7 +114,7 @@ def main() -> int:
|
|||
finger_y: int = -1
|
||||
no_collect_ratio = 0
|
||||
no_finger_ratio = 0
|
||||
timer = 100
|
||||
timer = 1000
|
||||
|
||||
i: int = 0
|
||||
while True:
|
||||
|
@ -124,6 +124,7 @@ def main() -> int:
|
|||
if not success:
|
||||
continue
|
||||
|
||||
frame = cv2.flip(frame, 1)
|
||||
ratio = max(no_finger_ratio, no_collect_ratio)
|
||||
frame = cv2.addWeighted(frame, 1 - ratio, np.ones(frame.shape, dtype=frame.dtype), ratio, 0)
|
||||
if i > 30:
|
||||
|
|
|
@ -13,6 +13,7 @@ opencv-contrib-python==4.8.0.76
|
|||
opencv-python==4.8.0.76
|
||||
packaging==23.1
|
||||
Pillow==10.0.0
|
||||
playsound==1.3.0
|
||||
protobuf==3.20.3
|
||||
pycparser==2.21
|
||||
pyparsing==3.0.9
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#!/bin/sh
|
||||
# st -f 'SauceCodePro Nerd Font Mono:size=10' -e sh -c '{ ./game.py | 2>/dev/null ffmpeg -y -f rawvideo -s 640x480 -pix_fmt bgr24 -i - -map 0:V:0 -filter:v "format=gray,hflip" -c:v libx265 -preset ultrafast -tune zerolatency -crf 30 -f nut - | TERM=xterm-mono CACA_DRIVER=ncurses DISPLAY= mpv --really-quiet --no-cache --no-config --vo=caca --untimed --profile=low-latency - || { echo Error 1>&2; read X; }; } | ./game.py'
|
||||
# st -f 'SauceCodePro Nerd Font Mono:size=10' -e sh -c '{ ./game.py | 2>/dev/null ffmpeg -y -f rawvideo -s 640x480 -pix_fmt bgr24 -i - -map 0:V:0 -filter:v "format=gray,hflip" -c:v libx265 -preset ultrafast -tune zerolatency -crf 30 -f nut - | TERM=xterm-mono CACA_DRIVER=ncurses DISPLAY= mpv --really-quiet --no-cache --no-config --vo=caca --untimed --profile=low-latency - || { echo Error 1>&2; read X; }; }'
|
||||
# st -f 'SauceCodePro Nerd Font Mono:size=10' -e sh -c '{ ./game.py | 2>/dev/null ffmpeg -y -f rawvideo -s 640x480 -pix_fmt bgr24 -i - -map 0:V:0 -filter:v "format=gray,hflip" -c:v libx264 -preset ultrafast -tune zerolatency -crf 30 -f nut - | TERM=xterm-mono CACA_DRIVER=ncurses DISPLAY= mpv --really-quiet --no-cache --no-config --vo=tct --untimed --profile=low-latency - || { echo Error 1>&2; read X; }; }'
|
||||
# st -f 'SauceCodePro Nerd Font Mono:size=10' -e sh -c '{ ./game.py | 2>/dev/null ffmpeg -y -f rawvideo -s 640x480 -pix_fmt bgr24 -i - -map 0:V:0 -filter:v "format=gray" -c:v libx265 -preset ultrafast -tune zerolatency -crf 30 -f nut - | TERM=xterm-mono CACA_DRIVER=ncurses DISPLAY= mpv --really-quiet --no-cache --no-config --vo=caca --untimed --profile=low-latency - || { echo Error 1>&2; read X; }; } | ./game.py'
|
||||
# st -f 'SauceCodePro Nerd Font Mono:size=10' -e sh -c '{ ./game.py | 2>/dev/null ffmpeg -y -f rawvideo -s 640x480 -pix_fmt bgr24 -i - -map 0:V:0 -filter:v "format=gray" -c:v libx265 -preset ultrafast -tune zerolatency -crf 30 -f nut - | TERM=xterm-mono CACA_DRIVER=ncurses DISPLAY= mpv --really-quiet --no-cache --no-config --vo=caca --untimed --profile=low-latency - || { echo Error 1>&2; read X; }; }'
|
||||
# st -f 'SauceCodePro Nerd Font Mono:size=10' -e sh -c '{ ./game.py | 2>/dev/null ffmpeg -y -f rawvideo -s 640x480 -pix_fmt bgr24 -i - -map 0:V:0 -filter:v "format=gray" -c:v libx264 -preset ultrafast -tune zerolatency -crf 30 -f nut - | TERM=xterm-mono CACA_DRIVER=ncurses DISPLAY= mpv --really-quiet --no-cache --no-config --vo=tct --untimed --profile=low-latency - || { echo Error 1>&2; read X; }; }'
|
||||
|
||||
TERM_FONT='SauceCodePro Nerd Font Mono'
|
||||
TERM_FONT_SIZE='10'
|
||||
|
@ -21,7 +21,7 @@ xterm \
|
|||
-pix_fmt bgr24 \
|
||||
-i - \
|
||||
-map 0:V:0 \
|
||||
-filter:v "format=gray,hflip" \
|
||||
-filter:v "format=gray" \
|
||||
-c:v libx265 \
|
||||
-preset ultrafast \
|
||||
-tune zerolatency \
|
||||
|
|
18
utils.py
18
utils.py
|
@ -4,11 +4,12 @@ from enum import Enum
|
|||
from subprocess import Popen
|
||||
from typing import Generator
|
||||
from types import ModuleType
|
||||
import threading
|
||||
|
||||
import numpy as np
|
||||
import mediapipe as mp
|
||||
import cv2
|
||||
from cv2 import VideoCapture
|
||||
from playsound import playsound
|
||||
|
||||
mp_hands = mp.solutions.hands
|
||||
mp_draw: ModuleType = mp.solutions.drawing_utils
|
||||
|
@ -40,22 +41,23 @@ def save_score(score: int) -> None:
|
|||
with open('./.score', 'w') as score_file:
|
||||
score_file.write(str(score))
|
||||
|
||||
def start_game_sfx() -> Popen:
|
||||
Popen(['paplay', './assets/sound/start.mp3']).communicate()
|
||||
def start_game_sfx() -> None:
|
||||
playsound('./assets/sound/start.mp3')
|
||||
time.sleep(.5)
|
||||
return Popen(['paplay', './assets/sound/background_music.mp3'])
|
||||
threading.Thread(target=playsound, args=('./assets/sound/background_music.mp3',), daemon=True).start()
|
||||
|
||||
def collect_sfx() -> None:
|
||||
Popen(['paplay', './assets/sound/collect.mp3'])
|
||||
pass
|
||||
threading.Thread(target=playsound, args=('./assets/sound/collect.mp3',), daemon=True).start()
|
||||
|
||||
def lost_sfx() -> None:
|
||||
Popen(['paplay', './assets/sound/lost.mp3']).communicate()
|
||||
playsound('./assets/sound/lost.mp3')
|
||||
|
||||
def show_matrix() -> None:
|
||||
Popen(['tmatrix'])
|
||||
|
||||
def initiate_rick() -> None:
|
||||
Popen(['paplay', './assets/sound/rick.mp3'])
|
||||
threading.Thread(target=playsound, args=('./assets/sound/rick.mp3',), daemon=True).start()
|
||||
cap = cv2.VideoCapture('./assets/video/rick2.mp4')
|
||||
fps: int = int(cap.get(cv2.CAP_PROP_FPS))
|
||||
desired_delay: float = 1 / fps
|
||||
|
@ -73,7 +75,7 @@ def initiate_rick() -> None:
|
|||
|
||||
|
||||
def found_hands() -> bool:
|
||||
capture: VideoCapture = cv2.VideoCapture(0)
|
||||
capture: cv2.VideoCapture = cv2.VideoCapture(0)
|
||||
hands = mp_hands.Hands(max_num_hands=1)
|
||||
success, frame = capture.read()
|
||||
if not success:
|
||||
|
|
Loading…
Reference in New Issue