Skip to content

Conversation

@C-Achard
Copy link

Finalizing the PySide6+multi-camera GUI by

Further refinement of GUI added in #35.

Features

  • Full project file tree refactor for more granularity and ease of use
  • Typed configs
  • Improved settings UX/UI
  • Theme/UI alignment with DLC, icons, colors, etc
  • Improved camera loading UX and validation
  • Many fixes to OpenCV backend
  • Fixes all issues in Pre-release fixes & improvements checklist #37

Also tweaks error handling, UI and UX.


Additional TODOs

  • Documentation overhaul (separate PR?)
  • Comprehensive unit and GUI test suite, >80% coverage (49% current)

arturoptophys and others added 30 commits October 21, 2025 11:22
…modern-python-and-pyqt6

Add Basler and GenTL camera backends for modular capture
…camera-functionality

Rework layout and camera handling controls
…r integration

- Implemented `get_device_count` method in `GenTLCameraBackend` to retrieve the number of GenTL devices detected.
- Added `max_devices` configuration option in `CameraSettings` to limit device probing.
- Introduced `BoundingBoxSettings` for bounding box visualization, integrated into the main GUI.
- Enhanced `DLCLiveProcessor` to accept a processor instance during configuration.
- Updated GUI to support processor selection and auto-recording based on processor commands.
- Refactored camera properties handling and removed deprecated advanced properties editor.
- Improved error handling and logging for processor connections and recording states.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
C-Achard and others added 27 commits January 28, 2026 11:41
Refactor camera configuration dialog to use background threads for camera detection and preview loading, improving UI responsiveness. Update OpenCV backend for robust, fast startup and Windows-optimized camera handling. Enhance camera factory to support cancellation and progress reporting during device discovery.
Cleaned up comments and removed 'NEW' markers in camera_config_dialog.py. Adjusted the order of UI preparation and loader creation in the camera preview logic, and commented out redundant loader cancellation code.
Refactored the OpenCVCameraBackend to improve platform-specific handling for Windows, macOS, and Linux. Added resolution normalization, alternate index probing, and robust fallback logic for device opening and configuration. Improved MJPG enabling, property whitelisting, and added a quick_ping discovery helper. Enhanced logging and made the backend more robust to device quirks and transient errors.
Updated CameraLoadWorker to emit the camera object directly and moved backend creation to the main thread for Windows compatibility. Improved _on_loader_success to handle both CameraBackend and CameraSettings payloads, ensuring proper preview initialization and error handling. Also fixed overlay geometry handling and reset preview state on stop.
Introduces a theme selection menu with dark and system (default) styles using qdarkstyle and QActionGroup. The current theme is tracked and can be switched via the new Appearance submenu under View.
Added 'qdarkstyle' to main dependencies for UI theming. Introduced 'pytorch' and 'tf' optional dependency groups for deeplabcut-live with respective extras.
Introduces a dropdown to select which camera is used for pose inference, replacing the previous hardcoded behavior. Updates camera label formatting and synchronizes selection between dialogs and main window. Removes unused additional options UI and ensures overlays update when the inference camera changes.
Refactored camera FPS tracking to support multiple cameras using per-camera deques and a configurable time window. Enhanced the camera stats panel to display per-camera FPS with clearer formatting, improved layout and sizing of stats widgets, and enabled text selection for stats labels. Minor UI adjustments were made for better usability and appearance.
Replaces the nested QHBoxLayout-based stats section with a QGridLayout for improved alignment and spacing of the Camera, DLC Processor, and Recorder status labels. This change simplifies the layout code and ensures better control over column stretching and widget alignment.
Introduces splash screen functionality and displays a logo with version text in the preview area when cameras are not running. Adds new logo and welcome image assets, updates the main window class name to DLCLiveMainWindow, and refactors icon loading and display logic for improved branding and user experience.
Enhances robustness by stopping and removing recorders after write errors, updating user notifications, and refining error messages for device disconnection. Also improves thread finalization and error handling in the VideoRecorder's writer loop.
Introduces persistent storage of the last used model path using QSettings and validates model files with a new utility function. Enhances camera selection logic to handle dynamic camera availability, updates the inference camera dropdown accordingly, and improves error handling and logging. Adds dlclivegui/utils.py with is_model_file for model file validation.
Refactors CameraConfigDialog to use a working copy of settings, adds UI helpers for backend-specific controls, and improves preview FPS reconciliation. Enhances camera backend probing in factory.py with quick_ping and sanitized settings, and exposes actual_fps and actual_resolution in OpenCVCameraBackend. Updates main window to skip camera validation while the config dialog is active.
Enhances the CameraConfigDialog to better handle Enter key events, apply settings more robustly, and improve preview state management. Refines FPS reconciliation logic for OpenCV cameras, ensuring user-requested FPS is not overwritten unless actual FPS is measurable. In the OpenCV backend, replaces LOG with logger, adds more detailed debug logging, and clarifies FPS and resolution handling, including improved logging for property setting and codec negotiation.
Major refactor of the GUI codebase: moves main window, camera config dialog, and theme logic into a new gui/ subpackage; introduces a RecordingManager for multi-camera recording; modularizes display, stats, and utility functions into utils/; moves service logic (DLC processor, video recorder, multi-camera controller) into services/; updates imports and usage throughout. This improves maintainability, separation of concerns, and code clarity.
Corrects the dlclivegui script entry point in pyproject.toml to point to dlclivegui:main. Cleans up comments and redundant code in splash screen logic in main.py. Updates a status message in camera_config_dialog.py for clarity.
Camera backends have been moved to a dedicated 'backends' subpackage and now use a registry with decorators for dynamic registration. Introduced config_adapters for flexible CameraSettings handling, and added Pydantic-based config models in utils/config_models.py for validation and conversion. The camera factory and processor logic now accept both dataclass and Pydantic models, improving flexibility and type safety. Also added a QtSettingsStore utility for persistent settings, and updated dependencies to include pydantic.
Introduce comprehensive test coverage for camera adapters, factory, and fake backends, as well as the DLC processor service. Includes fixtures and test doubles for isolated testing, and covers configuration, initialization, frame processing, error handling, and statistics computation.
Enhanced MultiCameraController to accept various camera settings formats (dataclasses, dicts, or pydantic models) and normalize them. Added a utility for converting settings, updated worker and controller logic, and introduced a new test for mixed input types. Also added a FakeBackend and patch_factory fixture for testing.
Added unit tests to verify frame rotation and cropping behavior, as well as handling of camera initialization failures in MultiCameraController. These tests improve coverage for edge cases and error handling.
Avoid calling queue.task_done() for the shutdown sentinel in DLCLiveProcessor worker loop and guard against ValueError if task_done is called unexpectedly. This prevents erroneous task accounting when the sentinel is used to stop the thread.

