Merge pull request #110 from Blu3u/feature/mac-os-support

Serial camera macOS support
This commit is contained in:
Prohurtz 2024-05-27 18:40:25 -05:00 committed by GitHub
commit 2243e63f3c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 517 additions and 502 deletions

View File

@ -67,6 +67,16 @@ class CameraState(Enum):
DISCONNECTED = 2
def is_serial_capture_source(addr: str) -> bool:
"""
Returns True if the capture source address is a serial port.
"""
return (addr.startswith("COM") # Windows
or addr.startswith("/dev/cu") # macOS
or addr.startswith("/dev/tty") # Linux
)
class Camera:
def __init__(
self,
@ -126,7 +136,8 @@ class Camera:
# than this, otherwise we can deadlock ourselves.
if self.config.capture_source != None and self.config.capture_source != "":
self.current_capture_source = self.config.capture_source
if "COM" in str(self.current_capture_source):
addr = str(self.current_capture_source)
if is_serial_capture_source(addr):
if (
self.serial_connection is None
or self.camera_status == CameraState.DISCONNECTED
@ -166,7 +177,8 @@ class Camera:
if should_push and not self.capture_event.wait(timeout=0.001):
continue
if self.config.capture_source != None:
if "COM" in str(self.current_capture_source):
addr = str(self.current_capture_source)
if is_serial_capture_source(addr):
self.get_serial_camera_picture(should_push)
else:
self.get_cv2_camera_picture(should_push)
@ -301,15 +313,16 @@ class Camera:
if not any(p for p in com_ports if port in p):
return
try:
rate = 115200 if sys.platform == "darwin" else 3000000 # Higher baud rate not working on macOS
conn = serial.Serial(
baudrate=3000000, port=port, xonxoff=False, dsrdtr=False, rtscts=False
baudrate=rate, port=port, xonxoff=False, dsrdtr=False, rtscts=False
)
# Set explicit buffer size for serial.
conn.set_buffer_size(rx_size=32768, tx_size=32768)
if sys.platform == "win32":
buffer_size = 32768
conn.set_buffer_size(rx_size=buffer_size, tx_size=buffer_size)
print(
f"{Fore.CYAN}[INFO] ETVR Serial Tracker device connected on {port}{Fore.RESET}"
)
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:

View File

@ -317,6 +317,7 @@ class CameraWidget:
len(values[self.gui_camera_addr]) > 5
and "http" not in values[self.gui_camera_addr]
and ".mp4" not in values[self.gui_camera_addr]
and not values[self.gui_camera_addr].startswith('/dev') # For MacOS and Linux users
): # If http is not in camera address, add it.
self.config.capture_source = f"http://{values[self.gui_camera_addr]}/"
else:

View File

@ -350,12 +350,10 @@ class EllipseBasedPupilDilation:
minp = float(self.maxval)
try:
if maxp != 0 and not (np.isnan(pupil_area) or np.isnan(maxp)):
eyedilation = (pupil_area - maxp) / (
minp - maxp
)
else:
if not np.isfinite(pupil_area) or not np.isfinite(maxp) or not np.isfinite(minp) or (minp - maxp) == 0:
eyedilation = 0.5
else:
eyedilation = (pupil_area - maxp) / (minp - maxp)
except:
eyedilation = 0.5
eyedilation = 1 - eyedilation

View File

@ -41,9 +41,11 @@ from one_euro_filter import OneEuroFilter
import psutil, os
import sys
from utils.misc_utils import resource_path
import platform
from pathlib import Path
frames = 0
models = Path("Models")
def run_model(input_queue, output_queue, session):
@ -70,10 +72,7 @@ class LEAP_C(object):
# Config variables
self.num_threads = 4 # Number of python threads to use (using ~1 more than needed to achieve wanted fps yields lower cpu usage)
self.queue_max_size = 1 # Optimize for best CPU usage, Memory, and Latency. A maxsize is needed to not create a potential memory leak.
if platform.system() == "Darwin":
self.model_path = resource_path("Models/leap123023.onnx") # funny MacOS files issues :P
else:
self.model_path = resource_path("Models\leap123023.onnx")
self.model_path = resource_path(models / 'leap123023.onnx')
self.low_priority = (
False # set process priority to low (may cause issues when unfocusing? reported by one, not reproducable)

View File

@ -2,6 +2,9 @@ import os
import typing
import sys
from pathlib import Path
from typing import Union
is_nt = True if os.name == "nt" else False
def PlaySound(*args, **kwargs): pass
@ -60,12 +63,14 @@ class FastMedian:
self.__median = lst_median(all, ordered=False)
return self.__median
def resource_path(relative_path):
""" Get absolute path to resource, works for dev and for PyInstaller """
def resource_path(relative_path: Union[str, Path]) -> str:
"""
Get absolute path to resource, works for dev and for PyInstaller
"""
try:
# PyInstaller creates a temp folder and stores path in _MEIPASS
base_path = sys._MEIPASS
base_path = Path(sys._MEIPASS)
except AttributeError:
base_path = os.path.abspath(".")
base_path = Path(".")
return os.path.join(base_path, relative_path)
return str(base_path / relative_path)

954
poetry.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -12,8 +12,8 @@ python-osc = "^1.8.0"
requests = "^2.28.1"
opencv-python = "^4.6.0.66"
numpy = "~1.23.5"
pye3d = "^0.3.1.post1"
pysimplegui = "^4.60.4"
pye3d = "^0.3.2"
pysimplegui = "^4.59.0"
pydantic = "^2.4.2"
scikit-image = "*"
pyserial = "^3.5"
@ -25,6 +25,7 @@ colorama = "^0.4.6"
taskipy = "^1.10.4"
pytest = "^8.0.0"
pytest-cov = "^4.1.0"
[tool.poetry.group.dev.dependencies]
black = "^22.10.0"
pyinstaller = "^5.6.2"