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:
Prohurtz 2023-05-11 07:18:57 -07:00 committed by GitHub
commit c5a9842dc7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 225 additions and 126 deletions

View File

@ -1,13 +1,14 @@
from config import EyeTrackConfig
from enum import Enum
import cv2
import numpy as np
import queue
import serial
import serial.tools.list_ports
import threading
import time
import numpy as np
from colorama import Fore
from config import EyeTrackConfig
from enum import Enum
WAIT_TIME = 0.1
@ -52,20 +53,23 @@ class Camera:
self.last_frame_time = time.time()
self.frame_number = 0
self.fps = 0
self.bps = 0
self.start = True
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):
if self.serial_connection is not None:
self.serial_connection.close()
def set_output_queue(self, camera_output_outgoing: "queue.Queue"):
self.camera_output_outgoing = camera_output_outgoing
def run(self):
while True:
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
should_push = True
# 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")
frame_number = self.wired_camera.get(cv2.CAP_PROP_POS_FRAMES)
self.fps = self.wired_camera.get(cv2.CAP_PROP_FPS)
self.bps = image.nbytes
if should_push:
self.push_image_to_queue(image, frame_number, self.fps)
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
pass
@ -153,34 +158,37 @@ class Camera:
return jpeg
def get_serial_camera_picture(self, should_push):
conn = self.serial_connection
if conn is None:
return
try:
if self.serial_connection.in_waiting:
if conn.in_waiting:
jpeg = self.get_next_jpeg_frame()
if jpeg:
# Create jpeg frame from byte string
image = cv2.imdecode(np.fromstring(jpeg, dtype=np.uint8), cv2.IMREAD_UNCHANGED)
if image is None:
print("image not found")
print(f"{Fore.YELLOW}[WARN] Frame drop. Corrupted JPEG.{Fore.RESET}")
return
# 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.
self.serial_connection.reset_input_buffer()
self.buffer = b''
if conn.in_waiting >= 32768:
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.
current_frame_time = time.time()
delta_time = current_frame_time - self.last_frame_time
self.last_frame_time = current_frame_time
if delta_time > 0:
self.fps = 1 / delta_time
self.bps = len(jpeg) / delta_time
self.frame_number = self.frame_number + 1
if should_push:
self.push_image_to_queue(image, self.frame_number, self.fps)
except UnboundLocalError as ex:
print(ex)
except Exception:
print("\033[93m[WARN]Serial capture source problem, assuming camera disconnected, waiting for reconnect.\033[0m")
self.serial_connection.close()
print(f"{Fore.YELLOW}[WARN] Serial capture source problem, assuming camera disconnected, waiting for reconnect.{Fore.RESET}")
conn.close()
self.camera_status = CameraState.DISCONNECTED
pass
@ -202,13 +210,14 @@ class Camera:
xonxoff=False,
dsrdtr=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"\033[94m[INFO] Serial Tracker successfully connected on {port}\033[0m")
print(f"{Fore.CYAN}[INFO] ETVR Serial Tracker device connected on {port}{Fore.RESET}")
self.serial_connection = conn
self.camera_status = CameraState.CONNECTED
except Exception:
print(f"{Fore.CYAN}[INFO] Failed to connect on {port}{Fore.RESET}")
self.camera_status = CameraState.DISCONNECTED
def push_image_to_queue(self, image, frame_number, fps):
@ -217,6 +226,6 @@ class Camera:
qsize = self.camera_output_outgoing.qsize()
if qsize > 1:
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.capture_event.clear()

View File

