feat: Add Camera Settings dialog for UVC controls and Qt parameters
- Implemented CameraSettingsDialog to manage UVC and Qt camera controls. - Integrated UVC parameter sliders and auto controls for brightness, contrast, saturation, hue, sharpness, gamma, white balance, backlight compensation, and exposure. - Added functionality to change white balance and exposure settings via Qt controls. - Updated MainWindow to open CameraSettingsDialog and manage UVC controller lifecycle. - Enhanced AppMenuBar to include a Camera Settings option. - Created tests for UVC controller abstraction layer and parameter info. - Documented camera specifications and supported features in new markdown files.
This commit is contained in:
480
notes/03-mvp-summary.md
Normal file
480
notes/03-mvp-summary.md
Normal file
@@ -0,0 +1,480 @@
|
||||
# Goal
|
||||
|
||||
Zbudować aplikację do podglądu kamery w czasie rzeczywistym (PySide6) z telemetrią, overlayami i systemem logowania do pliku — docelowo na Mac Mini z kamerą ELP.
|
||||
|
||||
---
|
||||
|
||||
# Constraints & Preferences
|
||||
|
||||
- Python 3.12.10, venv w `.venv-win`
|
||||
- Dev: Windows 11
|
||||
- Target: Mac Mini Intel i7, macOS Ventura, kamera ELP USB
|
||||
- `PySide6 6.11.0`, `psutil`, `pytest`, `ruff`
|
||||
- `QVideoWidget` porzucony — na Windows zasłania wszystkie child/sibling widgets przez natywny HWND D3D
|
||||
- Logi:
|
||||
- `logs/` w katalogu projektu
|
||||
- nowy plik z timestamp per sesja
|
||||
- max 20 plików
|
||||
- CSV telemetrii:
|
||||
- co 5 sekund
|
||||
- `flush` po każdym wierszu
|
||||
- CPU:
|
||||
- pokazywać oba:
|
||||
- sys %
|
||||
- per-core % (jak Task Manager)
|
||||
- Zmiana formatu kamery przez `stop+start`
|
||||
- nie `setCameraFormat` na żywej kamerze
|
||||
|
||||
---
|
||||
|
||||
# Progress
|
||||
|
||||
## Done
|
||||
|
||||
### Faza 0–7 MVP
|
||||
|
||||
- scaffolding
|
||||
- `CameraService`
|
||||
- `FrameDispatcher`
|
||||
- `TelemetryCollector`
|
||||
- `CameraView`
|
||||
- `TelemetryOverlay`
|
||||
- `IOverlayLayer`
|
||||
- `AppMenuBar`
|
||||
- `MainWindow`
|
||||
|
||||
### Rendering
|
||||
|
||||
- Usunięto `QVideoWidget`
|
||||
- `CameraView(QWidget)` z `paintEvent`
|
||||
- render + overlay w jednym przejściu
|
||||
|
||||
### Telemetria
|
||||
|
||||
`TelemetrySnapshot` — pola:
|
||||
|
||||
- `fps`
|
||||
- `target_fps`
|
||||
- `frame_time_ms`
|
||||
- `dropped_frames`
|
||||
- `cpu_percent_sys`
|
||||
- `cpu_percent_core`
|
||||
- `memory_mb`
|
||||
|
||||
### Kamera
|
||||
|
||||
- `CameraService.format_changed(float)` sygnał
|
||||
- `stop+start` przy:
|
||||
- `set_resolution`
|
||||
- `set_fps`
|
||||
|
||||
### Logowanie
|
||||
|
||||
- `_log_actual_format()`
|
||||
- loguje rzeczywisty format po starcie kamery
|
||||
- warning jeśli FPS się nie zgadza
|
||||
|
||||
### CameraFormat
|
||||
|
||||
`CameraFormat` dataclass z:
|
||||
|
||||
```python
|
||||
pixel_format: str
|
||||
```
|
||||
|
||||
Przykłady:
|
||||
|
||||
- `MJPG`
|
||||
- `YUY2`
|
||||
- `NV12`
|
||||
|
||||
w `camera_enumerator.py`
|
||||
|
||||
### Logging
|
||||
|
||||
`logging_setup.py`
|
||||
|
||||
- `FileHandler`
|
||||
- `DEBUG`
|
||||
- zawsze aktywny
|
||||
- `StreamHandler`
|
||||
- `WARNING`
|
||||
- przełączalny
|
||||
- nagłówek sesji:
|
||||
- wersja
|
||||
- platforma
|
||||
- Python
|
||||
- PySide6
|
||||
- CPU
|
||||
- RAM
|
||||
- pruning starych logów
|
||||
|
||||
### CSV
|
||||
|
||||
`csv_logger.py`
|
||||
|
||||
- `CsvTelemetryLogger`
|
||||
- throttling:
|
||||
- 5 s
|
||||
- `flush` po każdym wierszu
|
||||
|
||||
### Menu
|
||||
|
||||
`menu_bar.py`
|
||||
|
||||
- dostosowany do `CameraFormat`
|
||||
- `set_log_file_path()`
|
||||
- `set_console_level()`
|
||||
|
||||
### Config
|
||||
|
||||
`config.py`
|
||||
|
||||
- `LOG_DIR`
|
||||
- `MAX_LOG_FILES`
|
||||
- `TELEMETRY_CSV_INTERVAL_S`
|
||||
|
||||
### Main
|
||||
|
||||
`main.py`
|
||||
|
||||
- wywołuje `setup_logging()`
|
||||
- przekazuje `log_path` do `MainWindow`
|
||||
|
||||
### Main Window
|
||||
|
||||
`main_window.py`
|
||||
|
||||
- przyjmuje:
|
||||
|
||||
```python
|
||||
log_path: Path | None
|
||||
```
|
||||
|
||||
- tworzy:
|
||||
|
||||
```python
|
||||
CsvTelemetryLogger(log_path.with_suffix(".csv"))
|
||||
```
|
||||
|
||||
- podpina do:
|
||||
- `telemetry.metrics_updated`
|
||||
- wywołuje:
|
||||
- `menu.set_log_file_path()`
|
||||
- `csv_logger.close()` w `closeEvent`
|
||||
|
||||
### Repo
|
||||
|
||||
`.gitignore`
|
||||
|
||||
- dodano `logs/`
|
||||
|
||||
### Testy i jakość
|
||||
|
||||
- 20 testów jednostkowych
|
||||
- wszystkie zielone
|
||||
- `ruff`
|
||||
- czysty
|
||||
- wszystkie błędy naprawione
|
||||
|
||||
### Artefakty sesji
|
||||
|
||||
Para plików per sesja:
|
||||
|
||||
```text
|
||||
logs/duck-preview_<timestamp>.log
|
||||
logs/duck-preview_<timestamp>.csv
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## In Progress
|
||||
|
||||
- (none)
|
||||
|
||||
---
|
||||
|
||||
## Blocked
|
||||
|
||||
- (none)
|
||||
|
||||
---
|
||||
|
||||
# Key Decisions
|
||||
|
||||
## Rendering
|
||||
|
||||
### `QVideoWidget` → własny `CameraView(QWidget)`
|
||||
|
||||
Jedyny skuteczny sposób obejścia problemu z natywnym HWND na Windows.
|
||||
|
||||
## Overlay Architecture
|
||||
|
||||
### `IOverlayLayer` ABC
|
||||
|
||||
Pluggable overlaye bez modyfikacji `CameraView`.
|
||||
|
||||
Gotowe pod:
|
||||
|
||||
- YOLO
|
||||
- OCR
|
||||
- inne overlaye
|
||||
|
||||
## Pipeline
|
||||
|
||||
### `FrameDispatcher`
|
||||
|
||||
Pub/sub z `drop_if_busy`:
|
||||
|
||||
- render może gubić klatki
|
||||
- telemetria nigdy
|
||||
|
||||
## CPU Metrics
|
||||
|
||||
- CPU per-core (`psutil`)
|
||||
- dzielone przez `cpu_count`
|
||||
- wynik zgodny z Task Manager
|
||||
|
||||
## Memory Metrics
|
||||
|
||||
- `memory_info().wset` (Windows)
|
||||
- zamiast `rss`
|
||||
- odpowiada `Private Working Set`
|
||||
|
||||
## Logging Strategy
|
||||
|
||||
Dwa osobne pliki per sesja:
|
||||
|
||||
- `.log` — diagnostyka
|
||||
- `.csv` — metryki szeregów czasowych
|
||||
|
||||
## CameraFormat
|
||||
|
||||
`CameraFormat` dataclass zamiast krotki:
|
||||
|
||||
- niesie `pixel_format`
|
||||
- potrzebny w logach
|
||||
|
||||
---
|
||||
|
||||
# Next Steps
|
||||
|
||||
1. Przetestować na Windows:
|
||||
- czy logi powstają w `logs/`
|
||||
- czy CSV zapisuje dane co ~5 s
|
||||
|
||||
2. Przenieść na Mac Mini i przetestować z kamerą ELP:
|
||||
- sprawdzić `pixel_format` w logu
|
||||
- sprawdzić wykrycie backendu AVFoundation
|
||||
|
||||
3. Zweryfikować overlay telemetrii na żywym obrazie
|
||||
|
||||
4. (Opcjonalnie) dodać kolejne `IOverlayLayer`
|
||||
- YOLO
|
||||
- OCR
|
||||
|
||||
---
|
||||
|
||||
# Critical Context
|
||||
|
||||
## Camera Enumerator
|
||||
|
||||
`CameraEnumerator.list_cameras()` zwraca:
|
||||
|
||||
```python
|
||||
list[CameraInfo]
|
||||
```
|
||||
|
||||
gdzie:
|
||||
|
||||
```python
|
||||
formats: list[CameraFormat]
|
||||
```
|
||||
|
||||
`menu_bar.py` i `camera_service.py` iterują po:
|
||||
|
||||
- `fmt.width`
|
||||
- `fmt.height`
|
||||
- `fmt.max_fps`
|
||||
|
||||
---
|
||||
|
||||
## CSV Logger
|
||||
|
||||
Ścieżka CSV:
|
||||
|
||||
```python
|
||||
log_path.with_suffix(".csv")
|
||||
```
|
||||
|
||||
Powstaje para:
|
||||
|
||||
- `.log`
|
||||
- `.csv`
|
||||
|
||||
z tym samym timestamp.
|
||||
|
||||
---
|
||||
|
||||
## Console Logging
|
||||
|
||||
```python
|
||||
logging_setup.set_console_level(debug: bool)
|
||||
```
|
||||
|
||||
wywoływane z:
|
||||
|
||||
```python
|
||||
menu_bar._on_log_toggled
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Pixel Format
|
||||
|
||||
```python
|
||||
pixel_format_name()
|
||||
```
|
||||
|
||||
eksportowane z:
|
||||
|
||||
```python
|
||||
camera_enumerator.py
|
||||
```
|
||||
|
||||
używane również w:
|
||||
|
||||
```python
|
||||
camera_service.py
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Log Header
|
||||
|
||||
Nagłówek logu zawiera:
|
||||
|
||||
- wersję aplikacji
|
||||
- platformę
|
||||
- Python
|
||||
- PySide6
|
||||
- liczbę CPU
|
||||
- RAM
|
||||
|
||||
---
|
||||
|
||||
## Uruchamianie
|
||||
|
||||
```bash
|
||||
.venv-win\Scripts\python.exe -m app.main
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Ruff Fixes
|
||||
|
||||
Naprawiono:
|
||||
|
||||
- `E501`
|
||||
- długa linia w `camera_enumerator.py`
|
||||
- `F401`
|
||||
- `I001`
|
||||
- w `camera_service.py`
|
||||
- w `main.py`
|
||||
|
||||
---
|
||||
|
||||
# Relevant Files
|
||||
|
||||
## Entry Point
|
||||
|
||||
- `app/main.py`
|
||||
- wywołuje `setup_logging()`
|
||||
- przekazuje `log_path`
|
||||
|
||||
## Config
|
||||
|
||||
- `app/config.py`
|
||||
- `LOG_DIR`
|
||||
- `MAX_LOG_FILES`
|
||||
- `TELEMETRY_CSV_INTERVAL_S`
|
||||
|
||||
## Logging
|
||||
|
||||
- `app/logging_setup.py`
|
||||
- konfiguracja logowania
|
||||
- nagłówek sesji
|
||||
- pruning
|
||||
|
||||
## Telemetry
|
||||
|
||||
- `app/telemetry/csv_logger.py`
|
||||
- zapis CSV z throttlingiem
|
||||
|
||||
- `app/telemetry/telemetry_collector.py`
|
||||
- `TelemetrySnapshot`
|
||||
- `TelemetryCollector`
|
||||
|
||||
## Camera
|
||||
|
||||
- `app/camera/camera_enumerator.py`
|
||||
- `CameraFormat`
|
||||
- `CameraInfo`
|
||||
- `pixel_format_name()`
|
||||
|
||||
- `app/camera/camera_service.py`
|
||||
- `CameraService`
|
||||
- `format_changed`
|
||||
- `_log_actual_format()`
|
||||
|
||||
## UI
|
||||
|
||||
- `app/ui/main_window.py`
|
||||
- kompletny
|
||||
- podpięty `CsvTelemetryLogger`
|
||||
|
||||
- `app/ui/menu_bar.py`
|
||||
- `set_log_file_path()`
|
||||
- `set_console_level()`
|
||||
|
||||
- `app/ui/camera_view.py`
|
||||
- `CameraView`
|
||||
- rejestr `IOverlayLayer`
|
||||
|
||||
## Overlay
|
||||
|
||||
- `app/overlay/overlay_layer.py`
|
||||
- `IOverlayLayer` ABC
|
||||
|
||||
- `app/overlay/telemetry_overlay.py`
|
||||
- `TelemetryOverlay(IOverlayLayer)`
|
||||
|
||||
## Pipeline
|
||||
|
||||
- `app/pipeline/frame_dispatcher.py`
|
||||
- pub/sub
|
||||
- `drop_if_busy`
|
||||
|
||||
## Tests
|
||||
|
||||
- `tests/test_telemetry_collector.py`
|
||||
- 12 testów
|
||||
- mockuje `cpu_count`
|
||||
|
||||
- `tests/test_frame_dispatcher.py`
|
||||
- 8 testów
|
||||
|
||||
## Repo / Docs
|
||||
|
||||
- `.gitignore`
|
||||
- zawiera `logs/`
|
||||
|
||||
- `notes/01-mvp-preview.md`
|
||||
- PRD
|
||||
|
||||
- `notes/01-mvp-plan.md`
|
||||
- plan implementacji
|
||||
|
||||
- `notes/02-mvp-app.md`
|
||||
- stan aplikacji
|
||||
- historia prób i decyzji architektonicznych
|
||||
182
notes/camera_elp.md
Normal file
182
notes/camera_elp.md
Normal file
@@ -0,0 +1,182 @@
|
||||
# Camera Specification
|
||||
|
||||
## Model
|
||||
|
||||
**ELP-USB4KHDR01-MFV(5-50)**
|
||||
(10X zoom manual lens)
|
||||
|
||||
### Optional
|
||||
|
||||
**ELP-USB4KHDR01-MFV(2.8-12)**
|
||||
(2.8-12mm manual zoom lens)
|
||||
|
||||
---
|
||||
|
||||
## Sensor
|
||||
|
||||
- SONY IMX317 (1/2.5”)
|
||||
|
||||
## Max Resolution
|
||||
|
||||
- 3840(H) × 2160(V)
|
||||
|
||||
## Sensitivity
|
||||
|
||||
- 1000mV/Lux-sec
|
||||
|
||||
## Image Area
|
||||
|
||||
- 6100μm × 4524μm
|
||||
|
||||
## Picture Format
|
||||
|
||||
- MJPEG
|
||||
- YUY2 (YUYV)
|
||||
|
||||
---
|
||||
|
||||
# Resolution & FPS
|
||||
|
||||
## MJPEG Modes
|
||||
|
||||
| Resolution | FPS |
|
||||
|---|---|
|
||||
| 3840×2160 | 30 fps |
|
||||
| 2592×1944 | 30 fps |
|
||||
| 2048×1536 | 30 fps |
|
||||
| 1600×1200 | 30 fps |
|
||||
| 1920×1080 | 30 fps |
|
||||
| 1280×1024 | 30 fps |
|
||||
| 1280×960 | 30 fps |
|
||||
| 1280×720 | 30 fps |
|
||||
| 1024×768 | 30 fps |
|
||||
| 800×600 | 30 fps |
|
||||
| 640×480 | 30 fps |
|
||||
| 320×240 | 30 fps |
|
||||
|
||||
## YUY2 Modes
|
||||
|
||||
| Resolution | FPS |
|
||||
|---|---|
|
||||
| 3840×2160 | 1 fps |
|
||||
| 2592×1944 | 1 fps |
|
||||
| 2048×1536 | 3 fps |
|
||||
| 1600×1200 | 3 fps |
|
||||
| 1920×1080 | 3 fps |
|
||||
| 1280×1024 | 3 fps |
|
||||
| 1280×960 | 5 fps |
|
||||
| 1280×720 | 5 fps |
|
||||
| 1024×768 | 5 fps |
|
||||
| 800×600 | 20 fps |
|
||||
| 640×480 | 30 fps |
|
||||
| 320×240 | 30 fps |
|
||||
|
||||
---
|
||||
|
||||
## Optical / Image Parameters
|
||||
|
||||
| Parameter | Value |
|
||||
|---|---|
|
||||
| Center Definition | 1000LW/PH (Center) |
|
||||
| S/N Ratio | 26dB |
|
||||
| Sensitivity | 0.65V/lux-sec@550nm |
|
||||
| Low Illumination | 0.2lux |
|
||||
| Shutter | Electronic rolling shutter / Frame exposure |
|
||||
|
||||
---
|
||||
|
||||
## Interface
|
||||
|
||||
- USB2.0 High Speed
|
||||
|
||||
---
|
||||
|
||||
## Supported Features
|
||||
|
||||
| Feature | Support |
|
||||
|---|---|
|
||||
| AEC | Yes |
|
||||
| AEB | Yes |
|
||||
| AGC | Yes |
|
||||
|
||||
---
|
||||
|
||||
## Adjustable Parameters
|
||||
|
||||
- Brightness
|
||||
- Contrast
|
||||
- Saturation
|
||||
- Hue
|
||||
- Sharpness
|
||||
- Gamma
|
||||
- White Balance
|
||||
- Backlight Contrast
|
||||
- Exposure
|
||||
|
||||
---
|
||||
|
||||
## Lens
|
||||
|
||||
- 2.8-12mm / 5-50mm varifocal manual lens optional
|
||||
|
||||
---
|
||||
|
||||
## Audio
|
||||
|
||||
- Built-in microphone
|
||||
- Supports audio recording
|
||||
|
||||
---
|
||||
|
||||
## Power
|
||||
|
||||
| Parameter | Value |
|
||||
|---|---|
|
||||
| Power Supply | USB BUS POWER 4P-2.0mm socket |
|
||||
| Voltage | DC5V |
|
||||
| Current | 200mA |
|
||||
|
||||
---
|
||||
|
||||
## Physical Dimensions
|
||||
|
||||
- 45mm × 45mm × 50mm
|
||||
|
||||
---
|
||||
|
||||
## Temperature
|
||||
|
||||
| Parameter | Value |
|
||||
|---|---|
|
||||
| Storage Temperature | -20°C to 70°C |
|
||||
| Working Temperature | 0°C to 60°C |
|
||||
|
||||
---
|
||||
|
||||
## USB Cable
|
||||
|
||||
- 3M standard
|
||||
- Optional: 1M / 2M / 5M
|
||||
|
||||
---
|
||||
|
||||
# Supported Operating Systems
|
||||
|
||||
## Windows
|
||||
|
||||
- Windows XP
|
||||
- Windows Vista
|
||||
- Windows 7
|
||||
- Windows 8
|
||||
- Windows 10
|
||||
- Windows 11
|
||||
|
||||
## Linux
|
||||
|
||||
- Linux with UVC support
|
||||
- Kernel above linux-2.6.26
|
||||
|
||||
## macOS / Android
|
||||
|
||||
- macOS X 10.4.8 or later
|
||||
- Android 4.0 or above with UVC
|
||||
Reference in New Issue
Block a user