crossplatform?
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1 +1 @@
|
|||||||
mucapy_config.json
|
|
||||||
|
|||||||
109
mucapy/main.py
109
mucapy/main.py
@@ -18,12 +18,22 @@ import time
|
|||||||
|
|
||||||
class Config:
|
class Config:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
# Use JSON file in current working directory
|
# Use platform-specific user directory for config
|
||||||
self.config_file = os.path.join(os.getcwd(), 'mucapy_config.json')
|
if sys.platform.startswith('win'):
|
||||||
|
config_dir = os.path.join(os.environ.get('APPDATA', os.path.expanduser('~')), 'MuCaPy')
|
||||||
|
pictures_dir = os.path.join(os.environ.get('USERPROFILE', os.path.expanduser('~')), 'Pictures', 'MuCaPy')
|
||||||
|
else:
|
||||||
|
config_dir = os.path.join(os.path.expanduser('~'), '.config', 'mucapy')
|
||||||
|
pictures_dir = os.path.join(os.path.expanduser('~'), 'Pictures', 'MuCaPy')
|
||||||
|
|
||||||
|
# Create config directory if it doesn't exist
|
||||||
|
os.makedirs(config_dir, exist_ok=True)
|
||||||
|
|
||||||
|
self.config_file = os.path.join(config_dir, 'config.json')
|
||||||
self.settings = {
|
self.settings = {
|
||||||
'network_cameras': {}, # Store network cameras configuration
|
'network_cameras': {}, # Store network cameras configuration
|
||||||
'last_model_dir': '',
|
'last_model_dir': '',
|
||||||
'last_screenshot_dir': os.path.expanduser('~/Pictures/MuCaPy'),
|
'last_screenshot_dir': pictures_dir,
|
||||||
'last_layout': 0,
|
'last_layout': 0,
|
||||||
'last_fps': 10,
|
'last_fps': 10,
|
||||||
'last_selected_cameras': [],
|
'last_selected_cameras': [],
|
||||||
@@ -206,7 +216,7 @@ class MultiCamYOLODetector:
|
|||||||
"""Check for available cameras including network cameras"""
|
"""Check for available cameras including network cameras"""
|
||||||
self.available_cameras = []
|
self.available_cameras = []
|
||||||
|
|
||||||
# Try numeric indices first (this works more reliably)
|
# Try numeric indices first (this works on all platforms)
|
||||||
for i in range(max_to_check):
|
for i in range(max_to_check):
|
||||||
try:
|
try:
|
||||||
cap = cv2.VideoCapture(i)
|
cap = cv2.VideoCapture(i)
|
||||||
@@ -216,18 +226,19 @@ class MultiCamYOLODetector:
|
|||||||
except:
|
except:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Also check device paths as fallback
|
# Platform-specific device path checks
|
||||||
if os.path.exists('/dev'):
|
if sys.platform.startswith('linux'):
|
||||||
for i in range(max_to_check):
|
if os.path.exists('/dev'):
|
||||||
device_path = f"/dev/video{i}"
|
for i in range(max_to_check):
|
||||||
if os.path.exists(device_path) and device_path not in self.available_cameras:
|
device_path = f"/dev/video{i}"
|
||||||
try:
|
if os.path.exists(device_path) and device_path not in self.available_cameras:
|
||||||
cap = cv2.VideoCapture(device_path)
|
try:
|
||||||
if cap.isOpened():
|
cap = cv2.VideoCapture(device_path)
|
||||||
self.available_cameras.append(device_path)
|
if cap.isOpened():
|
||||||
cap.release()
|
self.available_cameras.append(device_path)
|
||||||
except:
|
cap.release()
|
||||||
continue
|
except:
|
||||||
|
continue
|
||||||
|
|
||||||
# Add saved network cameras
|
# Add saved network cameras
|
||||||
for name, camera_info in self.network_cameras.items():
|
for name, camera_info in self.network_cameras.items():
|
||||||
@@ -476,20 +487,58 @@ class CameraDisplay(QLabel):
|
|||||||
|
|
||||||
self.fullscreen_window = QMainWindow(self.window())
|
self.fullscreen_window = QMainWindow(self.window())
|
||||||
self.fullscreen_window.setWindowTitle(f"Camera {self.cam_id} - Fullscreen")
|
self.fullscreen_window.setWindowTitle(f"Camera {self.cam_id} - Fullscreen")
|
||||||
|
self.fullscreen_window.setWindowFlags(Qt.Window | Qt.FramelessWindowHint)
|
||||||
|
|
||||||
# Create central widget
|
# Create central widget
|
||||||
central_widget = QWidget()
|
central_widget = QWidget()
|
||||||
layout = QVBoxLayout(central_widget)
|
layout = QVBoxLayout(central_widget)
|
||||||
|
layout.setContentsMargins(0, 0, 0, 0)
|
||||||
|
|
||||||
|
# Create title bar
|
||||||
|
title_bar = QWidget()
|
||||||
|
title_bar.setStyleSheet("""
|
||||||
|
QWidget {
|
||||||
|
background-color: #1E1E1E;
|
||||||
|
color: #DDD;
|
||||||
|
}
|
||||||
|
""")
|
||||||
|
title_bar.setFixedHeight(30)
|
||||||
|
title_layout = QHBoxLayout(title_bar)
|
||||||
|
title_layout.setContentsMargins(10, 0, 10, 0)
|
||||||
|
|
||||||
|
# Add title label
|
||||||
|
title_label = QLabel(f"Camera {self.cam_id} - Fullscreen")
|
||||||
|
title_layout.addWidget(title_label)
|
||||||
|
|
||||||
|
# Add close button
|
||||||
|
close_btn = QPushButton("×")
|
||||||
|
close_btn.setFixedSize(20, 20)
|
||||||
|
close_btn.setStyleSheet("""
|
||||||
|
QPushButton {
|
||||||
|
background-color: transparent;
|
||||||
|
color: #DDD;
|
||||||
|
border: none;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
QPushButton:hover {
|
||||||
|
background-color: #E81123;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
""")
|
||||||
|
close_btn.clicked.connect(self.close_fullscreen)
|
||||||
|
title_layout.addWidget(close_btn)
|
||||||
|
|
||||||
|
layout.addWidget(title_bar)
|
||||||
|
|
||||||
# Create fullscreen label
|
# Create fullscreen label
|
||||||
label = QLabel()
|
self.fullscreen_label = QLabel()
|
||||||
label.setAlignment(Qt.AlignCenter)
|
self.fullscreen_label.setAlignment(Qt.AlignCenter)
|
||||||
label.setPixmap(self.pixmap().scaled(
|
self.fullscreen_label.setPixmap(self.pixmap().scaled(
|
||||||
QApplication.primaryScreen().size(),
|
QApplication.primaryScreen().size(),
|
||||||
Qt.KeepAspectRatio,
|
Qt.KeepAspectRatio,
|
||||||
Qt.SmoothTransformation
|
Qt.SmoothTransformation
|
||||||
))
|
))
|
||||||
layout.addWidget(label)
|
layout.addWidget(self.fullscreen_label)
|
||||||
|
|
||||||
self.fullscreen_window.setCentralWidget(central_widget)
|
self.fullscreen_window.setCentralWidget(central_widget)
|
||||||
|
|
||||||
@@ -501,15 +550,31 @@ class CameraDisplay(QLabel):
|
|||||||
screenshot_shortcut = QShortcut(QKeySequence("Ctrl+S"), self.fullscreen_window)
|
screenshot_shortcut = QShortcut(QKeySequence("Ctrl+S"), self.fullscreen_window)
|
||||||
screenshot_shortcut.activated.connect(self.take_screenshot)
|
screenshot_shortcut.activated.connect(self.take_screenshot)
|
||||||
|
|
||||||
|
# Make window draggable
|
||||||
|
title_bar.mousePressEvent = self.fullscreen_mousePressEvent
|
||||||
|
title_bar.mouseMoveEvent = self.fullscreen_mouseMoveEvent
|
||||||
|
|
||||||
# Update fullscreen image when main window updates
|
# Update fullscreen image when main window updates
|
||||||
self.fullscreen_timer = QTimer()
|
self.fullscreen_timer = QTimer()
|
||||||
self.fullscreen_timer.timeout.connect(
|
self.fullscreen_timer.timeout.connect(
|
||||||
lambda: self.update_fullscreen(label)
|
lambda: self.update_fullscreen(self.fullscreen_label)
|
||||||
)
|
)
|
||||||
self.fullscreen_timer.start(30)
|
self.fullscreen_timer.start(30)
|
||||||
|
|
||||||
# Show fullscreen
|
# Show fullscreen
|
||||||
self.fullscreen_window.showFullScreen()
|
self.fullscreen_window.showMaximized()
|
||||||
|
|
||||||
|
def fullscreen_mousePressEvent(self, event):
|
||||||
|
"""Handle mouse press events for dragging"""
|
||||||
|
if event.button() == Qt.LeftButton:
|
||||||
|
self.fullscreen_window.drag_position = event.globalPos() - self.fullscreen_window.frameGeometry().topLeft()
|
||||||
|
event.accept()
|
||||||
|
|
||||||
|
def fullscreen_mouseMoveEvent(self, event):
|
||||||
|
"""Handle mouse move events for dragging"""
|
||||||
|
if hasattr(self.fullscreen_window, 'drag_position'):
|
||||||
|
self.fullscreen_window.move(event.globalPos() - self.fullscreen_window.drag_position)
|
||||||
|
event.accept()
|
||||||
|
|
||||||
def update_fullscreen(self, label):
|
def update_fullscreen(self, label):
|
||||||
"""Update the fullscreen display"""
|
"""Update the fullscreen display"""
|
||||||
|
|||||||
13
mucapy_config.json
Normal file
13
mucapy_config.json
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"network_cameras": {},
|
||||||
|
"last_model_dir": "",
|
||||||
|
"last_screenshot_dir": "/home/rattatwinko/Pictures/MuCaPy",
|
||||||
|
"last_layout": 0,
|
||||||
|
"last_fps": 10,
|
||||||
|
"last_selected_cameras": [],
|
||||||
|
"window_geometry": null,
|
||||||
|
"confidence_threshold": 0.35,
|
||||||
|
"model_dir": "/home/rattatwinko/Documents/mucapy/mucapy/mucapy/models",
|
||||||
|
"fps": 10,
|
||||||
|
"layout": 0
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user