@ -1,8 +1,9 @@
import PySimpleGUI as sg
from config import EyeTrackConfig
from config import EyeTrackSettingsConfig
from collections import deque
from threading import Event, Thread
from eye_processor import EyeProcessor, InformationOrigin
from eye_processor import EyeProcessor, EyeInfoOrigin
from enum import Enum
from queue import Queue, Empty
from camera import Camera, CameraState
@ -24,6 +25,8 @@ class CameraWidget:
self.gui_save_tracking_button = f"-SAVETRACKINGBUTTON{widget_id}-"
self.gui_tracking_layout = f"-TRACKINGLAYOUT{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_restart_calibration = f"-RESTARTCALIBRATION{widget_id}-"
self.gui_stop_calibration = f"-STOPCALIBRATION{widget_id}-"
@ -46,6 +49,35 @@ class CameraWidget:
else:
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 = [
[
sg.Graph(
@ -82,6 +114,8 @@ class CameraWidget:
[
sg.Text("Mode:", 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(
# "Circle 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.x1, self.y1 = None, None
self.figure = None
self.is_mouse_up = True
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):
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
# 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 == "":
window[self.gui_mode_readout].update("Waiting for camera address")
window[self.gui_roi_message].update(visible=False)
@ -275,6 +296,8 @@ class CameraWidget:
window[self.gui_mode_readout].update("Calibration")
else:
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:
try:
@ -312,7 +335,7 @@ class CameraWidget:
graph = window[self.gui_output_graph]
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")
if not np.isnan(eye_info.x) and not np.isnan(eye_info.y):
@ -332,10 +355,10 @@ class CameraWidget:
# elif eye_info.blink:
# graph.update(background_color="#6f4ca1")
elif eye_info.info_type == InformationOrigin.FAILURE:
elif eye_info.info_type == EyeInfoOrigin.FAILURE:
graph.update(background_color="red")
# 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))
except Empty:
pass

View File

@ -1,10 +1,11 @@
from typing import Union, Dict
from osc import EyeId
import os.path
import json
from pydantic import BaseModel
import os.path
import shutil
from eye import EyeId
from pydantic import BaseModel
from typing import Union
CONFIG_FILE_NAME: str = "eyetrack_settings.json"
BACKUP_CONFIG_FILE_NAME: str = "eyetrack_settings.backup"

26
EyeTrackApp/eye.py Normal file
View 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

View File

@ -59,29 +59,9 @@ from ransac import *
from hsrac import External_Run_HSRACS
from blink import *
from eye import EyeInfo, EyeInfoOrigin
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 wrapper(*args, **kwargs):
@ -179,8 +159,8 @@ class EyeProcessor:
self.prev_x = None
self.prev_y = None
self.bd_blink = False
self.current_algo = InformationOrigin.HSRAC
self.current_algo = EyeInfoOrigin.HSRAC
try:
min_cutoff = float(self.settings.gui_min_cutoff) # 0.0004
@ -196,7 +176,7 @@ class EyeProcessor:
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:
image_stack = np.concatenate(
(
@ -280,7 +260,7 @@ class EyeProcessor:
else:
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)
# 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.current_algorithm = InformationOrigin.DADDY
self.current_algorithm = EyeInfoOrigin.DADDY
def HSRACM(self):
# todo: added process to initialise er_hsrac when resolution changes
@ -302,26 +282,26 @@ class EyeProcessor:
self.prev_x = self.rawx
self.prev_y = 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):
# 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.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.current_algorithm = InformationOrigin.HSF
self.current_algorithm = EyeInfoOrigin.HSF
def RANSAC3DM(self):
current_image_gray_copy = self.current_image_gray.copy() # Duplicate before overwriting in RANSAC3D.
self.rawx, self.rawy, self.thresh = RANSAC3D(self)
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):
print("calling")
self.rawx, self.rawy, self.thresh = BLOB(self)
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
# self.daddy = External_Run_DADDY()
self.firstalgo = None
self.secondalgo = None
self.thirdalgo = None
@ -473,23 +454,23 @@ class EyeProcessor:
# cx, cy, thresh = HSRAC(self)
# out_x, out_y = cal_osc(self, cx, cy)
# 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:
# 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)
# 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)
# 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
#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.BLOBM()

View File

@ -1,15 +1,17 @@
import os
from utils.misc_utils import is_nt
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 os
import PySimpleGUI as sg
import os
import queue
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:
from winotify import Notification

View File

@ -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.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)
# _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_p5smp, dm_rng_six, out=dm_rng_p_npaxis)

View File

@ -1,9 +1,7 @@
import sys
from utils.misc_utils import PlaySound, SND_FILENAME, SND_ASYNC
import numpy as np
from enum import IntEnum
from config import EyeTrackConfig
from config import EyeTrackSettingsConfig
from utils.misc_utils import PlaySound, SND_FILENAME, SND_ASYNC
class EyeId(IntEnum):
RIGHT = 0

View File

@ -335,7 +335,7 @@ def RANSAC3D(self):
self.failed = self.failed + 1 #we have failed, move onto next algo
return 0, 0, thresh
# 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)
#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))

View File

@ -1,12 +1,9 @@
import PySimpleGUI as sg
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 queue import Queue
from threading import Event
class SettingsWidget:
def __init__(self, widget_id: EyeId, main_config: EyeTrackSettingsConfig, osc_queue: Queue):

81
poetry.lock generated
View File

@ -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]]
name = "altgraph"
@ -163,7 +163,7 @@ colorama = {version = "*", markers = "platform_system == \"Windows\""}
name = "colorama"
version = "0.4.6"
description = "Cross-platform colored terminal text."
category = "dev"
category = "main"
optional = false
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
files = [
@ -363,6 +363,18 @@ files = [
{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]]
name = "mypy-extensions"
version = "1.0.0"
@ -526,19 +538,19 @@ files = [
[[package]]
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\"."
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
{file = "platformdirs-3.2.0-py3-none-any.whl", hash = "sha256:ebe11c0d7a805086e99506aa331612429a72ca7cd52a1f0d277dc4adc20cb10e"},
{file = "platformdirs-3.2.0.tar.gz", hash = "sha256:d5b638ca397f25f979350ff789db335903d7ea010ab28903f57b27e1b16c2b08"},
{file = "platformdirs-3.3.0-py3-none-any.whl", hash = "sha256:ea61fd7b85554beecbbd3e9b37fb26689b227ffae38f73353cbcc1cf8bd01878"},
{file = "platformdirs-3.3.0.tar.gz", hash = "sha256:64370d47dc3fca65b4879f89bdead8197e93e05d696d6d1816243ebae8595da5"},
]
[package.extras]
docs = ["furo (>=2022.12.7)", "proselint (>=0.13)", "sphinx (>=6.1.3)", "sphinx-autodoc-typehints (>=1.22,!=1.23.4)"]
test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.2.2)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"]
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.3.1)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"]
[[package]]
name = "protobuf"
@ -563,6 +575,33 @@ files = [
{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]]
name = "pycodestyle"
version = "2.9.1"
@ -814,14 +853,14 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
[[package]]
name = "setuptools"
version = "67.6.1"
version = "67.7.2"
description = "Easily download, build, install, upgrade, and uninstall Python packages"
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
{file = "setuptools-67.6.1-py3-none-any.whl", hash = "sha256:e728ca814a823bf7bf60162daf9db95b93d532948c4c0bea762ce62f60189078"},
{file = "setuptools-67.6.1.tar.gz", hash = "sha256:257de92a9d50a60b8e22abfcbb771571fde0dbf3ec234463212027a4eeecbe9a"},
{file = "setuptools-67.7.2-py3-none-any.whl", hash = "sha256:23aaf86b85ca52ceb801d32703f12d77517b2556af839621c641fca11287952b"},
{file = "setuptools-67.7.2.tar.gz", hash = "sha256:f104fa03692a2602fa0fec6c6a9e63b6c8a968de13e17c026957dd1f53d80990"},
]
[package.extras]
@ -856,11 +895,29 @@ files = [
[package.dependencies]
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]]
name = "tomli"
version = "2.0.1"
description = "A lil' TOML parser"
category = "dev"
category = "main"
optional = false
python-versions = ">=3.7"
files = [
@ -912,4 +969,4 @@ files = [
[metadata]
lock-version = "2.0"
python-versions = "~3.10.0"
content-hash = "f712f691b445b82d4d43ff66867f0142eedf33d4f024bb44168235de1e137206"
content-hash = "e7ba1f268906e96f3e40127b34c43e8eaa2a2367bc3a2b471d7f6917a1edcc76"

View File

@ -20,11 +20,16 @@ winotify = [
{ version = "^1.1.0", platform = 'win32' }
]
onnxruntime = "^1.13.1"
colorama = "^0.4.6"
taskipy = "^1.10.4"
[tool.poetry.group.dev.dependencies]
black = "^22.10.0"
pyinstaller = "^5.6.2"
flake8 = "^5.0.4"
[tool.taskipy.tasks]
dev = "python eyetrackapp.py"
[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"