Add GUI end-to-end tests and test fixtures: introduce tests/services/gui/conftest.py to provide a headless DLCLiveMainWindow fixture, patch CameraFactory and DLCLive to use test doubles, and add tests/services/gui/test_e2e.py which exercises preview rendering and inference flow. Minor test updates: supply a FakeBackend import for camera factory tests and add stop() stubs to fake backend implementations used in tests.
Migrate config dataclasses to Pydantic models and add lazy backend discovery.

Key changes:
- Replace dataclass-based CameraSettings/ApplicationSettings/etc. with Pydantic models in utils/config_models.py (CameraSettingsModel, ApplicationSettingsModel, MultiCameraSettingsModel, etc.). Added model helpers (from_dict/to_dict, load/save, output_path, writegear_options, convenience methods).
- Update camera backend API to accept CameraSettingsModel and tighten abstract methods (raise NotImplementedError by default).
- Rename and expose internal backend registry as _BACKEND_REGISTRY and update factory code to reference it.
- Implement lazy backend loading in cameras.factory: import backend packages/modules via importlib/pkgutil on first use so third-party or on-disk backend packages can register themselves via @register_backend. Added guard to raise if no backends are registered in GUI dialog.
- Adapt GUI (camera_config_dialog.py, main_window.py) to use the new models and validate/coerce form data via Pydantic models. Added form->model builder and updated preview/reconcile logic to operate on models.
- Add dlclivegui/cameras/backends/__init__.py to import built-in backend modules.
- Add tests/cameras/test_backend_discovery.py to verify lazy discovery, detection and creation of a temporarily installed test backend package.

Notes/compatibility:
- Public APIs that previously accepted dataclasses now expect the new *Model types (e.g. CameraSettingsModel, ApplicationSettingsModel). This is a breaking change; conversion helpers/compat shims were added where needed in the GUI.
- Factory now ensures backends are imported before listing/using them, enabling plugin/backends discovered on disk.
- Small behavioral change: CameraBackend methods now explicitly raise NotImplementedError unless overridden.
Replace legacy dataclass config usage with Pydantic models across cameras and DLC services. CameraSettingsModel and DLCProcessorSettingsModel are now used in controllers, processors, recorders and tests; adapters and ensure_dc_camera/list_of_dc_cameras utilities were removed/simplified. CameraBackend.stop is now an optional no-op by default. Add CameraSettingsModel helpers (from_dict, from_defaults, apply_defaults) and relax backend typing/default. Update tests and imports accordingly, and remove the obsolete test_adapters.py file.
Add conversion helper and validation for dynamic crop settings, and sync camera UI to models.

- utils/config_models.py: Add DynamicCropModel.to_tuple() to expose (enabled, margin, max_missing_frames).
- services/dlc_processor.py: Accept DynamicCropModel-like objects for dynamic settings by attempting .to_tuple(); validate format and raise a clear error on invalid data before unpacking.
- gui/camera_config_dialog.py: Automatically select the first available camera backend after populating the backend list, add _write_form_to_cam() to write UI control values back into a CameraSettingsModel, and update the preview reopen call to match the changed _needs_preview_reopen signature.

These changes improve robustness when dynamic crop settings are provided as model objects and ensure the camera configuration UI persists and selects a usable backend by default.
Major refactor of DLCLiveProcessor: remove legacy settings normalization, simplify configure(), start worker on first enqueued frame, always enqueue if queue exists, and eliminate sentinel-based shutdown. Introduce _timed_processor contextmanager and a dedicated _process_frame() to separate GPU inference, optional processor overhead timing, signal emission, and stats updates; add frame_processed signal and improve queue/task_done handling and stop/drain logic. Small change in GUI main window: only stop inference on camera error when no DLC camera remains. Add unit and end-to-end tests for camera config dialog and extend/rename several test modules to cover processor behavior and queue accounting.
@C-Achard C-Achard self-assigned this Jan 30, 2026
@C-Achard C-Achard added the enhancement New feature or request label Jan 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants