mirror of
https://github.com/EyeTrackVR/EyeTrackVR.git
synced 2025-11-04 14:39:42 +08:00
Merge pull request #81 from Blu3u/feature/usb_improvements
Improvements in tracking over USB, added taskipy, colorama, and realtime tracking info display
This commit is contained in:
commit
c5a9842dc7
@ -1,13 +1,14 @@
|
|||||||
from config import EyeTrackConfig
|
|
||||||
from enum import Enum
|
|
||||||
import cv2
|
import cv2
|
||||||
|
import numpy as np
|
||||||
import queue
|
import queue
|
||||||
import serial
|
import serial
|
||||||
import serial.tools.list_ports
|
import serial.tools.list_ports
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
|
|
||||||
import numpy as np
|
from colorama import Fore
|
||||||
|
from config import EyeTrackConfig
|
||||||
|
from enum import Enum
|
||||||
|
|
||||||
WAIT_TIME = 0.1
|
WAIT_TIME = 0.1
|
||||||
|
|
||||||
@ -52,20 +53,23 @@ class Camera:
|
|||||||
self.last_frame_time = time.time()
|
self.last_frame_time = time.time()
|
||||||
self.frame_number = 0
|
self.frame_number = 0
|
||||||
self.fps = 0
|
self.fps = 0
|
||||||
|
self.bps = 0
|
||||||
self.start = True
|
self.start = True
|
||||||
self.buffer = b''
|
self.buffer = b''
|
||||||
|
|
||||||
self.error_message = "\033[93m[WARN] Capture source {} not found, retrying...\033[0m"
|
self.error_message = f"{Fore.YELLOW}[WARN] Capture source {{}} not found, retrying...{Fore.RESET}"
|
||||||
|
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
if self.serial_connection is not None:
|
if self.serial_connection is not None:
|
||||||
self.serial_connection.close()
|
self.serial_connection.close()
|
||||||
|
|
||||||
def set_output_queue(self, camera_output_outgoing: "queue.Queue"):
|
def set_output_queue(self, camera_output_outgoing: "queue.Queue"):
|
||||||
self.camera_output_outgoing = camera_output_outgoing
|
self.camera_output_outgoing = camera_output_outgoing
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
while True:
|
while True:
|
||||||
if self.cancellation_event.is_set():
|
if self.cancellation_event.is_set():
|
||||||
print("\033[94m[INFO] Exiting Capture thread\033[0m")
|
print(f"{Fore.CYAN}[INFO] Exiting Capture thread{Fore.RESET}")
|
||||||
return
|
return
|
||||||
should_push = True
|
should_push = True
|
||||||
# If things aren't open, retry until they are. Don't let read requests come in any earlier
|
# If things aren't open, retry until they are. Don't let read requests come in any earlier
|
||||||
@ -125,10 +129,11 @@ class Camera:
|
|||||||
raise RuntimeError("Problem while getting frame")
|
raise RuntimeError("Problem while getting frame")
|
||||||
frame_number = self.wired_camera.get(cv2.CAP_PROP_POS_FRAMES)
|
frame_number = self.wired_camera.get(cv2.CAP_PROP_POS_FRAMES)
|
||||||
self.fps = self.wired_camera.get(cv2.CAP_PROP_FPS)
|
self.fps = self.wired_camera.get(cv2.CAP_PROP_FPS)
|
||||||
|
self.bps = image.nbytes
|
||||||
if should_push:
|
if should_push:
|
||||||
self.push_image_to_queue(image, frame_number, self.fps)
|
self.push_image_to_queue(image, frame_number, self.fps)
|
||||||
except:
|
except:
|
||||||
print("\033[93m[WARN] Capture source problem, assuming camera disconnected, waiting for reconnect.\033[0m")
|
print(f"{Fore.YELLOW}[WARN] Capture source problem, assuming camera disconnected, waiting for reconnect.{Fore.RESET}")
|
||||||
self.camera_status = CameraState.DISCONNECTED
|
self.camera_status = CameraState.DISCONNECTED
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -153,34 +158,37 @@ class Camera:
|
|||||||
return jpeg
|
return jpeg
|
||||||
|
|
||||||
def get_serial_camera_picture(self, should_push):
|
def get_serial_camera_picture(self, should_push):
|
||||||
|
conn = self.serial_connection
|
||||||
|
if conn is None:
|
||||||
|
return
|
||||||
try:
|
try:
|
||||||
if self.serial_connection.in_waiting:
|
if conn.in_waiting:
|
||||||
jpeg = self.get_next_jpeg_frame()
|
jpeg = self.get_next_jpeg_frame()
|
||||||
if jpeg:
|
if jpeg:
|
||||||
# Create jpeg frame from byte string
|
# Create jpeg frame from byte string
|
||||||
image = cv2.imdecode(np.fromstring(jpeg, dtype=np.uint8), cv2.IMREAD_UNCHANGED)
|
image = cv2.imdecode(np.fromstring(jpeg, dtype=np.uint8), cv2.IMREAD_UNCHANGED)
|
||||||
if image is None:
|
if image is None:
|
||||||
print("image not found")
|
print(f"{Fore.YELLOW}[WARN] Frame drop. Corrupted JPEG.{Fore.RESET}")
|
||||||
return
|
return
|
||||||
# Discard the serial buffer. This is due to the fact that it
|
# Discard the serial buffer. This is due to the fact that it
|
||||||
# may build up some outdated frames. A bit of a workaround here tbh.
|
# may build up some outdated frames. A bit of a workaround here tbh.
|
||||||
self.serial_connection.reset_input_buffer()
|
if conn.in_waiting >= 32768:
|
||||||
self.buffer = b''
|
print(f"{Fore.CYAN}[INFO] Discarding the serial buffer ({conn.in_waiting} bytes){Fore.RESET}")
|
||||||
|
conn.reset_input_buffer()
|
||||||
|
self.buffer = b''
|
||||||
# Calculate the fps.
|
# Calculate the fps.
|
||||||
current_frame_time = time.time()
|
current_frame_time = time.time()
|
||||||
delta_time = current_frame_time - self.last_frame_time
|
delta_time = current_frame_time - self.last_frame_time
|
||||||
self.last_frame_time = current_frame_time
|
self.last_frame_time = current_frame_time
|
||||||
if delta_time > 0:
|
if delta_time > 0:
|
||||||
self.fps = 1 / delta_time
|
self.fps = 1 / delta_time
|
||||||
|
self.bps = len(jpeg) / delta_time
|
||||||
self.frame_number = self.frame_number + 1
|
self.frame_number = self.frame_number + 1
|
||||||
if should_push:
|
if should_push:
|
||||||
self.push_image_to_queue(image, self.frame_number, self.fps)
|
self.push_image_to_queue(image, self.frame_number, self.fps)
|
||||||
|
|
||||||
except UnboundLocalError as ex:
|
|
||||||
print(ex)
|
|
||||||
except Exception:
|
except Exception:
|
||||||
print("\033[93m[WARN]Serial capture source problem, assuming camera disconnected, waiting for reconnect.\033[0m")
|
print(f"{Fore.YELLOW}[WARN] Serial capture source problem, assuming camera disconnected, waiting for reconnect.{Fore.RESET}")
|
||||||
self.serial_connection.close()
|
conn.close()
|
||||||
self.camera_status = CameraState.DISCONNECTED
|
self.camera_status = CameraState.DISCONNECTED
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -202,13 +210,14 @@ class Camera:
|
|||||||
xonxoff=False,
|
xonxoff=False,
|
||||||
dsrdtr=False,
|
dsrdtr=False,
|
||||||
rtscts=False)
|
rtscts=False)
|
||||||
|
# Set explicit buffer size for serial.
|
||||||
|
conn.set_buffer_size(rx_size = 32768, tx_size = 32768)
|
||||||
|
|
||||||
conn.reset_input_buffer()
|
print(f"{Fore.CYAN}[INFO] ETVR Serial Tracker device connected on {port}{Fore.RESET}")
|
||||||
|
|
||||||
print(f"\033[94m[INFO] Serial Tracker successfully connected on {port}\033[0m")
|
|
||||||
self.serial_connection = conn
|
self.serial_connection = conn
|
||||||
self.camera_status = CameraState.CONNECTED
|
self.camera_status = CameraState.CONNECTED
|
||||||
except Exception:
|
except Exception:
|
||||||
|
print(f"{Fore.CYAN}[INFO] Failed to connect on {port}{Fore.RESET}")
|
||||||
self.camera_status = CameraState.DISCONNECTED
|
self.camera_status = CameraState.DISCONNECTED
|
||||||
|
|
||||||
def push_image_to_queue(self, image, frame_number, fps):
|
def push_image_to_queue(self, image, frame_number, fps):
|
||||||
@ -217,6 +226,6 @@ class Camera:
|
|||||||
qsize = self.camera_output_outgoing.qsize()
|
qsize = self.camera_output_outgoing.qsize()
|
||||||
if qsize > 1:
|
if qsize > 1:
|
||||||
print(
|
print(
|
||||||
f"\033[91m[WARN] CAPTURE QUEUE BACKPRESSURE OF {qsize}. CHECK FOR CRASH OR TIMING ISSUES IN ALGORITHM.\033[0m")
|
f"{Fore.YELLOW}[WARN] CAPTURE QUEUE BACKPRESSURE OF {qsize}. CHECK FOR CRASH OR TIMING ISSUES IN ALGORITHM.{Fore.RESET}")
|
||||||
self.camera_output_outgoing.put((image, frame_number, fps))
|
self.camera_output_outgoing.put((image, frame_number, fps))
|
||||||
self.capture_event.clear()
|
self.capture_event.clear()
|
||||||
|
|||||||
@ -1,8 +1,9 @@
|
|||||||
import PySimpleGUI as sg
|
import PySimpleGUI as sg
|
||||||
from config import EyeTrackConfig
|
from config import EyeTrackConfig
|
||||||
from config import EyeTrackSettingsConfig
|
from config import EyeTrackSettingsConfig
|
||||||
|
from collections import deque
|
||||||
from threading import Event, Thread
|
from threading import Event, Thread
|
||||||
from eye_processor import EyeProcessor, InformationOrigin
|
from eye_processor import EyeProcessor, EyeInfoOrigin
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from queue import Queue, Empty
|
from queue import Queue, Empty
|
||||||
from camera import Camera, CameraState
|
from camera import Camera, CameraState
|
||||||
@ -24,6 +25,8 @@ class CameraWidget:
|
|||||||
self.gui_save_tracking_button = f"-SAVETRACKINGBUTTON{widget_id}-"
|
self.gui_save_tracking_button = f"-SAVETRACKINGBUTTON{widget_id}-"
|
||||||
self.gui_tracking_layout = f"-TRACKINGLAYOUT{widget_id}-"
|
self.gui_tracking_layout = f"-TRACKINGLAYOUT{widget_id}-"
|
||||||
self.gui_tracking_image = f"-IMAGE{widget_id}-"
|
self.gui_tracking_image = f"-IMAGE{widget_id}-"
|
||||||
|
self.gui_tracking_fps = f"-TRACKINGFPS{widget_id}-"
|
||||||
|
self.gui_tracking_bps = f"-TRACKINGBPS{widget_id}-"
|
||||||
self.gui_output_graph = f"-OUTPUTGRAPH{widget_id}-"
|
self.gui_output_graph = f"-OUTPUTGRAPH{widget_id}-"
|
||||||
self.gui_restart_calibration = f"-RESTARTCALIBRATION{widget_id}-"
|
self.gui_restart_calibration = f"-RESTARTCALIBRATION{widget_id}-"
|
||||||
self.gui_stop_calibration = f"-STOPCALIBRATION{widget_id}-"
|
self.gui_stop_calibration = f"-STOPCALIBRATION{widget_id}-"
|
||||||
@ -46,6 +49,35 @@ class CameraWidget:
|
|||||||
else:
|
else:
|
||||||
raise RuntimeError("\033[91m[WARN] Cannot have a camera widget represent both eyes!\033[0m")
|
raise RuntimeError("\033[91m[WARN] Cannot have a camera widget represent both eyes!\033[0m")
|
||||||
|
|
||||||
|
self.cancellation_event = Event()
|
||||||
|
# Set the event until start is called, otherwise we can block if shutdown is called.
|
||||||
|
self.cancellation_event.set()
|
||||||
|
self.capture_event = Event()
|
||||||
|
self.capture_queue = Queue()
|
||||||
|
self.roi_queue = Queue()
|
||||||
|
|
||||||
|
self.image_queue = Queue()
|
||||||
|
|
||||||
|
self.ransac = EyeProcessor(
|
||||||
|
self.config,
|
||||||
|
self.settings_config,
|
||||||
|
self.cancellation_event,
|
||||||
|
self.capture_event,
|
||||||
|
self.capture_queue,
|
||||||
|
self.image_queue,
|
||||||
|
self.eye_id,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.camera_status_queue = Queue()
|
||||||
|
self.camera = Camera(
|
||||||
|
self.config,
|
||||||
|
0,
|
||||||
|
self.cancellation_event,
|
||||||
|
self.capture_event,
|
||||||
|
self.camera_status_queue,
|
||||||
|
self.capture_queue,
|
||||||
|
)
|
||||||
|
|
||||||
self.roi_layout = [
|
self.roi_layout = [
|
||||||
[
|
[
|
||||||
sg.Graph(
|
sg.Graph(
|
||||||
@ -82,6 +114,8 @@ class CameraWidget:
|
|||||||
[
|
[
|
||||||
sg.Text("Mode:", background_color='#424042'),
|
sg.Text("Mode:", background_color='#424042'),
|
||||||
sg.Text("Calibrating", key=self.gui_mode_readout, background_color='#424042'),
|
sg.Text("Calibrating", key=self.gui_mode_readout, background_color='#424042'),
|
||||||
|
sg.Text("", key=self.gui_tracking_fps, background_color='#424042'),
|
||||||
|
sg.Text("", key=self.gui_tracking_bps, background_color='#424042'),
|
||||||
# sg.Checkbox(
|
# sg.Checkbox(
|
||||||
# "Circle crop:",
|
# "Circle crop:",
|
||||||
# default=self.config.gui_circular_crop,
|
# default=self.config.gui_circular_crop,
|
||||||
@ -123,40 +157,23 @@ class CameraWidget:
|
|||||||
],
|
],
|
||||||
]
|
]
|
||||||
|
|
||||||
self.cancellation_event = Event()
|
|
||||||
# Set the event until start is called, otherwise we can block if shutdown is called.
|
|
||||||
self.cancellation_event.set()
|
|
||||||
self.capture_event = Event()
|
|
||||||
self.capture_queue = Queue()
|
|
||||||
self.roi_queue = Queue()
|
|
||||||
|
|
||||||
self.image_queue = Queue()
|
|
||||||
|
|
||||||
self.ransac = EyeProcessor(
|
|
||||||
self.config,
|
|
||||||
self.settings_config,
|
|
||||||
self.cancellation_event,
|
|
||||||
self.capture_event,
|
|
||||||
self.capture_queue,
|
|
||||||
self.image_queue,
|
|
||||||
self.eye_id,
|
|
||||||
)
|
|
||||||
|
|
||||||
self.camera_status_queue = Queue()
|
|
||||||
self.camera = Camera(
|
|
||||||
self.config,
|
|
||||||
0,
|
|
||||||
self.cancellation_event,
|
|
||||||
self.capture_event,
|
|
||||||
self.camera_status_queue,
|
|
||||||
self.capture_queue,
|
|
||||||
)
|
|
||||||
|
|
||||||
self.x0, self.y0 = None, None
|
self.x0, self.y0 = None, None
|
||||||
self.x1, self.y1 = None, None
|
self.x1, self.y1 = None, None
|
||||||
self.figure = None
|
self.figure = None
|
||||||
self.is_mouse_up = True
|
self.is_mouse_up = True
|
||||||
self.in_roi_mode = False
|
self.in_roi_mode = False
|
||||||
|
self.movavg_fps_queue = deque(maxlen=120)
|
||||||
|
self.movavg_bps_queue = deque(maxlen=120)
|
||||||
|
|
||||||
|
def _movavg_fps(self, next_fps):
|
||||||
|
self.movavg_fps_queue.append(next_fps)
|
||||||
|
fps = round(sum(self.movavg_fps_queue) / len(self.movavg_fps_queue))
|
||||||
|
millisec = round((1 / fps if fps else 0) * 1000)
|
||||||
|
return f"{fps} Fps {millisec} ms"
|
||||||
|
|
||||||
|
def _movavg_bps(self, next_bps):
|
||||||
|
self.movavg_bps_queue.append(next_bps)
|
||||||
|
return f"{sum(self.movavg_bps_queue) / len(self.movavg_bps_queue) * 0.001 * 0.001 * 8:.3f} Mbps"
|
||||||
|
|
||||||
def started(self):
|
def started(self):
|
||||||
return not self.cancellation_event.is_set()
|
return not self.cancellation_event.is_set()
|
||||||
@ -261,6 +278,10 @@ class CameraWidget:
|
|||||||
|
|
||||||
needs_roi_set = self.config.roi_window_h <= 0 or self.config.roi_window_w <= 0
|
needs_roi_set = self.config.roi_window_h <= 0 or self.config.roi_window_w <= 0
|
||||||
|
|
||||||
|
# TODO: Refactor if statements below...
|
||||||
|
window[self.gui_tracking_fps].update('')
|
||||||
|
window[self.gui_tracking_bps].update('')
|
||||||
|
|
||||||
if self.config.capture_source is None or self.config.capture_source == "":
|
if self.config.capture_source is None or self.config.capture_source == "":
|
||||||
window[self.gui_mode_readout].update("Waiting for camera address")
|
window[self.gui_mode_readout].update("Waiting for camera address")
|
||||||
window[self.gui_roi_message].update(visible=False)
|
window[self.gui_roi_message].update(visible=False)
|
||||||
@ -275,6 +296,8 @@ class CameraWidget:
|
|||||||
window[self.gui_mode_readout].update("Calibration")
|
window[self.gui_mode_readout].update("Calibration")
|
||||||
else:
|
else:
|
||||||
window[self.gui_mode_readout].update("Tracking")
|
window[self.gui_mode_readout].update("Tracking")
|
||||||
|
window[self.gui_tracking_fps].update(self._movavg_fps(self.camera.fps))
|
||||||
|
window[self.gui_tracking_bps].update(self._movavg_bps(self.camera.bps))
|
||||||
|
|
||||||
if self.in_roi_mode:
|
if self.in_roi_mode:
|
||||||
try:
|
try:
|
||||||
@ -312,7 +335,7 @@ class CameraWidget:
|
|||||||
graph = window[self.gui_output_graph]
|
graph = window[self.gui_output_graph]
|
||||||
graph.erase()
|
graph.erase()
|
||||||
|
|
||||||
if eye_info.info_type != InformationOrigin.FAILURE: #and not eye_info.blink:
|
if eye_info.info_type != EyeInfoOrigin.FAILURE: #and not eye_info.blink:
|
||||||
graph.update(background_color="white")
|
graph.update(background_color="white")
|
||||||
if not np.isnan(eye_info.x) and not np.isnan(eye_info.y):
|
if not np.isnan(eye_info.x) and not np.isnan(eye_info.y):
|
||||||
|
|
||||||
@ -332,10 +355,10 @@ class CameraWidget:
|
|||||||
|
|
||||||
# elif eye_info.blink:
|
# elif eye_info.blink:
|
||||||
# graph.update(background_color="#6f4ca1")
|
# graph.update(background_color="#6f4ca1")
|
||||||
elif eye_info.info_type == InformationOrigin.FAILURE:
|
elif eye_info.info_type == EyeInfoOrigin.FAILURE:
|
||||||
graph.update(background_color="red")
|
graph.update(background_color="red")
|
||||||
# Relay information to OSC
|
# Relay information to OSC
|
||||||
if eye_info.info_type != InformationOrigin.FAILURE:
|
if eye_info.info_type != EyeInfoOrigin.FAILURE:
|
||||||
self.osc_queue.put((self.eye_id, eye_info))
|
self.osc_queue.put((self.eye_id, eye_info))
|
||||||
except Empty:
|
except Empty:
|
||||||
pass
|
pass
|
||||||
|
|||||||
@ -1,10 +1,11 @@
|
|||||||
from typing import Union, Dict
|
|
||||||
from osc import EyeId
|
|
||||||
import os.path
|
|
||||||
import json
|
import json
|
||||||
from pydantic import BaseModel
|
import os.path
|
||||||
import shutil
|
import shutil
|
||||||
|
|
||||||
|
from eye import EyeId
|
||||||
|
from pydantic import BaseModel
|
||||||
|
from typing import Union
|
||||||
|
|
||||||
CONFIG_FILE_NAME: str = "eyetrack_settings.json"
|
CONFIG_FILE_NAME: str = "eyetrack_settings.json"
|
||||||
BACKUP_CONFIG_FILE_NAME: str = "eyetrack_settings.backup"
|
BACKUP_CONFIG_FILE_NAME: str = "eyetrack_settings.backup"
|
||||||
|
|
||||||
|
|||||||
26
EyeTrackApp/eye.py
Normal file
26
EyeTrackApp/eye.py
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
from dataclasses import dataclass
|
||||||
|
from enum import Enum, IntEnum
|
||||||
|
|
||||||
|
class EyeId(IntEnum):
|
||||||
|
RIGHT = 0
|
||||||
|
LEFT = 1
|
||||||
|
BOTH = 2
|
||||||
|
SETTINGS = 3
|
||||||
|
|
||||||
|
|
||||||
|
class EyeInfoOrigin(Enum):
|
||||||
|
RANSAC = 1
|
||||||
|
BLOB = 2
|
||||||
|
FAILURE = 3
|
||||||
|
HSF = 4
|
||||||
|
HSRAC = 5
|
||||||
|
DADDY = 6
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class EyeInfo:
|
||||||
|
info_type: EyeInfoOrigin
|
||||||
|
x: float
|
||||||
|
y: float
|
||||||
|
pupil_dialation: float
|
||||||
|
blink: float
|
||||||
@ -59,29 +59,9 @@ from ransac import *
|
|||||||
from hsrac import External_Run_HSRACS
|
from hsrac import External_Run_HSRACS
|
||||||
from blink import *
|
from blink import *
|
||||||
|
|
||||||
|
from eye import EyeInfo, EyeInfoOrigin
|
||||||
from intensity_eye_open import *
|
from intensity_eye_open import *
|
||||||
|
|
||||||
class InformationOrigin(Enum):
|
|
||||||
RANSAC = 1
|
|
||||||
BLOB = 2
|
|
||||||
FAILURE = 3
|
|
||||||
HSF = 4
|
|
||||||
HSRAC = 5
|
|
||||||
DADDY = 6
|
|
||||||
|
|
||||||
bbb = 0
|
|
||||||
@dataclass
|
|
||||||
class EyeInformation:
|
|
||||||
info_type: InformationOrigin
|
|
||||||
x: float
|
|
||||||
y: float
|
|
||||||
pupil_dialation: float
|
|
||||||
blink: float
|
|
||||||
|
|
||||||
|
|
||||||
lowb = np.array(0)
|
|
||||||
|
|
||||||
|
|
||||||
def run_once(f):
|
def run_once(f):
|
||||||
def wrapper(*args, **kwargs):
|
def wrapper(*args, **kwargs):
|
||||||
@ -179,8 +159,8 @@ class EyeProcessor:
|
|||||||
self.prev_x = None
|
self.prev_x = None
|
||||||
self.prev_y = None
|
self.prev_y = None
|
||||||
self.bd_blink = False
|
self.bd_blink = False
|
||||||
self.current_algo = InformationOrigin.HSRAC
|
self.current_algo = EyeInfoOrigin.HSRAC
|
||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
min_cutoff = float(self.settings.gui_min_cutoff) # 0.0004
|
min_cutoff = float(self.settings.gui_min_cutoff) # 0.0004
|
||||||
@ -196,7 +176,7 @@ class EyeProcessor:
|
|||||||
beta=beta
|
beta=beta
|
||||||
)
|
)
|
||||||
|
|
||||||
def output_images_and_update(self, threshold_image, output_information: EyeInformation):
|
def output_images_and_update(self, threshold_image, output_information: EyeInfo):
|
||||||
try:
|
try:
|
||||||
image_stack = np.concatenate(
|
image_stack = np.concatenate(
|
||||||
(
|
(
|
||||||
@ -280,7 +260,7 @@ class EyeProcessor:
|
|||||||
else:
|
else:
|
||||||
self.eyeopen = ibo
|
self.eyeopen = ibo
|
||||||
|
|
||||||
self.output_images_and_update(self.thresh, EyeInformation(self.current_algo, self.out_x, self.out_y, 0, self.eyeopen))
|
self.output_images_and_update(self.thresh, EyeInfo(self.current_algo, self.out_x, self.out_y, 0, self.eyeopen))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -293,7 +273,7 @@ class EyeProcessor:
|
|||||||
self.rawx, self.rawy, self.eyeopen = self.er_daddy.run(self.current_image_gray)
|
self.rawx, self.rawy, self.eyeopen = self.er_daddy.run(self.current_image_gray)
|
||||||
# Daddy also uses a one euro filter, so I'll have to use it twice, but I'm not going to think too much about it.
|
# Daddy also uses a one euro filter, so I'll have to use it twice, but I'm not going to think too much about it.
|
||||||
self.out_x, self.out_y = cal.cal_osc(self, self.rawx, self.rawy)
|
self.out_x, self.out_y = cal.cal_osc(self, self.rawx, self.rawy)
|
||||||
self.current_algorithm = InformationOrigin.DADDY
|
self.current_algorithm = EyeInfoOrigin.DADDY
|
||||||
|
|
||||||
def HSRACM(self):
|
def HSRACM(self):
|
||||||
# todo: added process to initialise er_hsrac when resolution changes
|
# todo: added process to initialise er_hsrac when resolution changes
|
||||||
@ -302,26 +282,26 @@ class EyeProcessor:
|
|||||||
self.prev_x = self.rawx
|
self.prev_x = self.rawx
|
||||||
self.prev_y = self.rawy
|
self.prev_y = self.rawy
|
||||||
self.out_x, self.out_y = cal.cal_osc(self, self.rawx, self.rawy)
|
self.out_x, self.out_y = cal.cal_osc(self, self.rawx, self.rawy)
|
||||||
self.current_algorithm = InformationOrigin.HSRAC
|
self.current_algorithm = EyeInfoOrigin.HSRAC
|
||||||
|
|
||||||
def HSFM(self):
|
def HSFM(self):
|
||||||
# todo: added process to initialise er_hsf when resolution changes
|
# todo: added process to initialise er_hsf when resolution changes
|
||||||
self.rawx, self.rawy, self.thresh = self.er_hsf.run(self.current_image_gray)
|
self.rawx, self.rawy, self.thresh = self.er_hsf.run(self.current_image_gray)
|
||||||
self.eyeopen = self.ibo.intense(self.rawx, self.rawy, self.current_image_gray)
|
self.eyeopen = self.ibo.intense(self.rawx, self.rawy, self.current_image_gray)
|
||||||
self.out_x, self.out_y = cal.cal_osc(self, self.rawx, self.rawy)
|
self.out_x, self.out_y = cal.cal_osc(self, self.rawx, self.rawy)
|
||||||
self.current_algorithm = InformationOrigin.HSF
|
self.current_algorithm = EyeInfoOrigin.HSF
|
||||||
|
|
||||||
def RANSAC3DM(self):
|
def RANSAC3DM(self):
|
||||||
current_image_gray_copy = self.current_image_gray.copy() # Duplicate before overwriting in RANSAC3D.
|
current_image_gray_copy = self.current_image_gray.copy() # Duplicate before overwriting in RANSAC3D.
|
||||||
self.rawx, self.rawy, self.thresh = RANSAC3D(self)
|
self.rawx, self.rawy, self.thresh = RANSAC3D(self)
|
||||||
self.out_x, self.out_y = cal.cal_osc(self, self.rawx, self.rawy)
|
self.out_x, self.out_y = cal.cal_osc(self, self.rawx, self.rawy)
|
||||||
self.current_algorithm = InformationOrigin.RANSAC
|
self.current_algorithm = EyeInfoOrigin.RANSAC
|
||||||
|
|
||||||
def BLOBM(self):
|
def BLOBM(self):
|
||||||
print("calling")
|
print("calling")
|
||||||
self.rawx, self.rawy, self.thresh = BLOB(self)
|
self.rawx, self.rawy, self.thresh = BLOB(self)
|
||||||
self.out_x, self.out_y = cal.cal_osc(self, self.rawx, self.rawy)
|
self.out_x, self.out_y = cal.cal_osc(self, self.rawx, self.rawy)
|
||||||
self.current_algorithm = InformationOrigin.BLOB
|
self.current_algorithm = EyeInfoOrigin.BLOB
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -359,6 +339,7 @@ class EyeProcessor:
|
|||||||
# Run the following somewhere
|
# Run the following somewhere
|
||||||
# self.daddy = External_Run_DADDY()
|
# self.daddy = External_Run_DADDY()
|
||||||
|
|
||||||
|
|
||||||
self.firstalgo = None
|
self.firstalgo = None
|
||||||
self.secondalgo = None
|
self.secondalgo = None
|
||||||
self.thirdalgo = None
|
self.thirdalgo = None
|
||||||
@ -473,23 +454,23 @@ class EyeProcessor:
|
|||||||
# cx, cy, thresh = HSRAC(self)
|
# cx, cy, thresh = HSRAC(self)
|
||||||
# out_x, out_y = cal_osc(self, cx, cy)
|
# out_x, out_y = cal_osc(self, cx, cy)
|
||||||
# if cx == 0:
|
# if cx == 0:
|
||||||
# self.output_images_and_update(thresh, EyeInformation(InformationOrigin.HSRAC, out_x, out_y, 0, True)) #update app
|
# self.output_images_and_update(thresh, EyeInfo(EyeInfoOrigin.HSRAC, out_x, out_y, 0, True)) #update app
|
||||||
# else:
|
# else:
|
||||||
# self.output_images_and_update(thresh, EyeInformation(InformationOrigin.HSRAC, out_x, out_y, 0, self.blinkvalue))
|
# self.output_images_and_update(thresh, EyeInfo(EyeInfoOrigin.HSRAC, out_x, out_y, 0, self.blinkvalue))
|
||||||
|
|
||||||
|
|
||||||
# cx, cy, thresh = RANSAC3D(self)
|
# cx, cy, thresh = RANSAC3D(self)
|
||||||
# out_x, out_y = cal_osc(self, cx, cy)
|
# out_x, out_y = cal_osc(self, cx, cy)
|
||||||
# self.output_images_and_update(thresh, EyeInformation(InformationOrigin.RANSAC, out_x, out_y, 0, False)) #update app
|
# self.output_images_and_update(thresh, EyeInfo(EyeInfoOrigin.RANSAC, out_x, out_y, 0, False)) #update app
|
||||||
|
|
||||||
|
|
||||||
# cx, cy, larger_threshold = BLOB(self)
|
# cx, cy, larger_threshold = BLOB(self)
|
||||||
# out_x, out_y = cal_osc(self, cx, cy)
|
# out_x, out_y = cal_osc(self, cx, cy)
|
||||||
# self.output_images_and_update(larger_threshold, EyeInformation(InformationOrigin.BLOB, out_x, out_y, 0, False)) #update app
|
# self.output_images_and_update(larger_threshold, EyeInfo(EyeInfoOrigin.BLOB, out_x, out_y, 0, False)) #update app
|
||||||
|
|
||||||
#center_x, center_y, frame = HSF(self) #run algo
|
#center_x, center_y, frame = HSF(self) #run algo
|
||||||
#out_x, out_y = cal_osc(self, center_x, center_y) #filter and calibrate
|
#out_x, out_y = cal_osc(self, center_x, center_y) #filter and calibrate
|
||||||
#self.output_images_and_update(frame, EyeInformation(InformationOrigin.HSF, out_x, out_y, 0, False)) #update app
|
#self.output_images_and_update(frame, EyeInfo(EyeInfoOrigin.HSF, out_x, out_y, 0, False)) #update app
|
||||||
|
|
||||||
self.ALGOSELECT() #run our algos in priority order set in settings
|
self.ALGOSELECT() #run our algos in priority order set in settings
|
||||||
#self.BLOBM()
|
#self.BLOBM()
|
||||||
|
|||||||
@ -1,15 +1,17 @@
|
|||||||
import os
|
import os
|
||||||
from utils.misc_utils import is_nt
|
import os
|
||||||
from osc import VRChatOSCReceiver, VRChatOSC, EyeId
|
|
||||||
from config import EyeTrackConfig
|
|
||||||
from camera_widget import CameraWidget
|
|
||||||
from settings_widget import SettingsWidget
|
|
||||||
|
|
||||||
import queue
|
|
||||||
import threading
|
|
||||||
import PySimpleGUI as sg
|
import PySimpleGUI as sg
|
||||||
import os
|
import queue
|
||||||
import requests
|
import requests
|
||||||
|
import threading
|
||||||
|
|
||||||
|
from camera_widget import CameraWidget
|
||||||
|
from config import EyeTrackConfig
|
||||||
|
from eye import EyeId
|
||||||
|
from osc import VRChatOSCReceiver, VRChatOSC
|
||||||
|
from settings_widget import SettingsWidget
|
||||||
|
from utils.misc_utils import is_nt
|
||||||
|
|
||||||
|
|
||||||
if is_nt:
|
if is_nt:
|
||||||
from winotify import Notification
|
from winotify import Notification
|
||||||
|
|||||||
@ -112,9 +112,9 @@ def fit_rotated_ellipse_ransac(data: np.ndarray, sfc: np.random.Generator, iter_
|
|||||||
|
|
||||||
np.matmul(dm_rng_swap_trans, dm_rng_swap, out=dm_rng_5x5)
|
np.matmul(dm_rng_swap_trans, dm_rng_swap, out=dm_rng_5x5)
|
||||||
# np.linalg.solve(np.matmul(dm_rng_swap_trans, dm_rng_swap), dm_rng_swap_trans) # solve is slow https://github.com/bogovicj/JaneliaMLCourse/issues/1
|
# np.linalg.solve(np.matmul(dm_rng_swap_trans, dm_rng_swap), dm_rng_swap_trans) # solve is slow https://github.com/bogovicj/JaneliaMLCourse/issues/1
|
||||||
#_umath_linalg.inv(dm_rng_5x5, signature='d->d',
|
|
||||||
# extobj=inv_ext, out=dm_rng_5x5)
|
|
||||||
dm_rng_5x5 = np.linalg.pinv(dm_rng_5x5)
|
dm_rng_5x5 = np.linalg.pinv(dm_rng_5x5)
|
||||||
|
# _umath_linalg.inv(dm_rng_5x5, signature='d->d',
|
||||||
|
# extobj=inv_ext, out=dm_rng_5x5)
|
||||||
np.matmul(dm_rng_5x5, dm_rng_swap_trans, out=dm_rng_p5smp)
|
np.matmul(dm_rng_5x5, dm_rng_swap_trans, out=dm_rng_p5smp)
|
||||||
|
|
||||||
np.matmul(dm_rng_p5smp, dm_rng_six, out=dm_rng_p_npaxis)
|
np.matmul(dm_rng_p5smp, dm_rng_six, out=dm_rng_p_npaxis)
|
||||||
|
|||||||
@ -1,9 +1,7 @@
|
|||||||
import sys
|
|
||||||
from utils.misc_utils import PlaySound, SND_FILENAME, SND_ASYNC
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
from enum import IntEnum
|
from enum import IntEnum
|
||||||
from config import EyeTrackConfig
|
from utils.misc_utils import PlaySound, SND_FILENAME, SND_ASYNC
|
||||||
from config import EyeTrackSettingsConfig
|
|
||||||
|
|
||||||
class EyeId(IntEnum):
|
class EyeId(IntEnum):
|
||||||
RIGHT = 0
|
RIGHT = 0
|
||||||
|
|||||||
@ -335,7 +335,7 @@ def RANSAC3D(self):
|
|||||||
self.failed = self.failed + 1 #we have failed, move onto next algo
|
self.failed = self.failed + 1 #we have failed, move onto next algo
|
||||||
return 0, 0, thresh
|
return 0, 0, thresh
|
||||||
# Shove a concatenated image out to the main GUI thread for rendering
|
# Shove a concatenated image out to the main GUI thread for rendering
|
||||||
#self.output_images_and_update(thresh, EyeInformation(InformationOrigin.FAILURE, 0 ,0, 0, False))
|
#self.output_images_and_update(thresh, EyeInfo(EyeInfoOrigin.FAILURE, 0 ,0, 0, False))
|
||||||
#self.output_images_and_update(thresh, output_info)
|
#self.output_images_and_update(thresh, output_info)
|
||||||
#except:
|
#except:
|
||||||
# self.output_images_and_update(thresh, EyeInformation(InformationOrigin.RANSAC, out_x, out_y, 0, self.blinkvalue))
|
# self.output_images_and_update(thresh, EyeInfo(EyeInfoOrigin.RANSAC, out_x, out_y, 0, self.blinkvalue))
|
||||||
|
|||||||
@ -1,12 +1,9 @@
|
|||||||
import PySimpleGUI as sg
|
import PySimpleGUI as sg
|
||||||
|
|
||||||
from config import EyeTrackSettingsConfig
|
from config import EyeTrackSettingsConfig
|
||||||
from threading import Event, Thread
|
|
||||||
from eye_processor import EyeProcessor, InformationOrigin
|
|
||||||
from enum import Enum
|
|
||||||
from queue import Queue, Empty
|
|
||||||
from camera import Camera, CameraState
|
|
||||||
import cv2
|
|
||||||
from osc import EyeId
|
from osc import EyeId
|
||||||
|
from queue import Queue
|
||||||
|
from threading import Event
|
||||||
|
|
||||||
class SettingsWidget:
|
class SettingsWidget:
|
||||||
def __init__(self, widget_id: EyeId, main_config: EyeTrackSettingsConfig, osc_queue: Queue):
|
def __init__(self, widget_id: EyeId, main_config: EyeTrackSettingsConfig, osc_queue: Queue):
|
||||||
|
|||||||
81
poetry.lock
generated
81
poetry.lock
generated
@ -1,4 +1,4 @@
|
|||||||
# This file is automatically @generated by Poetry 1.4.2 and should not be changed by hand.
|
# This file is automatically @generated by Poetry and should not be changed by hand.
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "altgraph"
|
name = "altgraph"
|
||||||
@ -163,7 +163,7 @@ colorama = {version = "*", markers = "platform_system == \"Windows\""}
|
|||||||
name = "colorama"
|
name = "colorama"
|
||||||
version = "0.4.6"
|
version = "0.4.6"
|
||||||
description = "Cross-platform colored terminal text."
|
description = "Cross-platform colored terminal text."
|
||||||
category = "dev"
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
|
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
|
||||||
files = [
|
files = [
|
||||||
@ -363,6 +363,18 @@ files = [
|
|||||||
{file = "msgpack-1.0.5.tar.gz", hash = "sha256:c075544284eadc5cddc70f4757331d99dcbc16b2bbd4849d15f8aae4cf36d31c"},
|
{file = "msgpack-1.0.5.tar.gz", hash = "sha256:c075544284eadc5cddc70f4757331d99dcbc16b2bbd4849d15f8aae4cf36d31c"},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mslex"
|
||||||
|
version = "0.3.0"
|
||||||
|
description = "shlex for windows"
|
||||||
|
category = "main"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.5"
|
||||||
|
files = [
|
||||||
|
{file = "mslex-0.3.0-py2.py3-none-any.whl", hash = "sha256:380cb14abf8fabf40e56df5c8b21a6d533dc5cbdcfe42406bbf08dda8f42e42a"},
|
||||||
|
{file = "mslex-0.3.0.tar.gz", hash = "sha256:4a1ac3f25025cad78ad2fe499dd16d42759f7a3801645399cce5c404415daa97"},
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mypy-extensions"
|
name = "mypy-extensions"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
@ -526,19 +538,19 @@ files = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "platformdirs"
|
name = "platformdirs"
|
||||||
version = "3.2.0"
|
version = "3.3.0"
|
||||||
description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
|
description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
|
||||||
category = "dev"
|
category = "dev"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.7"
|
||||||
files = [
|
files = [
|
||||||
{file = "platformdirs-3.2.0-py3-none-any.whl", hash = "sha256:ebe11c0d7a805086e99506aa331612429a72ca7cd52a1f0d277dc4adc20cb10e"},
|
{file = "platformdirs-3.3.0-py3-none-any.whl", hash = "sha256:ea61fd7b85554beecbbd3e9b37fb26689b227ffae38f73353cbcc1cf8bd01878"},
|
||||||
{file = "platformdirs-3.2.0.tar.gz", hash = "sha256:d5b638ca397f25f979350ff789db335903d7ea010ab28903f57b27e1b16c2b08"},
|
{file = "platformdirs-3.3.0.tar.gz", hash = "sha256:64370d47dc3fca65b4879f89bdead8197e93e05d696d6d1816243ebae8595da5"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
docs = ["furo (>=2022.12.7)", "proselint (>=0.13)", "sphinx (>=6.1.3)", "sphinx-autodoc-typehints (>=1.22,!=1.23.4)"]
|
docs = ["furo (>=2023.3.27)", "proselint (>=0.13)", "sphinx (>=6.1.3)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)"]
|
||||||
test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.2.2)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"]
|
test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.3.1)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "protobuf"
|
name = "protobuf"
|
||||||
@ -563,6 +575,33 @@ files = [
|
|||||||
{file = "protobuf-4.22.3.tar.gz", hash = "sha256:23452f2fdea754a8251d0fc88c0317735ae47217e0d27bf330a30eec2848811a"},
|
{file = "protobuf-4.22.3.tar.gz", hash = "sha256:23452f2fdea754a8251d0fc88c0317735ae47217e0d27bf330a30eec2848811a"},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "psutil"
|
||||||
|
version = "5.9.5"
|
||||||
|
description = "Cross-platform lib for process and system monitoring in Python."
|
||||||
|
category = "main"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
||||||
|
files = [
|
||||||
|
{file = "psutil-5.9.5-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:be8929ce4313f9f8146caad4272f6abb8bf99fc6cf59344a3167ecd74f4f203f"},
|
||||||
|
{file = "psutil-5.9.5-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:ab8ed1a1d77c95453db1ae00a3f9c50227ebd955437bcf2a574ba8adbf6a74d5"},
|
||||||
|
{file = "psutil-5.9.5-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:4aef137f3345082a3d3232187aeb4ac4ef959ba3d7c10c33dd73763fbc063da4"},
|
||||||
|
{file = "psutil-5.9.5-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:ea8518d152174e1249c4f2a1c89e3e6065941df2fa13a1ab45327716a23c2b48"},
|
||||||
|
{file = "psutil-5.9.5-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:acf2aef9391710afded549ff602b5887d7a2349831ae4c26be7c807c0a39fac4"},
|
||||||
|
{file = "psutil-5.9.5-cp27-none-win32.whl", hash = "sha256:5b9b8cb93f507e8dbaf22af6a2fd0ccbe8244bf30b1baad6b3954e935157ae3f"},
|
||||||
|
{file = "psutil-5.9.5-cp27-none-win_amd64.whl", hash = "sha256:8c5f7c5a052d1d567db4ddd231a9d27a74e8e4a9c3f44b1032762bd7b9fdcd42"},
|
||||||
|
{file = "psutil-5.9.5-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:3c6f686f4225553615612f6d9bc21f1c0e305f75d7d8454f9b46e901778e7217"},
|
||||||
|
{file = "psutil-5.9.5-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7a7dd9997128a0d928ed4fb2c2d57e5102bb6089027939f3b722f3a210f9a8da"},
|
||||||
|
{file = "psutil-5.9.5-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:89518112647f1276b03ca97b65cc7f64ca587b1eb0278383017c2a0dcc26cbe4"},
|
||||||
|
{file = "psutil-5.9.5-cp36-abi3-win32.whl", hash = "sha256:104a5cc0e31baa2bcf67900be36acde157756b9c44017b86b2c049f11957887d"},
|
||||||
|
{file = "psutil-5.9.5-cp36-abi3-win_amd64.whl", hash = "sha256:b258c0c1c9d145a1d5ceffab1134441c4c5113b2417fafff7315a917a026c3c9"},
|
||||||
|
{file = "psutil-5.9.5-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:c607bb3b57dc779d55e1554846352b4e358c10fff3abf3514a7a6601beebdb30"},
|
||||||
|
{file = "psutil-5.9.5.tar.gz", hash = "sha256:5410638e4df39c54d957fc51ce03048acd8e6d60abc0f5107af51e5fb566eb3c"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
test = ["enum34", "ipaddress", "mock", "pywin32", "wmi"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pycodestyle"
|
name = "pycodestyle"
|
||||||
version = "2.9.1"
|
version = "2.9.1"
|
||||||
@ -814,14 +853,14 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "setuptools"
|
name = "setuptools"
|
||||||
version = "67.6.1"
|
version = "67.7.2"
|
||||||
description = "Easily download, build, install, upgrade, and uninstall Python packages"
|
description = "Easily download, build, install, upgrade, and uninstall Python packages"
|
||||||
category = "dev"
|
category = "dev"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.7"
|
||||||
files = [
|
files = [
|
||||||
{file = "setuptools-67.6.1-py3-none-any.whl", hash = "sha256:e728ca814a823bf7bf60162daf9db95b93d532948c4c0bea762ce62f60189078"},
|
{file = "setuptools-67.7.2-py3-none-any.whl", hash = "sha256:23aaf86b85ca52ceb801d32703f12d77517b2556af839621c641fca11287952b"},
|
||||||
{file = "setuptools-67.6.1.tar.gz", hash = "sha256:257de92a9d50a60b8e22abfcbb771571fde0dbf3ec234463212027a4eeecbe9a"},
|
{file = "setuptools-67.7.2.tar.gz", hash = "sha256:f104fa03692a2602fa0fec6c6a9e63b6c8a968de13e17c026957dd1f53d80990"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
@ -856,11 +895,29 @@ files = [
|
|||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
mpmath = ">=0.19"
|
mpmath = ">=0.19"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "taskipy"
|
||||||
|
version = "1.10.4"
|
||||||
|
description = "tasks runner for python projects"
|
||||||
|
category = "main"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.6,<4.0"
|
||||||
|
files = [
|
||||||
|
{file = "taskipy-1.10.4-py3-none-any.whl", hash = "sha256:b96245d7f2956d36821435acaa822143ef6d2ff6cfecc48cf0a48c4b95456c14"},
|
||||||
|
{file = "taskipy-1.10.4.tar.gz", hash = "sha256:0006429f708f530fc7add28ca51fd41f6c6e1fbe86763ff05125e1af3e8bdc7e"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
colorama = ">=0.4.4,<0.5.0"
|
||||||
|
mslex = {version = ">=0.3.0,<0.4.0", markers = "sys_platform == \"win32\""}
|
||||||
|
psutil = ">=5.7.2,<6.0.0"
|
||||||
|
tomli = {version = ">=2.0.1,<3.0.0", markers = "python_version >= \"3.7\" and python_version < \"4.0\""}
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tomli"
|
name = "tomli"
|
||||||
version = "2.0.1"
|
version = "2.0.1"
|
||||||
description = "A lil' TOML parser"
|
description = "A lil' TOML parser"
|
||||||
category = "dev"
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.7"
|
||||||
files = [
|
files = [
|
||||||
@ -912,4 +969,4 @@ files = [
|
|||||||
[metadata]
|
[metadata]
|
||||||
lock-version = "2.0"
|
lock-version = "2.0"
|
||||||
python-versions = "~3.10.0"
|
python-versions = "~3.10.0"
|
||||||
content-hash = "f712f691b445b82d4d43ff66867f0142eedf33d4f024bb44168235de1e137206"
|
content-hash = "e7ba1f268906e96f3e40127b34c43e8eaa2a2367bc3a2b471d7f6917a1edcc76"
|
||||||
|
|||||||
@ -20,11 +20,16 @@ winotify = [
|
|||||||
{ version = "^1.1.0", platform = 'win32' }
|
{ version = "^1.1.0", platform = 'win32' }
|
||||||
]
|
]
|
||||||
onnxruntime = "^1.13.1"
|
onnxruntime = "^1.13.1"
|
||||||
|
colorama = "^0.4.6"
|
||||||
|
taskipy = "^1.10.4"
|
||||||
[tool.poetry.group.dev.dependencies]
|
[tool.poetry.group.dev.dependencies]
|
||||||
black = "^22.10.0"
|
black = "^22.10.0"
|
||||||
pyinstaller = "^5.6.2"
|
pyinstaller = "^5.6.2"
|
||||||
flake8 = "^5.0.4"
|
flake8 = "^5.0.4"
|
||||||
|
|
||||||
|
[tool.taskipy.tasks]
|
||||||
|
dev = "python eyetrackapp.py"
|
||||||
|
|
||||||
[build-system]
|
[build-system]
|
||||||
requires = ["poetry-core>=1.0.0"]
|
requires = ["poetry-core>=1.0.0"]
|
||||||
build-backend = "poetry.core.masonry.api"
|
build-backend = "poetry.core.masonry.api"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user