Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aa17d7ffd3 | ||
|
|
e86c05a885 | ||
|
|
f728524ee6 | ||
|
|
98b43ce903 | ||
|
|
1186c3bb35 | ||
|
|
16458d98e9 | ||
|
|
8a8bea1211 | ||
|
|
a92dcf2659 |
6
.gitignore
vendored
@@ -7,3 +7,9 @@ debug_ocr/
|
||||
.ruff_cache/
|
||||
.env
|
||||
.env.*
|
||||
dataset_yolo/labels/*.cache
|
||||
dataset_yolo/labels/*_backup_before_remap_*/
|
||||
runs/flywms_dataset_check/
|
||||
runs/flywms_dataset_check_1epoch/
|
||||
navigate_snapshots*/
|
||||
wms_received*/
|
||||
|
||||
70
aggiornamento-2026-05-16-09-03.md
Normal file
@@ -0,0 +1,70 @@
|
||||
# Aggiornamento 2026-05-16 09:03
|
||||
|
||||
## Decisione
|
||||
|
||||
Separare il ritmo della preview dal ritmo di inferenza YOLO.
|
||||
|
||||
Motivo: il video sorgente e' circa 30 fps, ma la pipeline completa non deve necessariamente elaborare ogni frame. Per la demo e per la futura pipeline reale e' piu' utile mantenere bassa la latenza, lasciando che la visualizzazione e YOLO abbiano frequenze configurabili.
|
||||
|
||||
## Implementazione
|
||||
|
||||
Aggiunti due parametri in `flywms_navigation.ini` e nel parser di `flywms_navigation.py`:
|
||||
|
||||
- `preview_fps`: FPS massimo per lettura/preview realtime. `0` usa il framerate della sorgente.
|
||||
- `yolo_fps`: FPS massimo per inferenza YOLO. `0` esegue YOLO su ogni frame di preview.
|
||||
|
||||
Valori iniziali:
|
||||
|
||||
```ini
|
||||
preview_fps = 24.0
|
||||
yolo_fps = 15.0
|
||||
```
|
||||
|
||||
La stessa logica e' stata applicata anche alla shell DearPyGUI `flywms_navigation_gui.py`.
|
||||
|
||||
## Nota su video e camera reale
|
||||
|
||||
Con un file video, questi parametri simulano il ritmo desiderato della preview e limitano l'inferenza YOLO. In questa versione single-thread, se YOLO e' piu' lento del target, non si puo' arrivare al target.
|
||||
|
||||
Con una camera reale, il codice prova anche a impostare `CAP_PROP_FPS` quando la sorgente e' webcam/camera. Questo e' best effort: molti driver ignorano il valore. Il metodo robusto resta scartare frame lato software e usare sempre il frame piu' recente disponibile.
|
||||
|
||||
## Verifiche
|
||||
|
||||
Compilazione:
|
||||
|
||||
```powershell
|
||||
python -m py_compile flywms_navigation.py flywms_navigation_gui.py
|
||||
```
|
||||
|
||||
Lettura config:
|
||||
|
||||
```text
|
||||
24.0 15.0
|
||||
```
|
||||
|
||||
Run headless con `yolo_fps=15` su CPU:
|
||||
|
||||
```text
|
||||
fps=5.5 yolo_fps=5.5
|
||||
```
|
||||
|
||||
Interpretazione: su CPU il ciclo non raggiunge 15 fps, quindi YOLO gira comunque su ogni frame effettivamente processato.
|
||||
|
||||
Run headless con `yolo_fps=2`:
|
||||
|
||||
```text
|
||||
fps=13.7 yolo_fps=2.0
|
||||
```
|
||||
|
||||
Interpretazione: il throttling YOLO funziona; la preview procede piu' veloce dell'inferenza.
|
||||
|
||||
## Prossimo passo
|
||||
|
||||
Quando arrivera' la GPU, rimisurare con:
|
||||
|
||||
- `preview_fps = 24.0`;
|
||||
- `yolo_fps = 15.0`;
|
||||
- device GPU Ultralytics;
|
||||
- GUI DearPyGUI attiva.
|
||||
|
||||
Se il costo GUI diventera' dominante, separare in seguito thread inferenza e thread GUI con stato latest-frame.
|
||||
99
aggiornamento-2026-05-16-10-14.md
Normal file
@@ -0,0 +1,99 @@
|
||||
# Aggiornamento 2026-05-16 10:14
|
||||
|
||||
## Obiettivo
|
||||
|
||||
Cambiare il payload destinato all'OCR: non piu' solo il crop del gaylord, ma il crop ravvicinato dell'etichetta associata al gaylord centrato.
|
||||
|
||||
Il gaylord resta l'ancora semantica: serve per sapere a quale oggetto appartiene l'etichetta. L'etichetta diventa il target ottico da centrare e fotografare.
|
||||
|
||||
## Decisioni
|
||||
|
||||
- L'etichetta accettata deve avere classe `etichetta`.
|
||||
- Il bbox etichetta deve essere contenuto nel bbox del gaylord centrato.
|
||||
- Detection etichetta fuori da un gaylord vengono ignorate.
|
||||
- Se il gaylord e' centrato ma non c'e' etichetta contenuta, viene loggato `ETICHETTA_NON_TROVATA` e si attende un frame successivo.
|
||||
- Il crop etichetta usa padding configurabile.
|
||||
- Il sistema mantiene sia snapshot/crop gaylord sia crop etichetta.
|
||||
- Il movimento drone verso l'etichetta e il ritorno al gaylord sono simulati in pixel.
|
||||
|
||||
## Parametri aggiunti
|
||||
|
||||
In `flywms_navigation.ini`:
|
||||
|
||||
```ini
|
||||
label_class = etichetta
|
||||
label_payload_pad_ratio = 0.20
|
||||
label_move_sec = 2.0
|
||||
label_stabilization_sec = 1.0
|
||||
label_return_sec = 2.0
|
||||
```
|
||||
|
||||
## Comportamento OpenCV
|
||||
|
||||
Quando il gaylord centrato ha un'etichetta associata:
|
||||
|
||||
1. si ferma la scansione;
|
||||
2. viene disegnata una freccia nera bidirezionale dal centro del gaylord al centro dell'etichetta;
|
||||
3. vengono mostrati i comandi di centraggio etichetta;
|
||||
4. viene simulato il movimento verso l'etichetta;
|
||||
5. viene simulata la stabilizzazione;
|
||||
6. viene salvato il crop dell'etichetta;
|
||||
7. viene simulato il ritorno al centro gaylord;
|
||||
8. viene ripresa la scansione.
|
||||
|
||||
La finestra `flywms etichetta` mostra il crop dell'etichetta. La finestra `flywms snapshot` continua a mostrare il crop/debug del gaylord.
|
||||
|
||||
## Metadati
|
||||
|
||||
Ogni record JSONL ora include:
|
||||
|
||||
- `gaylord_bbox`;
|
||||
- `label_bbox`;
|
||||
- `movement_vector_px`;
|
||||
- `debug_frame_path`;
|
||||
- `ocr_payload_path`;
|
||||
- `label_payload_path`.
|
||||
|
||||
## Verifiche
|
||||
|
||||
Compilazione:
|
||||
|
||||
```powershell
|
||||
python -m py_compile flywms_navigation.py flywms_navigation_gui.py
|
||||
```
|
||||
|
||||
Run headless ordinario su 80 frame:
|
||||
|
||||
```text
|
||||
det=2 labels=1 tracks=2 snapshots=0
|
||||
```
|
||||
|
||||
Nessuno snapshot nei primi 80 frame perche' il gaylord non era ancora sulla linea stretta di scatto.
|
||||
|
||||
Run headless forzato con tolleranza larga:
|
||||
|
||||
```powershell
|
||||
python flywms_navigation.py --no-display --max-frames 6 --remote-ack-timeout-sec 0 --label-move-sec 0 --label-stabilization-sec 0 --label-return-sec 0 --snapshot-line-tolerance-ratio 0.20 --snapshot-output-dir navigate_snapshots_test --preview-fps 0 --yolo-fps 0
|
||||
```
|
||||
|
||||
Risultato:
|
||||
|
||||
```text
|
||||
SNAPSHOT 0001 track=2 frame=3 pos=gaylord 1
|
||||
CENTRA_ETICHETTA dx=+314px dy=-498px
|
||||
SCATTA_FOTO_ETICHETTA snapshot_0001_track_002_label_payload.jpg
|
||||
INVIA_ROI_REMOTA snapshot_0001_track_002_label_payload.jpg
|
||||
```
|
||||
|
||||
Crop generati:
|
||||
|
||||
```text
|
||||
label_payload: (94, 371, 3)
|
||||
ocr_payload/gaylord: (1079, 1114, 3)
|
||||
```
|
||||
|
||||
## Limiti noti
|
||||
|
||||
- Il tracking etichetta non e' ancora un tracker separato; per ora usa la detection etichetta contenuta nel gaylord durante la finestra candidata.
|
||||
- Se piu' etichette sono contenute nello stesso gaylord, viene scelto un fallback deterministico. In condizioni corrette non dovrebbe accadere.
|
||||
- La GUI DearPyGUI e' stata aggiornata solo per non regredire, ma la validazione visuale di questa fase e' pensata sulle finestre OpenCV.
|
||||
41
aggiornamento-2026-05-16-10-37.md
Normal file
@@ -0,0 +1,41 @@
|
||||
# Aggiornamento 2026-05-16 10:37
|
||||
|
||||
## Obiettivo
|
||||
|
||||
Rendere piu' leggibile la simulazione di movimento verso l'etichetta nella finestra OpenCV dei comandi.
|
||||
|
||||
## Modifiche
|
||||
|
||||
- Aumentate di un secondo le pause configurate:
|
||||
- `label_move_sec`: da 2.0 a 3.0;
|
||||
- `label_stabilization_sec`: da 1.0 a 2.0;
|
||||
- `label_return_sec`: da 2.0 a 3.0.
|
||||
- Aggiunto un riquadro grafico nella finestra `flywms comandi`.
|
||||
- Durante `CENTRA_ETICHETTA` il riquadro mostra una freccia grande dal centro gaylord verso nord-est/etichetta.
|
||||
- Durante `RITORNA_CENTRO_GAYLORD` il riquadro mostra una freccia grande dall'etichetta verso il centro gaylord.
|
||||
|
||||
## Verifiche
|
||||
|
||||
Compilazione:
|
||||
|
||||
```powershell
|
||||
python -m py_compile flywms_navigation.py flywms_navigation_gui.py
|
||||
```
|
||||
|
||||
Lettura configurazione:
|
||||
|
||||
```text
|
||||
3.0 2.0 3.0
|
||||
```
|
||||
|
||||
Run headless forzato:
|
||||
|
||||
```powershell
|
||||
python flywms_navigation.py --no-display --max-frames 6 --remote-ack-timeout-sec 0 --label-move-sec 0 --label-stabilization-sec 0 --label-return-sec 0 --snapshot-line-tolerance-ratio 0.20 --snapshot-output-dir navigate_snapshots_test --preview-fps 0 --yolo-fps 0
|
||||
```
|
||||
|
||||
La verifica visuale va fatta con le finestre OpenCV:
|
||||
|
||||
```powershell
|
||||
python flywms_navigation.py
|
||||
```
|
||||
30
aggiornamento-2026-05-16-10-47.md
Normal file
@@ -0,0 +1,30 @@
|
||||
# Aggiornamento 2026-05-16 10:47
|
||||
|
||||
## Obiettivo
|
||||
|
||||
Rendere piu' leggibili nella finestra comandi i delta di spostamento verso l'etichetta e di ritorno al centro gaylord.
|
||||
|
||||
## Modifiche
|
||||
|
||||
- Nel riquadro grafico della finestra `flywms comandi` vengono ora mostrati in grande:
|
||||
- `DX ORIZZONTALE`;
|
||||
- `DY VERTICALE`.
|
||||
- Durante `CENTRA_ETICHETTA` i valori sono quelli dal centro gaylord al centro etichetta.
|
||||
- Durante `RITORNA_CENTRO_GAYLORD` i valori sono invertiti, quindi rappresentano il movimento dall'etichetta al centro gaylord.
|
||||
- Il comando visuale della fase di ritorno contiene ora anche `dx` e `dy`.
|
||||
|
||||
## Verifiche
|
||||
|
||||
Compilazione:
|
||||
|
||||
```powershell
|
||||
python -m py_compile flywms_navigation.py flywms_navigation_gui.py
|
||||
```
|
||||
|
||||
Run headless forzato:
|
||||
|
||||
```powershell
|
||||
python flywms_navigation.py --no-display --max-frames 6 --remote-ack-timeout-sec 0 --label-move-sec 0 --label-stabilization-sec 0 --label-return-sec 0 --snapshot-line-tolerance-ratio 0.20 --snapshot-output-dir navigate_snapshots_test --preview-fps 0 --yolo-fps 0
|
||||
```
|
||||
|
||||
La verifica effettiva dei delta grandi va fatta con finestra OpenCV attiva.
|
||||
50
aggiornamento-2026-05-16-10-49.md
Normal file
@@ -0,0 +1,50 @@
|
||||
# Aggiornamento 2026-05-16 10:49
|
||||
|
||||
## Obiettivo
|
||||
|
||||
Rendere configurabile la posizione e dimensione delle finestre OpenCV.
|
||||
|
||||
## Modifiche
|
||||
|
||||
Aggiunti parametri in `flywms_navigation.ini`:
|
||||
|
||||
```ini
|
||||
window_layout_enabled = true
|
||||
navigate_window = 20,40,1100,620
|
||||
commands_window = 1140,40,760,520
|
||||
snapshot_window = 1140,590,520,360
|
||||
label_window = 1140,980,520,260
|
||||
```
|
||||
|
||||
Formato:
|
||||
|
||||
```text
|
||||
x,y,width,height
|
||||
```
|
||||
|
||||
In `flywms_navigation.py` sono state aggiunte:
|
||||
|
||||
- `parse_window_rect`;
|
||||
- `apply_window_layout`.
|
||||
|
||||
La funzione viene chiamata subito dopo la creazione delle finestre OpenCV.
|
||||
|
||||
## Verifiche
|
||||
|
||||
Compilazione:
|
||||
|
||||
```powershell
|
||||
python -m py_compile flywms_navigation.py flywms_navigation_gui.py
|
||||
```
|
||||
|
||||
Lettura configurazione:
|
||||
|
||||
```text
|
||||
True
|
||||
20,40,1100,620
|
||||
1140,40,760,520
|
||||
1140,590,520,360
|
||||
1140,980,520,260
|
||||
```
|
||||
|
||||
Nota: OpenCV applica posizione e dimensione best effort. Su Windows di solito funziona, ma DPI scaling e multi-monitor possono introdurre differenze.
|
||||
110
aggiornamento-2026-05-16-11-04.md
Normal file
@@ -0,0 +1,110 @@
|
||||
# Aggiornamento 2026-05-16 11:04
|
||||
|
||||
## Milestone prima implementazione comunicazione WMS
|
||||
|
||||
Questa milestone documenta la specifica concordata prima di completare la parte client-server reale tra `flywms_navigation.py` e un server WMS demo.
|
||||
|
||||
## Obiettivo
|
||||
|
||||
Implementare una comunicazione reale, asincrona e configurabile tra:
|
||||
|
||||
- client navigazione: `flywms_navigation.py`;
|
||||
- server WMS demo: nuovo script FastAPI.
|
||||
|
||||
Il client deve inviare il crop etichetta e i metadati dello snapshot. Il server deve ricevere, salvare i payload per debug, simulare OCR/WMS e rispondere `ACK` o `NACK`.
|
||||
|
||||
## Decisioni concordate
|
||||
|
||||
- Server demo basato su FastAPI.
|
||||
- Dipendenze installate:
|
||||
- `fastapi`;
|
||||
- `uvicorn`;
|
||||
- `python-multipart`.
|
||||
- Il server deve salvare fisicamente le immagini ricevute in una cartella di debug.
|
||||
- Modalita' risposta configurabili:
|
||||
- `always-ack`;
|
||||
- `always-nack`;
|
||||
- `alternate`;
|
||||
- `random`.
|
||||
- Il client deve poter inviare a un server su altro computer tramite IP/porta configurabili.
|
||||
- Il loop video/navigazione non deve fare la POST direttamente: invio tramite worker asincrono.
|
||||
- La sequenza logica rimane:
|
||||
- stop;
|
||||
- scatta etichetta;
|
||||
- invia WMS;
|
||||
- attende risposta o timeout;
|
||||
- riparte.
|
||||
- L'attesa della risposta deve essere gestita senza congelare brutalmente il rendering.
|
||||
|
||||
## Configurazione prevista lato navigazione
|
||||
|
||||
Da aggiungere/validare in `flywms_navigation.ini`:
|
||||
|
||||
```ini
|
||||
wms_enabled = false
|
||||
wms_server_url = http://127.0.0.1:8088/api/v1/navigation-snapshot
|
||||
wms_client_id = flywms-demo-01
|
||||
wms_timeout_sec = 2.0
|
||||
wms_queue_max_size = 8
|
||||
wms_send_gaylord_debug = true
|
||||
```
|
||||
|
||||
Per server remoto:
|
||||
|
||||
```ini
|
||||
wms_server_url = http://192.168.1.50:8088/api/v1/navigation-snapshot
|
||||
```
|
||||
|
||||
## Configurazione prevista lato server
|
||||
|
||||
Da implementare in `flywms_wms_server.py`:
|
||||
|
||||
```text
|
||||
host = 0.0.0.0
|
||||
port = 8088
|
||||
fake_ack_mode = always-ack
|
||||
fake_processing_sec = 0.5
|
||||
received_dir = wms_received
|
||||
```
|
||||
|
||||
## Protocollo previsto
|
||||
|
||||
Endpoint:
|
||||
|
||||
```text
|
||||
POST /api/v1/navigation-snapshot
|
||||
```
|
||||
|
||||
Payload multipart:
|
||||
|
||||
- `metadata`: JSON;
|
||||
- `label_image`: JPEG crop etichetta;
|
||||
- `gaylord_image`: JPEG opzionale/debug.
|
||||
|
||||
Risposta:
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "ACK",
|
||||
"request_id": "...",
|
||||
"message": "codice valido su WMS",
|
||||
"fake_ocr_text": "DEMO-0001",
|
||||
"processing_ms": 120
|
||||
}
|
||||
```
|
||||
|
||||
Oppure:
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "NACK",
|
||||
"request_id": "...",
|
||||
"message": "codice non riconosciuto",
|
||||
"fake_ocr_text": "",
|
||||
"processing_ms": 120
|
||||
}
|
||||
```
|
||||
|
||||
## Nota operativa
|
||||
|
||||
Al momento della creazione di questa milestone erano gia' stati installati i pacchetti FastAPI e iniziati i primi campi/config del client WMS. La milestone serve a fissare la specifica prima di proseguire con il completamento.
|
||||
132
aggiornamento-2026-05-16-11-12.md
Normal file
@@ -0,0 +1,132 @@
|
||||
# Aggiornamento 2026-05-16 11:12
|
||||
|
||||
## Obiettivo
|
||||
|
||||
Completare la prima implementazione reale client-server tra `flywms_navigation.py` e un server WMS demo.
|
||||
|
||||
## Implementazione
|
||||
|
||||
### Client navigazione
|
||||
|
||||
In `flywms_navigation.py` sono stati aggiunti:
|
||||
|
||||
- `WmsSnapshotJob`;
|
||||
- `WmsResult`;
|
||||
- `WmsAsyncClient`;
|
||||
- creazione multipart HTTP senza base64;
|
||||
- worker thread con coda non bloccante;
|
||||
- invio del crop etichetta e, se configurato, del frame/debug gaylord;
|
||||
- attesa di risposta WMS dopo il ritorno simulato al centro gaylord;
|
||||
- gestione `ACK`, `NACK`, `ERROR`, `TIMEOUT`.
|
||||
|
||||
Il loop video non esegue direttamente la POST: accoda il job e il worker invia in background.
|
||||
|
||||
### Server WMS demo
|
||||
|
||||
Aggiunto `flywms_wms_server.py` basato su FastAPI.
|
||||
|
||||
Endpoint:
|
||||
|
||||
```text
|
||||
POST /api/v1/navigation-snapshot
|
||||
GET /health
|
||||
```
|
||||
|
||||
Payload multipart:
|
||||
|
||||
- `metadata`: JSON;
|
||||
- `label_image`: JPEG crop etichetta;
|
||||
- `gaylord_image`: JPEG opzionale/debug.
|
||||
|
||||
Il server salva ogni richiesta in:
|
||||
|
||||
```text
|
||||
wms_received/
|
||||
```
|
||||
|
||||
oppure nella directory passata con `--received-dir`.
|
||||
|
||||
Modalita risposta:
|
||||
|
||||
- `always-ack`;
|
||||
- `always-nack`;
|
||||
- `alternate`;
|
||||
- `random`.
|
||||
|
||||
### Configurazione
|
||||
|
||||
Parametri aggiunti in `flywms_navigation.ini`:
|
||||
|
||||
```ini
|
||||
wms_enabled = false
|
||||
wms_server_url = http://127.0.0.1:8088/api/v1/navigation-snapshot
|
||||
wms_client_id = flywms-demo-01
|
||||
wms_timeout_sec = 2.0
|
||||
wms_queue_max_size = 8
|
||||
wms_send_gaylord_debug = true
|
||||
wms_server_host = 0.0.0.0
|
||||
wms_server_port = 8088
|
||||
wms_received_dir = wms_received
|
||||
wms_fake_ack_mode = always-ack
|
||||
wms_fake_processing_sec = 0.5
|
||||
```
|
||||
|
||||
Aggiornato `.gitignore`:
|
||||
|
||||
```text
|
||||
wms_received*/
|
||||
```
|
||||
|
||||
## Test end-to-end
|
||||
|
||||
Server avviato in job PowerShell locale su:
|
||||
|
||||
```text
|
||||
http://127.0.0.1:8088
|
||||
```
|
||||
|
||||
Health check:
|
||||
|
||||
```json
|
||||
{"status":"ok"}
|
||||
```
|
||||
|
||||
Client headless con snapshot forzato:
|
||||
|
||||
```powershell
|
||||
python flywms_navigation.py --no-display --max-frames 6 --snapshot-line-tolerance-ratio 0.20 --snapshot-output-dir navigate_snapshots_test --preview-fps 0 --yolo-fps 0 --label-move-sec 0 --label-stabilization-sec 0 --label-return-sec 0 --remote-ack-timeout-sec 5 --wms-enabled --wms-server-url http://127.0.0.1:8088/api/v1/navigation-snapshot
|
||||
```
|
||||
|
||||
Risultato client:
|
||||
|
||||
```text
|
||||
[WMS] job accodato request_id=77cba060-1433-43f3-a387-3811e6734907 snapshot=1
|
||||
[WMS] risposta request_id=77cba060-1433-43f3-a387-3811e6734907 status=ACK message=codice valido su WMS
|
||||
[WMS] ACK request_id=77cba060-1433-43f3-a387-3811e6734907 snapshot=1 codice valido su WMS
|
||||
[CMD] RIPARTI_DESTRA
|
||||
```
|
||||
|
||||
Risultati salvati dal server:
|
||||
|
||||
```text
|
||||
wms_received_test/000001_77cba060-1433-43f3-a387-3811e6734907/metadata.json
|
||||
wms_received_test/000001_77cba060-1433-43f3-a387-3811e6734907/snapshot_0001_track_002_frame.jpg
|
||||
wms_received_test/000001_77cba060-1433-43f3-a387-3811e6734907/snapshot_0001_track_002_label_payload.jpg
|
||||
```
|
||||
|
||||
Metadati ricevuti includono:
|
||||
|
||||
- `request_id`;
|
||||
- `client_id`;
|
||||
- `snapshot_id`;
|
||||
- `simulated_position`;
|
||||
- `track_id`;
|
||||
- `gaylord_bbox`;
|
||||
- `label_bbox`;
|
||||
- `movement_vector_px`.
|
||||
|
||||
## Note
|
||||
|
||||
- La sequenza fisica simulata resta: movimento verso etichetta, stabilizzazione, scatto, ritorno al gaylord.
|
||||
- L'invio WMS parte dopo lo scatto etichetta e puo' procedere mentre viene simulato il ritorno.
|
||||
- La ripartenza viene comandata solo dopo risposta WMS o timeout.
|
||||
49
aggiornamento-2026-05-16-11-29.md
Normal file
@@ -0,0 +1,49 @@
|
||||
# Aggiornamento 2026-05-16 11:29
|
||||
|
||||
## Bugfix
|
||||
|
||||
Corretto crash all'avvio di `flywms_navigation.py --wms-enabled`.
|
||||
|
||||
Errore:
|
||||
|
||||
```text
|
||||
AttributeError: 'Namespace' object has no attribute 'window_layout_enabled'
|
||||
```
|
||||
|
||||
## Causa
|
||||
|
||||
I parametri layout finestre erano presenti in `flywms_navigation.ini` e nei default di `load_navigation_config`, ma mancavano in `parse_args()`.
|
||||
|
||||
## Correzione
|
||||
|
||||
Aggiunti argomenti CLI:
|
||||
|
||||
```text
|
||||
--window-layout-enabled
|
||||
--navigate-window
|
||||
--commands-window
|
||||
--snapshot-window
|
||||
--label-window
|
||||
```
|
||||
|
||||
## Verifiche
|
||||
|
||||
Compilazione:
|
||||
|
||||
```powershell
|
||||
python -m py_compile flywms_navigation.py flywms_navigation_gui.py flywms_wms_server.py
|
||||
```
|
||||
|
||||
Parsing argomenti:
|
||||
|
||||
```text
|
||||
True 20,40,1100,620 1140,40,760,520 1140,590,520,360 1140,980,520,260
|
||||
```
|
||||
|
||||
Run headless:
|
||||
|
||||
```powershell
|
||||
python flywms_navigation.py --no-display --max-frames 1 --wms-enabled
|
||||
```
|
||||
|
||||
Risultato: avvio e chiusura corretti senza crash.
|
||||
62
aggiornamento-2026-05-16-12-04.md
Normal file
@@ -0,0 +1,62 @@
|
||||
# Aggiornamento 2026-05-16 12:04
|
||||
|
||||
## Milestone prima implementazione OCR lato WMS server
|
||||
|
||||
## Obiettivo
|
||||
|
||||
Evolvere `flywms_wms_server.py` da server demo ACK/NACK a server WMS demo con pipeline remota:
|
||||
|
||||
1. riceve crop etichetta e metadati dal client navigazione;
|
||||
2. mostra l'immagine ricevuta in una finestra server;
|
||||
3. esegue OCR sul crop etichetta;
|
||||
4. prepara payload WMS finale;
|
||||
5. salva payload WMS su disco;
|
||||
6. simula verifica WMS con risposta `ACK`/`NACK`;
|
||||
7. risponde realmente al client.
|
||||
|
||||
## Decisioni concordate
|
||||
|
||||
- Il codice OCR deve idealmente essere il codice numerico reale sull'etichetta.
|
||||
- Se OCR reale non e' disponibile o non legge nulla, usare fallback demo configurabile.
|
||||
- Il server deve rispondere realmente al client.
|
||||
- Il client, per ora, continua a mostrare la risposta ma mantiene la logica di attesa demo gia' configurata.
|
||||
- In futuro il tempo di attesa verra' spostato completamente lato server e il client si adeguera' alla risposta.
|
||||
- La finestra payload server mostra solo l'ultimo gaylord ricevuto.
|
||||
- Il server salva anche il payload WMS finale in JSON, oltre al metadata originale.
|
||||
- L'esito `ACK/NACK` resta governato da `wms_fake_ack_mode`.
|
||||
|
||||
## Finestre server previste
|
||||
|
||||
- `wms immagine ricevuta`: crop etichetta ricevuto dal client.
|
||||
- `wms payload`: ultimo payload WMS con informazioni utili:
|
||||
- request id;
|
||||
- client id / drone;
|
||||
- snapshot id;
|
||||
- posizione;
|
||||
- codice OCR;
|
||||
- esito WMS;
|
||||
- data/ora ricezione;
|
||||
- track id;
|
||||
- bbox etichetta;
|
||||
- vettore movimento.
|
||||
|
||||
## Configurazione prevista
|
||||
|
||||
Da aggiungere in `flywms_navigation.ini`:
|
||||
|
||||
```ini
|
||||
wms_ui_enabled = true
|
||||
wms_ocr_enabled = true
|
||||
wms_ocr_mode = auto
|
||||
wms_fake_ocr_prefix = UDC
|
||||
wms_fake_ocr_delay_sec = 0.2
|
||||
wms_fake_wms_delay_sec = 1.0
|
||||
wms_operator = udrone
|
||||
wms_site = demo-magazzino
|
||||
```
|
||||
|
||||
## Note tecniche
|
||||
|
||||
La GUI OpenCV del server non deve essere aggiornata direttamente dall'handler HTTP. L'handler aggiorna stato condiviso thread-safe; un thread UI separato aggiorna le finestre OpenCV.
|
||||
|
||||
L'OCR reale verra' implementato cercando prima le opzioni gia' disponibili nell'ambiente/progetto. Se non disponibili, il server resta funzionante con fallback demo e lo segnala nel payload.
|
||||
116
aggiornamento-2026-05-16-12-08.md
Normal file
@@ -0,0 +1,116 @@
|
||||
# Aggiornamento 2026-05-16 12:08
|
||||
|
||||
## Obiettivo
|
||||
|
||||
Implementare lato `flywms_wms_server.py` la prima pipeline WMS/OCR demo con finestre server.
|
||||
|
||||
## Implementazione server
|
||||
|
||||
Il server ora:
|
||||
|
||||
- riceve crop etichetta e metadati;
|
||||
- salva `metadata.json`;
|
||||
- esegue OCR sul crop etichetta;
|
||||
- salva `wms_payload.json`;
|
||||
- aggiorna una finestra OpenCV con l'immagine ricevuta;
|
||||
- aggiorna una finestra OpenCV con il payload WMS dell'ultimo gaylord;
|
||||
- risponde al client con `ACK/NACK` e codice OCR.
|
||||
|
||||
## OCR
|
||||
|
||||
Motore implementato:
|
||||
|
||||
- EasyOCR, se disponibile;
|
||||
- fallback demo se OCR non legge nulla o se viene avviato con `--no-ocr`.
|
||||
|
||||
Sul crop di test, EasyOCR e' disponibile ma non ha letto testo utile; e' stato usato fallback:
|
||||
|
||||
```text
|
||||
UDC-0001
|
||||
```
|
||||
|
||||
Il payload indica esplicitamente:
|
||||
|
||||
```json
|
||||
"ocr_backend": "fake",
|
||||
"ocr_fallback_used": true
|
||||
```
|
||||
|
||||
oppure `easyocr-fallback` quando EasyOCR gira ma non trova testo.
|
||||
|
||||
## Configurazione aggiunta
|
||||
|
||||
In `flywms_navigation.ini`:
|
||||
|
||||
```ini
|
||||
wms_ui_enabled = true
|
||||
wms_ocr_enabled = true
|
||||
wms_ocr_mode = easyocr
|
||||
wms_fake_ocr_prefix = UDC
|
||||
wms_fake_ocr_delay_sec = 0.2
|
||||
wms_operator = udrone
|
||||
wms_site = demo-magazzino
|
||||
```
|
||||
|
||||
Il server supporta anche:
|
||||
|
||||
```powershell
|
||||
--no-ui
|
||||
--no-ocr
|
||||
```
|
||||
|
||||
per test headless.
|
||||
|
||||
## Client
|
||||
|
||||
Il client navigazione ora mostra anche il codice OCR ricevuto:
|
||||
|
||||
```text
|
||||
OCR_CODICE UDC-0001
|
||||
```
|
||||
|
||||
La risposta server include nel messaggio:
|
||||
|
||||
```text
|
||||
codice valido su WMS: UDC-0001
|
||||
```
|
||||
|
||||
## Verifiche
|
||||
|
||||
Compilazione:
|
||||
|
||||
```powershell
|
||||
python -m py_compile flywms_wms_server.py flywms_navigation.py flywms_navigation_gui.py
|
||||
```
|
||||
|
||||
Test OCR diretto sul crop etichetta:
|
||||
|
||||
```text
|
||||
OcrServerResult(text='UDC-0001', raw_text='', confidence=0.0, backend='easyocr-fallback', fallback_used=True)
|
||||
```
|
||||
|
||||
Test end-to-end server/client con server headless:
|
||||
|
||||
```powershell
|
||||
python flywms_wms_server.py --host 127.0.0.1 --port 8088 --received-dir wms_received_test --fake-processing-sec 0.1 --fake-ocr-delay-sec 0 --no-ui --no-ocr
|
||||
```
|
||||
|
||||
Client:
|
||||
|
||||
```powershell
|
||||
python flywms_navigation.py --no-display --max-frames 6 --snapshot-line-tolerance-ratio 0.20 --snapshot-output-dir navigate_snapshots_test --preview-fps 0 --yolo-fps 0 --label-move-sec 0 --label-stabilization-sec 0 --label-return-sec 0 --remote-ack-timeout-sec 5 --wms-enabled --wms-server-url http://127.0.0.1:8088/api/v1/navigation-snapshot
|
||||
```
|
||||
|
||||
Risultato:
|
||||
|
||||
```text
|
||||
[WMS] risposta request_id=... status=ACK message=codice valido su WMS: UDC-0001
|
||||
[WMS] ACK request_id=... snapshot=1 codice valido su WMS: UDC-0001
|
||||
[CMD] RIPARTI_DESTRA
|
||||
```
|
||||
|
||||
## Note
|
||||
|
||||
- La finestra server mostra l'ultimo payload ricevuto.
|
||||
- Il server salva `wms_payload.json` oltre a `metadata.json`.
|
||||
- L'esito `ACK/NACK` resta governato da `wms_fake_ack_mode`.
|
||||
43
aggiornamento-2026-05-16-12-10.md
Normal file
@@ -0,0 +1,43 @@
|
||||
# Aggiornamento 2026-05-16 12:10
|
||||
|
||||
## Obiettivo
|
||||
|
||||
Evitare falsi codici UDC quando OCR non determina davvero il testo.
|
||||
|
||||
## Decisione
|
||||
|
||||
Il primo gaylord ha etichetta tagliata. In quel caso il server non deve inventare un codice come `UDC-0001`.
|
||||
|
||||
Quando OCR fallisce o non legge testo utile, il codice restituito deve essere:
|
||||
|
||||
```text
|
||||
udc non determinato
|
||||
```
|
||||
|
||||
## Modifiche
|
||||
|
||||
In `flywms_wms_server.py`:
|
||||
|
||||
- cambiato fallback OCR;
|
||||
- aggiunto campo configurabile `undetermined_code_text`;
|
||||
- il payload mantiene `ocr_fallback_used = true`.
|
||||
|
||||
In `flywms_navigation.ini`:
|
||||
|
||||
```ini
|
||||
wms_undetermined_code_text = udc non determinato
|
||||
```
|
||||
|
||||
## Verifiche
|
||||
|
||||
Compilazione:
|
||||
|
||||
```powershell
|
||||
python -m py_compile flywms_wms_server.py flywms_navigation.py flywms_navigation_gui.py
|
||||
```
|
||||
|
||||
Test OCR sul crop del primo gaylord:
|
||||
|
||||
```text
|
||||
OcrServerResult(text='udc non determinato', raw_text='', confidence=0.0, backend='easyocr-fallback', fallback_used=True)
|
||||
```
|
||||
188
aggiornamento-2026-05-16-13-01.md
Normal file
@@ -0,0 +1,188 @@
|
||||
# Aggiornamento 2026-05-16 13:01
|
||||
|
||||
## Salvataggio discussione prima del riavvio PC
|
||||
|
||||
Questo file riassume lo stato della discussione e del lavoro fatto finora, per evitare perdita di contesto in caso di crash o riavvio.
|
||||
|
||||
## Stato generale
|
||||
|
||||
Il progetto FlyWMS sta evolvendo da una demo locale di navigazione YOLO/OpenCV verso una pipeline distribuita:
|
||||
|
||||
- `flywms_navigation.py`: simulatore drone/navigazione;
|
||||
- `flywms_wms_server.py`: server WMS demo;
|
||||
- comunicazione reale HTTP multipart tra client navigazione e server WMS;
|
||||
- crop etichetta come payload principale per OCR/WMS;
|
||||
- gaylord come ancora semantica per associare etichetta e posizione.
|
||||
|
||||
## Decisioni importanti prese
|
||||
|
||||
- Il gaylord resta l'oggetto di riferimento: serve a sapere a quale UDC/posizione appartiene l'etichetta.
|
||||
- L'OCR deve lavorare sul crop dell'etichetta, non sul crop del gaylord intero.
|
||||
- L'etichetta valida deve avere bbox contenuto nel bbox del gaylord centrato.
|
||||
- Detection etichetta fuori dal gaylord vengono ignorate.
|
||||
- Se il gaylord e' centrato ma non viene trovata un'etichetta contenuta, si segnala `ETICHETTA_NON_TROVATA` e si attende un frame successivo.
|
||||
- Il movimento drone verso etichetta e ritorno al centro gaylord e' simulato con vettore pixel `dx/dy`.
|
||||
- La freccia nera bidirezionale rappresenta il movimento dal centro gaylord al centro etichetta.
|
||||
- La finestra comandi mostra anche grandi delta:
|
||||
- `DX ORIZZONTALE`;
|
||||
- `DY VERTICALE`.
|
||||
- Le finestre OpenCV client sono configurabili da INI.
|
||||
- Il server WMS non era inizialmente dotato di finestre; poi e' stato deciso di aggiungere finestre server demo.
|
||||
- Il server WMS deve salvare immagini e payload ricevuti.
|
||||
- L'esito `ACK/NACK` per ora resta configurabile e simulato.
|
||||
- Il codice OCR deve essere reale quando possibile; se OCR non determina il codice, non bisogna inventare un valore.
|
||||
- Per il primo gaylord, avendo etichetta tagliata, il codice deve essere:
|
||||
|
||||
```text
|
||||
udc non determinato
|
||||
```
|
||||
|
||||
## File principali modificati o aggiunti
|
||||
|
||||
- `flywms_navigation.py`
|
||||
- tracking gaylord;
|
||||
- associazione etichetta contenuta nel bbox gaylord;
|
||||
- crop etichetta;
|
||||
- freccia movimento;
|
||||
- finestre OpenCV;
|
||||
- client WMS asincrono;
|
||||
- invio HTTP multipart;
|
||||
- gestione ACK/NACK/ERROR/TIMEOUT.
|
||||
|
||||
- `flywms_navigation.ini`
|
||||
- parametri navigazione;
|
||||
- parametri FPS preview/YOLO;
|
||||
- parametri etichetta;
|
||||
- parametri finestre OpenCV;
|
||||
- parametri client/server WMS;
|
||||
- parametri OCR/fallback.
|
||||
|
||||
- `flywms_wms_server.py`
|
||||
- server FastAPI;
|
||||
- endpoint `/api/v1/navigation-snapshot`;
|
||||
- endpoint `/health`;
|
||||
- salvataggio immagini e metadati;
|
||||
- OCR EasyOCR con fallback;
|
||||
- payload WMS finale;
|
||||
- finestre OpenCV server;
|
||||
- opzioni `--no-ui` e `--no-ocr`.
|
||||
|
||||
- `.gitignore`
|
||||
- aggiunto `wms_received*/`.
|
||||
|
||||
## Milestone create nella sessione
|
||||
|
||||
- `aggiornamento-2026-05-16-09-03.md`
|
||||
- `aggiornamento-2026-05-16-10-14.md`
|
||||
- `aggiornamento-2026-05-16-10-37.md`
|
||||
- `aggiornamento-2026-05-16-10-47.md`
|
||||
- `aggiornamento-2026-05-16-10-49.md`
|
||||
- `aggiornamento-2026-05-16-11-04.md`
|
||||
- `aggiornamento-2026-05-16-11-12.md`
|
||||
- `aggiornamento-2026-05-16-11-29.md`
|
||||
- `aggiornamento-2026-05-16-12-04.md`
|
||||
- `aggiornamento-2026-05-16-12-08.md`
|
||||
- `aggiornamento-2026-05-16-12-10.md`
|
||||
|
||||
## Test eseguiti
|
||||
|
||||
Compilazione piu' volte:
|
||||
|
||||
```powershell
|
||||
python -m py_compile flywms_navigation.py flywms_navigation_gui.py flywms_wms_server.py
|
||||
```
|
||||
|
||||
Test client-server WMS locale:
|
||||
|
||||
```text
|
||||
[WMS] job accodato request_id=...
|
||||
[WMS] risposta request_id=... status=ACK message=codice valido su WMS: ...
|
||||
[CMD] RIPARTI_DESTRA
|
||||
```
|
||||
|
||||
Server ha salvato:
|
||||
|
||||
```text
|
||||
metadata.json
|
||||
wms_payload.json
|
||||
snapshot_..._frame.jpg
|
||||
snapshot_..._label_payload.jpg
|
||||
```
|
||||
|
||||
OCR su primo crop etichetta:
|
||||
|
||||
```text
|
||||
OcrServerResult(text='udc non determinato', raw_text='', confidence=0.0, backend='easyocr-fallback', fallback_used=True)
|
||||
```
|
||||
|
||||
## Problema attuale prima del riavvio
|
||||
|
||||
Eseguendo:
|
||||
|
||||
```powershell
|
||||
python flywms_navigation.py --wms-enabled
|
||||
```
|
||||
|
||||
il programma sembra non partire. Dopo `CTRL+C`, lo stack trace mostra che era fermo durante l'import di Ultralytics/PyTorch:
|
||||
|
||||
```text
|
||||
detector = UltralyticsDetector(args.weights, args.ultralytics_device)
|
||||
from ultralytics import YOLO
|
||||
import torch
|
||||
KeyboardInterrupt
|
||||
```
|
||||
|
||||
Questo indica che il blocco avviene prima dell'avvio della logica WMS e prima dell'apertura del video: il processo sta impiegando molto tempo a importare `torch`/`ultralytics` o e' rallentato da stato del PC/disco/ambiente Python.
|
||||
|
||||
Non sembra causato direttamente dal codice WMS, perche' lo stack trace si ferma in import PyTorch.
|
||||
|
||||
## Diagnosi da fare dopo riavvio
|
||||
|
||||
1. Verificare tempo import PyTorch/Ultralytics:
|
||||
|
||||
```powershell
|
||||
python -c "import time; t=time.time(); import torch; print('torch', time.time()-t); t=time.time(); from ultralytics import YOLO; print('ultralytics', time.time()-t)"
|
||||
```
|
||||
|
||||
2. Verificare avvio senza WMS:
|
||||
|
||||
```powershell
|
||||
python flywms_navigation.py --no-display --max-frames 1
|
||||
```
|
||||
|
||||
3. Verificare avvio con WMS ma senza finestre:
|
||||
|
||||
```powershell
|
||||
python flywms_navigation.py --no-display --max-frames 1 --wms-enabled
|
||||
```
|
||||
|
||||
4. Avviare server WMS:
|
||||
|
||||
```powershell
|
||||
python flywms_wms_server.py --host 0.0.0.0 --port 8088
|
||||
```
|
||||
|
||||
5. Avviare navigazione:
|
||||
|
||||
```powershell
|
||||
python flywms_navigation.py --wms-enabled
|
||||
```
|
||||
|
||||
## Stato git noto
|
||||
|
||||
Ultimo commit locale fatto:
|
||||
|
||||
```text
|
||||
1186c3b configura fps preview e yolo
|
||||
```
|
||||
|
||||
Il branch risultava avanti di 1 commit rispetto a `origin/master` prima delle modifiche successive.
|
||||
|
||||
Molte modifiche successive risultano non ancora committate. Prima di proseguire dopo il riavvio conviene fare:
|
||||
|
||||
```powershell
|
||||
git status --short --branch
|
||||
python -m py_compile flywms_navigation.py flywms_navigation_gui.py flywms_wms_server.py
|
||||
```
|
||||
|
||||
e poi valutare commit/push.
|
||||
26
aggiornamento-2026-05-16-14-34.md
Normal file
@@ -0,0 +1,26 @@
|
||||
# Aggiornamento 2026-05-16 14:34
|
||||
|
||||
## Milestone test Tesseract OCR
|
||||
|
||||
## Obiettivo
|
||||
|
||||
Valutare Tesseract come alternativa piu' leggera a EasyOCR per leggere codici numerici sulle etichette.
|
||||
|
||||
## Motivazione
|
||||
|
||||
EasyOCR si e' rivelato fragile sui crop piccoli/tagliati e molto pesante in RAM/tempo di avvio. Per codici numerici semplici, Tesseract con whitelist `0123456789` potrebbe essere piu' controllabile.
|
||||
|
||||
## Strategia
|
||||
|
||||
- Verificare se `tesseract.exe` e' installato.
|
||||
- Se manca, installare/abilitare Tesseract e il package Python `pytesseract`.
|
||||
- Aggiungere supporto server a `wms_ocr_mode = tesseract`.
|
||||
- Usare OCR numerico con:
|
||||
- preprocess OpenCV;
|
||||
- whitelist cifre;
|
||||
- `--psm 7` o simile;
|
||||
- fallback `udc non determinato` se non legge un codice valido.
|
||||
|
||||
## Nota
|
||||
|
||||
Tesseract va considerato un test, non ancora la soluzione definitiva. Se confonde cifre o produce risultati instabili, dovra' restituire `udc non determinato`.
|
||||
75
aggiornamento-2026-05-16-17-18.md
Normal file
@@ -0,0 +1,75 @@
|
||||
# Aggiornamento 2026-05-16 17:18
|
||||
|
||||
## Test supporto Tesseract
|
||||
|
||||
## Stato
|
||||
|
||||
E' stato installato il wrapper Python:
|
||||
|
||||
```powershell
|
||||
python -m pip install pytesseract
|
||||
```
|
||||
|
||||
Sul PC pero' non risulta installato il binario:
|
||||
|
||||
```text
|
||||
tesseract.exe
|
||||
```
|
||||
|
||||
`where tesseract` non trova nulla.
|
||||
|
||||
## Modifiche implementate
|
||||
|
||||
In `flywms_wms_server.py` e' stato aggiunto supporto opzionale a:
|
||||
|
||||
```text
|
||||
wms_ocr_mode = tesseract
|
||||
```
|
||||
|
||||
Il server ora:
|
||||
|
||||
- usa `pytesseract` se disponibile;
|
||||
- usa whitelist numerica `0123456789`;
|
||||
- prova piu' preprocess OpenCV;
|
||||
- richiede consenso tra almeno due varianti;
|
||||
- se Tesseract non e' installato o il risultato e' ambiguo, restituisce `udc non determinato`.
|
||||
|
||||
E' stato aggiunto un controllo preventivo:
|
||||
|
||||
- se `wms_tesseract_cmd` e' configurato ma il file non esiste, fallback immediato;
|
||||
- se `tesseract` non e' nel PATH, fallback immediato.
|
||||
|
||||
Questo evita che `pytesseract` resti appeso cercando un binario assente.
|
||||
|
||||
## Verifica eseguita
|
||||
|
||||
Sul crop:
|
||||
|
||||
```text
|
||||
navigate_snapshots/snapshot_0002_track_003_label_payload.jpg
|
||||
```
|
||||
|
||||
con OCR mode `tesseract`, senza tesseract installato:
|
||||
|
||||
```text
|
||||
Tesseract fallback: tesseract.exe non trovato nel PATH
|
||||
OcrServerResult(text='udc non determinato', raw_text='', confidence=0.0, backend='tesseract-missing', fallback_used=True)
|
||||
```
|
||||
|
||||
## Nota
|
||||
|
||||
Il file `flywms_navigation.ini` al momento non e' stato aggiornato con `wms_tesseract_cmd` perche' il patch tool non e' riuscito a scriverlo in questa fase. I default del server contengono gia' `wms_tesseract_cmd = ""`, quindi il codice resta funzionante. Va aggiornato l'INI appena il file non risulta piu' bloccato.
|
||||
|
||||
## Prossimo passo
|
||||
|
||||
Installare Tesseract per Windows e poi testare:
|
||||
|
||||
```powershell
|
||||
python flywms_wms_server.py --ocr-mode tesseract
|
||||
```
|
||||
|
||||
Se `tesseract.exe` non e' nel PATH, avviare con:
|
||||
|
||||
```powershell
|
||||
python flywms_wms_server.py --ocr-mode tesseract --tesseract-cmd "C:\Program Files\Tesseract-OCR\tesseract.exe"
|
||||
```
|
||||
84
aggiornamento-2026-05-16-17-19.md
Normal file
@@ -0,0 +1,84 @@
|
||||
# Aggiornamento 2026-05-16 17:19
|
||||
|
||||
## Milestone OCR alternativo
|
||||
|
||||
## Stato corrente
|
||||
|
||||
EasyOCR e' stato giudicato troppo fragile e troppo pesante per la demo attuale:
|
||||
|
||||
- confonde cifre critiche, ad esempio `8` e `2`;
|
||||
- puo' consumare molta RAM;
|
||||
- puo' rallentare o bloccare i test;
|
||||
- non e' adatto a restituire codici WMS se la confidenza e' bassa.
|
||||
|
||||
La regola semantica decisa e':
|
||||
|
||||
```text
|
||||
meglio "udc non determinato" che un codice sbagliato
|
||||
```
|
||||
|
||||
## Decisione
|
||||
|
||||
Testare Tesseract come alternativa piu' leggera e piu' controllabile per OCR numerico.
|
||||
|
||||
La logica prevista:
|
||||
|
||||
- whitelist solo cifre `0123456789`;
|
||||
- piu' preprocess OpenCV;
|
||||
- consenso tra varianti;
|
||||
- soglia di confidenza;
|
||||
- fallback `udc non determinato` se il risultato e' assente o ambiguo.
|
||||
|
||||
## Implementazione fatta
|
||||
|
||||
In `flywms_wms_server.py`:
|
||||
|
||||
- aggiunto supporto a `ocr_mode = tesseract`;
|
||||
- aggiunto uso opzionale di `pytesseract`;
|
||||
- aggiunto controllo preventivo del binario `tesseract.exe`;
|
||||
- aggiunti preprocess:
|
||||
- grayscale;
|
||||
- sharpen;
|
||||
- Otsu threshold;
|
||||
- adaptive threshold;
|
||||
- Otsu invertito;
|
||||
- aggiunta logica di consenso;
|
||||
- se Tesseract manca, il server non resta appeso.
|
||||
|
||||
## Ambiente
|
||||
|
||||
Wrapper Python installato:
|
||||
|
||||
```text
|
||||
pytesseract
|
||||
```
|
||||
|
||||
Binario non trovato:
|
||||
|
||||
```text
|
||||
tesseract.exe
|
||||
```
|
||||
|
||||
Verifica:
|
||||
|
||||
```text
|
||||
Tesseract fallback: tesseract.exe non trovato nel PATH
|
||||
OcrServerResult(text='udc non determinato', raw_text='', confidence=0.0, backend='tesseract-missing', fallback_used=True)
|
||||
```
|
||||
|
||||
## Prossimi passi
|
||||
|
||||
1. Installare Tesseract per Windows.
|
||||
2. Verificare se `tesseract.exe` entra nel PATH.
|
||||
3. Se non entra nel PATH, avviare il server con:
|
||||
|
||||
```powershell
|
||||
python flywms_wms_server.py --ocr-mode tesseract --tesseract-cmd "C:\Program Files\Tesseract-OCR\tesseract.exe"
|
||||
```
|
||||
|
||||
4. Testare sui crop etichetta gia' salvati.
|
||||
5. Se resta fragile, valutare una mini rete neurale dedicata ai 10 caratteri numerici.
|
||||
|
||||
## Nota
|
||||
|
||||
Il file `flywms_navigation.ini` non e' ancora stato aggiornato con la voce `wms_tesseract_cmd` perche' in questa fase il patch tool non e' riuscito a scriverlo. Il server ha comunque default interni funzionanti.
|
||||
69
aggiornamento-2026-05-16-19-46.md
Normal file
@@ -0,0 +1,69 @@
|
||||
# Aggiornamento 2026-05-16 19:46
|
||||
|
||||
## Valutazione YOLO digits come OCR alternativo
|
||||
|
||||
Abbiamo analizzato il progetto `thawro/yolov8-digits-detection`:
|
||||
|
||||
- repository: https://github.com/thawro/yolov8-digits-detection
|
||||
- modello ONNX disponibile: https://huggingface.co/spaces/thawro/yolov8-digits-detection/tree/main/models
|
||||
|
||||
L'idea e' usare YOLO non per trovare il gaylord o l'etichetta, ma per leggere le cifre dentro il crop etichetta:
|
||||
|
||||
1. il client `flywms_navigation.py` individua gaylord ed etichetta come oggi;
|
||||
2. il server WMS riceve il crop dell'etichetta;
|
||||
3. il server passa il crop a un detector YOLO digits;
|
||||
4. il detector restituisce bbox e classe delle singole cifre;
|
||||
5. il server ordina le cifre da sinistra a destra;
|
||||
6. il codice UDC finale e' la concatenazione delle cifre riconosciute;
|
||||
7. se la sequenza non e' valida, il server deve rispondere `udc non determinato`.
|
||||
|
||||
## Considerazioni tecniche
|
||||
|
||||
Il progetto dichiara un dataset basato su cifre manoscritte HWD+, ma il demo video mostra anche riconoscimento su caratteri stampati. Questo significa che non va escluso a priori: va provato sui nostri crop reali, perche' potrebbe generalizzare abbastanza bene sulle etichette del video.
|
||||
|
||||
Vantaggi:
|
||||
|
||||
- modello piccolo: `yolo.onnx` e' circa 12 MB;
|
||||
- potenzialmente molto piu' leggero di EasyOCR;
|
||||
- puo' evitare il caricamento di EasyOCR/PyTorch nel server WMS;
|
||||
- architettura adatta al nostro caso, perche' il codice UDC e' composto da cifre;
|
||||
- output interpretabile: bbox, confidenza e classe di ogni cifra.
|
||||
|
||||
Rischi:
|
||||
|
||||
- il dominio di training non e' identico alle nostre etichette industriali;
|
||||
- alcune cifre critiche, ad esempio 8 e 2, potrebbero comunque essere confuse;
|
||||
- serve una fase di validazione su immagini reali delle nostre etichette;
|
||||
- la licenza del repository/modello deve essere verificata prima di un uso oltre la demo;
|
||||
- il modello riconosce singole cifre, quindi dovremo implementare noi ordinamento, filtri e validazione.
|
||||
|
||||
## Proposta di integrazione
|
||||
|
||||
Non conviene importare tutto il progetto come package. Conviene invece:
|
||||
|
||||
- scaricare/posizionare il modello `yolo.onnx` in una cartella locale, ad esempio `models/yolo_digits/yolo.onnx`;
|
||||
- aggiungere una modalita' OCR nel server:
|
||||
|
||||
```ini
|
||||
wms_ocr_mode = yolo_digits
|
||||
wms_yolo_digits_model = models/yolo_digits/yolo.onnx
|
||||
wms_yolo_digits_conf = 0.35
|
||||
wms_yolo_digits_expected_len = 6
|
||||
```
|
||||
|
||||
- implementare nel server una classe tipo `YoloDigitsOcr`;
|
||||
- usare `onnxruntime` oppure OpenCV DNN per l'inferenza;
|
||||
- restituire sempre un risultato conservativo:
|
||||
- codice numerico solo se la sequenza supera i controlli minimi;
|
||||
- `udc non determinato` in caso di ambiguita', crop tagliato o confidenza insufficiente.
|
||||
|
||||
## Decisione pratica
|
||||
|
||||
La strada e' promettente e probabilmente piu' coerente del generico OCR classico. La prova corretta da fare e':
|
||||
|
||||
1. integrare il modello come modalita' sperimentale separata;
|
||||
2. non sostituire ancora EasyOCR/Tesseract;
|
||||
3. eseguire test sui crop etichetta salvati dal nostro server;
|
||||
4. confrontare errori e tempi rispetto a EasyOCR e Tesseract;
|
||||
5. decidere se basta il modello esistente oppure serve fine-tuning su nostre etichette.
|
||||
|
||||
25
aggiornamento-2026-05-16-19-52.md
Normal file
@@ -0,0 +1,25 @@
|
||||
# Aggiornamento 2026-05-16 19:52
|
||||
|
||||
## Nuovo laboratorio YOLO OCR
|
||||
|
||||
E' stata creata la cartella separata:
|
||||
|
||||
```text
|
||||
C:\devel\yolo-ocr
|
||||
```
|
||||
|
||||
Scopo della cartella:
|
||||
|
||||
- lavorare in modo pulito sull'ipotesi YOLO digits OCR;
|
||||
- evitare di sporcare subito `flywms_navigation.py` e `flywms_wms_server.py`;
|
||||
- provare il modello `thawro/yolov8-digits-detection` sui crop reali delle etichette;
|
||||
- misurare accuratezza e tempi di inferenza;
|
||||
- preparare eventualmente una pipeline di addestramento/fine-tuning con immagini nostre;
|
||||
- trasferire in FlyWMS solo una soluzione gia' validata.
|
||||
|
||||
Decisione tecnica:
|
||||
|
||||
- `C:\devel\flywms` resta il progetto principale;
|
||||
- `C:\devel\yolo-ocr` diventa il laboratorio OCR isolato;
|
||||
- le prossime operazioni relative a YOLO digits OCR dovranno usare `C:\devel\yolo-ocr` come directory di lavoro.
|
||||
|
||||
94
aggiornamento-2026-05-16-20-12.md
Normal file
@@ -0,0 +1,94 @@
|
||||
# Aggiornamento 2026-05-16 20:12
|
||||
|
||||
## Primo test YOLO digits su crop etichetta
|
||||
|
||||
E' stato scaricato il progetto:
|
||||
|
||||
```text
|
||||
C:\devel\yolo-ocr\external\yolov8-digits-detection
|
||||
```
|
||||
|
||||
Sono state trovate 28 immagini di test in:
|
||||
|
||||
```text
|
||||
C:\devel\yolo-ocr\immagini_test
|
||||
```
|
||||
|
||||
Nota: la cartella indicata verbalmente come `C:\yolo-ocr\immagini_test` non esisteva; le immagini erano nella cartella corretta `C:\devel\yolo-ocr\immagini_test`.
|
||||
|
||||
## Runner creato
|
||||
|
||||
E' stato creato:
|
||||
|
||||
```text
|
||||
C:\devel\yolo-ocr\tools\batch_yolo_digits.py
|
||||
```
|
||||
|
||||
Il runner:
|
||||
|
||||
- carica i modelli ONNX del progetto;
|
||||
- non installa PyTorch;
|
||||
- evita `pytorch_lightning`, usato dal progetto solo per logging;
|
||||
- esegue inferenza CPU;
|
||||
- ordina le cifre rilevate da sinistra a destra;
|
||||
- salva un CSV con codice, numero cifre, confidenza media e tempo;
|
||||
- salva immagini annotate con bbox delle cifre;
|
||||
- salva una tavola di controllo visivo.
|
||||
|
||||
## Risultato con soglia 0.25
|
||||
|
||||
Output:
|
||||
|
||||
```text
|
||||
immagini=28
|
||||
codici_numerici=24
|
||||
load_sec=2.679
|
||||
infer_ms_medio=52.7
|
||||
conf=0.25
|
||||
iou=0.7
|
||||
```
|
||||
|
||||
Il modello e' veloce: circa 53 ms per crop su CPU.
|
||||
|
||||
Qualita':
|
||||
|
||||
- riconosce davvero alcune cifre stampate;
|
||||
- quindi la pista YOLO digits e' concreta;
|
||||
- tuttavia spesso riconosce solo una parte del codice;
|
||||
- alcuni crop restituiscono 1-3 cifre invece del codice completo;
|
||||
- il modello out-of-the-box non e' ancora sufficiente per lettura affidabile UDC.
|
||||
|
||||
## Risultato con soglia 0.10
|
||||
|
||||
Output:
|
||||
|
||||
```text
|
||||
immagini=28
|
||||
codici_numerici=27
|
||||
load_sec=1.881
|
||||
infer_ms_medio=61.5
|
||||
conf=0.1
|
||||
iou=0.7
|
||||
```
|
||||
|
||||
La soglia piu' bassa fa trovare piu' cifre, ma introduce duplicati e classi sbagliate. Quindi il problema non si risolve solo abbassando la soglia.
|
||||
|
||||
## Conclusione
|
||||
|
||||
Il modello esistente e' utile come base sperimentale, ma non e' pronto da integrare nel WMS come OCR affidabile.
|
||||
|
||||
La cosa positiva e' che:
|
||||
|
||||
- il modello e' leggero;
|
||||
- gira senza PyTorch;
|
||||
- riconosce cifre stampate almeno parzialmente;
|
||||
- la velocita' e' adeguata;
|
||||
- puo' diventare molto interessante con fine-tuning su immagini reali delle nostre etichette.
|
||||
|
||||
Prossimo passo consigliato:
|
||||
|
||||
1. migliorare preprocessing e crop locale, cercando di isolare meglio la riga numerica;
|
||||
2. creare una piccola tabella ground truth per le 28 immagini;
|
||||
3. misurare accuracy reale cifra per cifra e codice intero;
|
||||
4. valutare fine-tuning del modello con immagini nostre annotate.
|
||||
|
||||
29
aggiornamento-2026-05-17-09-30.md
Normal file
@@ -0,0 +1,29 @@
|
||||
# Aggiornamento 2026-05-17 09:30
|
||||
|
||||
## Decisione: passare al fine-tuning YOLO digits
|
||||
|
||||
Dopo il primo test del modello `thawro/yolov8-digits-detection` sui crop reali, la direzione scelta e' passare direttamente al fine-tuning.
|
||||
|
||||
Motivazione:
|
||||
|
||||
- il modello base riconosce alcune cifre stampate;
|
||||
- la velocita' CPU e' adeguata;
|
||||
- l'accuratezza out-of-the-box non e' sufficiente;
|
||||
- i nostri codici UDC hanno dominio visivo specifico: font, stampa, prospettiva, luce, sfocatura, tagli parziali;
|
||||
- un OCR generico resta fragile, mentre un detector addestrato sulle nostre etichette puo' migliorare molto.
|
||||
|
||||
Percorso previsto:
|
||||
|
||||
1. raccogliere crop reali delle etichette;
|
||||
2. annotare ogni cifra con bbox e classe `0..9`;
|
||||
3. creare dataset YOLO con split `train/val/test`;
|
||||
4. fare training/fine-tuning YOLOv8 detection;
|
||||
5. esportare il modello in ONNX;
|
||||
6. testare il modello nel laboratorio `C:\devel\yolo-ocr`;
|
||||
7. integrare nel server WMS solo quando il risultato e' affidabile.
|
||||
|
||||
Decisione architetturale:
|
||||
|
||||
- il fine-tuning resta nel laboratorio `C:\devel\yolo-ocr`;
|
||||
- FlyWMS non viene toccato finche' il modello OCR non e' validato.
|
||||
|
||||
53
aggiornamento-2026-05-17-09-39.md
Normal file
@@ -0,0 +1,53 @@
|
||||
# Aggiornamento 2026-05-17 09:39
|
||||
|
||||
## Preparazione dataset per fine-tuning YOLO OCR
|
||||
|
||||
E' stata creata la struttura dataset nel laboratorio:
|
||||
|
||||
```text
|
||||
C:\devel\yolo-ocr\dataset
|
||||
```
|
||||
|
||||
Cartelle principali:
|
||||
|
||||
```text
|
||||
dataset\images\to_annotate
|
||||
dataset\images\train
|
||||
dataset\images\val
|
||||
dataset\images\test
|
||||
dataset\labels\to_annotate
|
||||
dataset\labels\train
|
||||
dataset\labels\val
|
||||
dataset\labels\test
|
||||
dataset\annotations_raw
|
||||
dataset\manifests
|
||||
```
|
||||
|
||||
Sono state copiate 28 immagini in:
|
||||
|
||||
```text
|
||||
C:\devel\yolo-ocr\dataset\images\to_annotate
|
||||
```
|
||||
|
||||
E' stato creato:
|
||||
|
||||
```text
|
||||
C:\devel\yolo-ocr\dataset\data.yaml
|
||||
C:\devel\yolo-ocr\dataset\README_ANNOTAZIONE.md
|
||||
```
|
||||
|
||||
Regola di annotazione:
|
||||
|
||||
- annotare ogni singola cifra del codice UDC;
|
||||
- usare classi `0..9`;
|
||||
- non annotare l'intera etichetta;
|
||||
- non annotare testi, righe o loghi;
|
||||
- non annotare cifre troppo ambigue.
|
||||
|
||||
Valutazione quantita' dati:
|
||||
|
||||
- le 28 immagini attuali sono poche;
|
||||
- possono bastare per una demo controllata o per un primo proof-of-concept;
|
||||
- non bastano per una soluzione robusta da campo;
|
||||
- per robustezza reale servira' arrivare a centinaia di crop, includendo casi difficili.
|
||||
|
||||
18
aggiornamento-2026-05-17-10-08.md
Normal file
@@ -0,0 +1,18 @@
|
||||
# Aggiornamento 2026-05-17 10:08
|
||||
|
||||
## Configurazione Label Studio per cifre UDC
|
||||
|
||||
E' stato creato il file XML di configurazione Label Studio:
|
||||
|
||||
```text
|
||||
C:\devel\yolo-ocr\dataset\label_studio_digits_config.xml
|
||||
```
|
||||
|
||||
Contiene dieci classi rettangolari:
|
||||
|
||||
```text
|
||||
0 1 2 3 4 5 6 7 8 9
|
||||
```
|
||||
|
||||
Questa configurazione serve ad annotare ogni singola cifra del codice UDC con un bbox rettangolare standard, compatibile con export YOLO detection.
|
||||
|
||||
20
aggiornamento-2026-05-17-10-37.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# Aggiornamento 2026-05-17 10:37
|
||||
|
||||
## Avvio fase fine-tuning YOLO OCR
|
||||
|
||||
L'utente ha completato una prima sessione di tagging in Label Studio e ha chiesto di usare le immagini annotate per lanciare il fine-tuning.
|
||||
|
||||
Verifiche iniziali:
|
||||
|
||||
- le immagini sono presenti in `C:\devel\yolo-ocr\dataset\images\to_annotate`;
|
||||
- non risultano ancora file YOLO `.txt` in `dataset\labels\to_annotate`;
|
||||
- non risultano export Label Studio nuovi nella cartella export standard;
|
||||
- probabilmente le annotazioni sono ancora nel database SQLite interno di Label Studio.
|
||||
|
||||
Prossimo passo:
|
||||
|
||||
- leggere le annotazioni dal database Label Studio;
|
||||
- convertirle in formato YOLO;
|
||||
- creare split `train/val/test`;
|
||||
- avviare un primo training dimostrativo.
|
||||
|
||||
82
aggiornamento-2026-05-17-11-21.md
Normal file
@@ -0,0 +1,82 @@
|
||||
# Aggiornamento 2026-05-17 11:21
|
||||
|
||||
## Fine-tuning YOLO OCR completato
|
||||
|
||||
Sono state convertite le annotazioni Label Studio del progetto:
|
||||
|
||||
```text
|
||||
project_id=4
|
||||
nome=addestramento ocr
|
||||
```
|
||||
|
||||
Dataset YOLO creato:
|
||||
|
||||
```text
|
||||
C:\devel\yolo-ocr\dataset
|
||||
```
|
||||
|
||||
Split:
|
||||
|
||||
```text
|
||||
images=26
|
||||
boxes=156
|
||||
train=19
|
||||
val=5
|
||||
test=2
|
||||
```
|
||||
|
||||
Training lanciato inizialmente su GPU, ma fallito per incompatibilita':
|
||||
|
||||
```text
|
||||
GPU: NVIDIA GeForce GTX 1050
|
||||
problema: PyTorch installato non supporta compute capability sm_61
|
||||
errore: CUDA error: no kernel image is available for execution on the device
|
||||
```
|
||||
|
||||
Training rilanciato e completato su CPU:
|
||||
|
||||
```powershell
|
||||
yolo detect train data=C:\devel\yolo-ocr\dataset\data.yaml model=yolov8n.pt epochs=60 imgsz=640 batch=4 workers=0 device=cpu project=C:\devel\yolo-ocr\training_runs name=digits_yolov8n_demo_cpu patience=15 seed=42
|
||||
```
|
||||
|
||||
Risultati finali su validation:
|
||||
|
||||
```text
|
||||
precision: 0.603
|
||||
recall: 0.556
|
||||
mAP50: 0.753
|
||||
mAP50-95: 0.582
|
||||
```
|
||||
|
||||
Risultati su test:
|
||||
|
||||
```text
|
||||
images: 2
|
||||
boxes: 12
|
||||
precision: 0.535
|
||||
recall: 0.771
|
||||
mAP50: 0.752
|
||||
mAP50-95: 0.488
|
||||
```
|
||||
|
||||
Artefatti stabili copiati in:
|
||||
|
||||
```text
|
||||
C:\devel\yolo-ocr\models\udc_digits_yolov8n_demo.pt
|
||||
C:\devel\yolo-ocr\models\udc_digits_yolov8n_demo.onnx
|
||||
```
|
||||
|
||||
Riepilogo tecnico:
|
||||
|
||||
```text
|
||||
C:\devel\yolo-ocr\TRAINING_SUMMARY.md
|
||||
```
|
||||
|
||||
Interpretazione:
|
||||
|
||||
- il fine-tuning funziona;
|
||||
- il modello addestrato e' molto piu' promettente del modello generico provato ieri;
|
||||
- l'export ONNX funziona;
|
||||
- il dataset e' pero' ancora troppo piccolo;
|
||||
- la metrica mAP e' incoraggiante, ma ora serve misurare la lettura del codice intero, perche' per il WMS una sola cifra sbagliata rende errato tutto il codice UDC.
|
||||
|
||||
46
aggiornamento-2026-05-17-14-48.md
Normal file
@@ -0,0 +1,46 @@
|
||||
# Aggiornamento 2026-05-17 14:48
|
||||
|
||||
## Installazione RTX 3050 e verifica stack GPU
|
||||
|
||||
Nuova GPU rilevata:
|
||||
|
||||
```text
|
||||
NVIDIA GeForce RTX 3050
|
||||
VRAM: 6144 MiB
|
||||
Driver: 596.36
|
||||
CUDA driver runtime: 13.2
|
||||
```
|
||||
|
||||
PyTorch vede correttamente la GPU:
|
||||
|
||||
```text
|
||||
torch: 2.11.0+cu128
|
||||
cuda_available: True
|
||||
device_count: 1
|
||||
device_name: NVIDIA GeForce RTX 3050
|
||||
capability: (8, 6)
|
||||
```
|
||||
|
||||
Questo risolve il problema avuto con la GTX 1050, che non era compatibile con il build PyTorch CUDA installato.
|
||||
|
||||
Modifica effettuata:
|
||||
|
||||
```text
|
||||
flywms_navigation.ini
|
||||
ultralytics_device = 0
|
||||
```
|
||||
|
||||
Situazione stack:
|
||||
|
||||
- PyTorch/Ultralytics: GPU utilizzabile;
|
||||
- OpenCV: attualmente `GUI: NONE`, quindi va ripristinito `opencv-python` non headless;
|
||||
- ONNX Runtime: attualmente solo CPU provider, ma per il modello OCR piccolo puo' bastare CPU;
|
||||
- Label Studio ha installato `opencv-python-headless`, causando la perdita delle finestre OpenCV.
|
||||
|
||||
Prossime azioni consigliate:
|
||||
|
||||
1. ripristinare OpenCV GUI;
|
||||
2. fare benchmark FlyWMS con `ultralytics_device = 0`;
|
||||
3. rilanciare training/fine-tuning OCR su GPU se servono nuovi modelli;
|
||||
4. valutare ONNX Runtime GPU solo se l'OCR ONNX diventa un collo di bottiglia.
|
||||
|
||||
52
aggiornamento-2026-05-17-14-51.md
Normal file
@@ -0,0 +1,52 @@
|
||||
# Aggiornamento 2026-05-17 14:51
|
||||
|
||||
## Diagnosi rallentamento avvio programmi
|
||||
|
||||
Sintomo:
|
||||
|
||||
- i programmi partono molto lentamente;
|
||||
- non compaiono errori evidenti;
|
||||
- anche il comando minimale `python -c "print('ok')"` impiega circa 4 secondi;
|
||||
- import pesanti come `torch` restano molto lenti.
|
||||
|
||||
Indizi trovati:
|
||||
|
||||
```text
|
||||
git-lfs attivo in piu' processi
|
||||
MsMpEng / Microsoft Defender attivo
|
||||
pCloud attivo
|
||||
SearchIndexer attivo
|
||||
testhd2.mp4 modificato come file LFS
|
||||
```
|
||||
|
||||
Processi `git-lfs` osservati:
|
||||
|
||||
```text
|
||||
git-lfs 10916
|
||||
git-lfs 13380
|
||||
git-lfs 15520
|
||||
git-lfs 17104
|
||||
```
|
||||
|
||||
Ipotesi piu' probabile:
|
||||
|
||||
- Git LFS sta lavorando/scansionando file grandi, in particolare video;
|
||||
- Defender e/o pCloud stanno scansionando o sincronizzando gli stessi file;
|
||||
- questo crea pressione su disco/I/O;
|
||||
- l'avvio di Python, PyTorch, Label Studio e altri programmi diventa molto lento anche senza errori espliciti.
|
||||
|
||||
Altri punti:
|
||||
|
||||
- alcuni comandi diagnostici Windows richiedono privilegi amministrativi e sono stati negati;
|
||||
- `opencv-python-headless` resta installato e OpenCV risulta `GUI: NONE`;
|
||||
- questo problema OpenCV e' separato dal rallentamento generale, ma va sistemato.
|
||||
|
||||
Azioni consigliate:
|
||||
|
||||
1. fermare i processi `git-lfs` appesi;
|
||||
2. evitare che pCloud sincronizzi `C:\devel`;
|
||||
3. aggiungere esclusioni Defender per `C:\devel` e per le cartelle Python/progetto;
|
||||
4. gestire i video grandi fuori dal repository o confermare intenzionalmente le modifiche LFS;
|
||||
5. ripristinare OpenCV GUI;
|
||||
6. creare ambienti Python separati invece di continuare a installare tutto nel Python globale.
|
||||
|
||||
75
aggiornamento-2026-05-17-20-36.md
Normal file
@@ -0,0 +1,75 @@
|
||||
# Aggiornamento 2026-05-17 20:36
|
||||
|
||||
## Test accuratezza codice intero YOLO OCR
|
||||
|
||||
E' stato creato il test:
|
||||
|
||||
```text
|
||||
C:\devel\yolo-ocr\tools\evaluate_code_accuracy.py
|
||||
```
|
||||
|
||||
Scopo:
|
||||
|
||||
- usare il modello fine-tuned;
|
||||
- rilevare le cifre su ogni crop;
|
||||
- ordinare i bbox da sinistra a destra;
|
||||
- ricostruire il codice UDC;
|
||||
- confrontarlo con la ground truth derivata dalle label YOLO;
|
||||
- produrre CSV e immagini annotate.
|
||||
|
||||
Primo test:
|
||||
|
||||
```powershell
|
||||
python tools\evaluate_code_accuracy.py --split test --device 0 --conf 0.25 --iou 0.50 --output outputs\code_eval_test
|
||||
python tools\evaluate_code_accuracy.py --split all --device 0 --conf 0.25 --iou 0.50 --output outputs\code_eval_all
|
||||
```
|
||||
|
||||
Risultati:
|
||||
|
||||
```text
|
||||
split=test
|
||||
images=2
|
||||
code_ok=0
|
||||
code_accuracy=0.0000
|
||||
char_accuracy=0.5385
|
||||
```
|
||||
|
||||
```text
|
||||
split=all
|
||||
images=26
|
||||
code_ok=0
|
||||
code_accuracy=0.0000
|
||||
char_accuracy=0.5389
|
||||
```
|
||||
|
||||
Esempi:
|
||||
|
||||
```text
|
||||
expected=187184 predicted=1871182
|
||||
expected=182368 predicted=18288
|
||||
```
|
||||
|
||||
Sono state provate anche soglie diverse:
|
||||
|
||||
```text
|
||||
conf=0.40 iou=0.40 -> code_accuracy=0.0000 char_accuracy=0.5316
|
||||
conf=0.50 iou=0.40 -> code_accuracy=0.0385 char_accuracy=0.4872
|
||||
conf=0.60 iou=0.40 -> code_accuracy=0.0000 char_accuracy=0.4487
|
||||
```
|
||||
|
||||
Conclusione:
|
||||
|
||||
- il fine-tuning ha migliorato molto la capacita' di rilevare bbox cifra rispetto al modello generico;
|
||||
- pero' la lettura del codice intero non e' ancora affidabile;
|
||||
- gli errori principali sono duplicazioni, cifre mancanti e confusione nelle ultime cifre;
|
||||
- il prefisso `182` / `187` viene spesso agganciato, ma non basta per il WMS;
|
||||
- non conviene integrare ancora il modello in FlyWMS come OCR operativo.
|
||||
|
||||
Prossimi passi consigliati:
|
||||
|
||||
1. aumentare dataset annotato;
|
||||
2. introdurre post-processing specifico per codice a 6 cifre;
|
||||
3. valutare crop piu' stretto della sola riga numerica;
|
||||
4. usare metriche di codice intero come criterio principale;
|
||||
5. integrare in FlyWMS solo come modalita' sperimentale quando il codice intero migliora.
|
||||
|
||||
166
aggiornamento-2026-05-17-20-57.md
Normal file
@@ -0,0 +1,166 @@
|
||||
# Aggiornamento 2026-05-17 20:57
|
||||
|
||||
## Obiettivo
|
||||
|
||||
Provare la strada del dataset aumentato per il riconoscimento OCR numerico via YOLO, senza integrare ancora nulla in `flywms`.
|
||||
|
||||
## Dataset aumentato
|
||||
|
||||
Creato lo script:
|
||||
|
||||
```text
|
||||
C:\devel\yolo-ocr\tools\augment_yolo_dataset.py
|
||||
```
|
||||
|
||||
Generato il dataset:
|
||||
|
||||
```text
|
||||
C:\devel\yolo-ocr\dataset_augmented
|
||||
```
|
||||
|
||||
Composizione:
|
||||
|
||||
```text
|
||||
train: 247 immagini, 1482 bbox
|
||||
val: 5 immagini, 30 bbox
|
||||
test: 2 immagini, 12 bbox
|
||||
```
|
||||
|
||||
Nota importante: l'aumento dati e' applicato solo al train. Validation e test restano immagini originali, quindi sono utili per misurare se il modello generalizza.
|
||||
|
||||
Augmentation applicate:
|
||||
|
||||
- piccole rotazioni;
|
||||
- piccole traslazioni;
|
||||
- scala leggera;
|
||||
- contrasto/luminosita';
|
||||
- CLAHE;
|
||||
- sharpening;
|
||||
- blur leggero;
|
||||
- rumore;
|
||||
- compressione JPEG simulata.
|
||||
|
||||
## Training GPU
|
||||
|
||||
Addestramento eseguito sulla RTX 3050:
|
||||
|
||||
```powershell
|
||||
yolo detect train data=C:\devel\yolo-ocr\dataset_augmented\data.yaml model=yolov8n.pt epochs=120 imgsz=640 batch=16 workers=0 device=0 project=C:\devel\yolo-ocr\training_runs name=digits_yolov8n_aug_gpu patience=30 seed=42
|
||||
```
|
||||
|
||||
Il training e' terminato con early stopping:
|
||||
|
||||
```text
|
||||
Best epoch: 11
|
||||
Epoch completate: 41
|
||||
Durata: circa 0.098 ore
|
||||
```
|
||||
|
||||
Metriche YOLO finali su validation:
|
||||
|
||||
```text
|
||||
precision: 0.826
|
||||
recall: 0.873
|
||||
mAP50: 0.990
|
||||
mAP50-95: 0.745
|
||||
```
|
||||
|
||||
Velocita' indicativa:
|
||||
|
||||
```text
|
||||
preprocess: 0.6 ms
|
||||
inference: 7.7 ms
|
||||
postprocess: 4.1 ms
|
||||
```
|
||||
|
||||
## Artefatti
|
||||
|
||||
Peso PyTorch:
|
||||
|
||||
```text
|
||||
C:\devel\yolo-ocr\models\udc_digits_yolov8n_aug.pt
|
||||
```
|
||||
|
||||
Export ONNX:
|
||||
|
||||
```text
|
||||
C:\devel\yolo-ocr\models\udc_digits_yolov8n_aug.onnx
|
||||
```
|
||||
|
||||
Run originale:
|
||||
|
||||
```text
|
||||
C:\devel\yolo-ocr\training_runs\digits_yolov8n_aug_gpu
|
||||
```
|
||||
|
||||
## Valutazione codice intero
|
||||
|
||||
Con soglia standard:
|
||||
|
||||
```powershell
|
||||
python C:\devel\yolo-ocr\tools\evaluate_code_accuracy.py --model C:\devel\yolo-ocr\training_runs\digits_yolov8n_aug_gpu\weights\best.pt --dataset C:\devel\yolo-ocr\dataset_augmented --split test --device 0 --conf 0.25 --iou 0.50 --output C:\devel\yolo-ocr\outputs\code_eval_aug_test
|
||||
```
|
||||
|
||||
Risultato su test:
|
||||
|
||||
```text
|
||||
images=2
|
||||
code_ok=0
|
||||
code_accuracy=0.0000
|
||||
char_accuracy=0.3333
|
||||
```
|
||||
|
||||
Il problema era una cifra mancante nei due codici:
|
||||
|
||||
```text
|
||||
187184 -> 17184
|
||||
182368 -> 18268
|
||||
```
|
||||
|
||||
Abbassando la soglia a `conf=0.15`, sui 2 test il codice completo diventa corretto:
|
||||
|
||||
```text
|
||||
conf=0.15, iou=0.35..0.65
|
||||
code_accuracy=1.0000
|
||||
char_accuracy=1.0000
|
||||
```
|
||||
|
||||
Pero' sulla validation originale, sempre con `conf=0.15`, il risultato resta insufficiente:
|
||||
|
||||
```text
|
||||
images=5
|
||||
code_ok=1
|
||||
code_accuracy=0.2000
|
||||
char_accuracy=0.7812
|
||||
```
|
||||
|
||||
Esempi validation:
|
||||
|
||||
```text
|
||||
187184 -> 187184 OK
|
||||
182430 -> 18243601 NO
|
||||
182519 -> 182610 NO
|
||||
182511 -> 182611 NO
|
||||
182242 -> 18224 NO
|
||||
```
|
||||
|
||||
## Conclusione
|
||||
|
||||
La strada del dataset aumentato e' utile: le metriche YOLO sugli oggetti sono migliorate molto e la GPU funziona bene.
|
||||
|
||||
Pero' il problema reale non e' ancora risolto, perche' noi non dobbiamo solo rilevare cifre: dobbiamo ricostruire un codice numerico affidabile. Il modello ora e' sensibile alla soglia di confidenza e produce ancora cifre duplicate, mancanti o confuse.
|
||||
|
||||
Non conviene integrare questo OCR in `flywms` in questa forma.
|
||||
|
||||
## Prossimo passo tecnico
|
||||
|
||||
Prima di altro training, serve migliorare il post-processing del codice:
|
||||
|
||||
- soglia bassa controllata;
|
||||
- ordinamento sinistra-destra;
|
||||
- clustering/merge dei bbox vicini;
|
||||
- vincolo codice a 6 cifre;
|
||||
- gestione duplicati;
|
||||
- report per capire quali cifre sono davvero ambigue.
|
||||
|
||||
Solo dopo questa fase ha senso decidere se aumentare ancora il dataset o cambiare architettura.
|
||||
196
aggiornamento-2026-05-18-14-18.md
Normal file
@@ -0,0 +1,196 @@
|
||||
# Aggiornamento 2026-05-18 14:18
|
||||
|
||||
## Obiettivo
|
||||
|
||||
Avviare la pista PaddleOCR come alternativa OCR tarabile sui crop etichetta, lasciando per ora da parte YOLO caratteri e senza integrare nulla in `flywms`.
|
||||
|
||||
## Decisione tecnica
|
||||
|
||||
Per PaddleOCR non usiamo le annotazioni bbox cifra-per-cifra.
|
||||
|
||||
Usiamo invece l'etichetta intera:
|
||||
|
||||
```text
|
||||
crop_etichetta.jpg<TAB>codice_completo
|
||||
```
|
||||
|
||||
Questo e' piu' coerente con l'obiettivo demo: dato un crop dell'etichetta, ottenere direttamente il codice UDC.
|
||||
|
||||
## Dataset creato
|
||||
|
||||
Creato script:
|
||||
|
||||
```text
|
||||
C:\devel\yolo-ocr\tools\prepare_paddleocr_dataset.py
|
||||
```
|
||||
|
||||
Generata cartella:
|
||||
|
||||
```text
|
||||
C:\devel\yolo-ocr\paddleocr-recognizer
|
||||
```
|
||||
|
||||
Dataset:
|
||||
|
||||
```text
|
||||
C:\devel\yolo-ocr\paddleocr-recognizer\dataset
|
||||
```
|
||||
|
||||
Conteggi:
|
||||
|
||||
```text
|
||||
train: 475 immagini
|
||||
val: 5 immagini
|
||||
test: 2 immagini
|
||||
```
|
||||
|
||||
Il train contiene varianti aumentate dell'intera etichetta. Validation e test restano crop originali.
|
||||
|
||||
File prodotti:
|
||||
|
||||
```text
|
||||
dataset\train_list.txt
|
||||
dataset\val_list.txt
|
||||
dataset\test_list.txt
|
||||
digit_dict.txt
|
||||
preprocessed_preview\
|
||||
README.md
|
||||
README_OPERATIVO.md
|
||||
```
|
||||
|
||||
## Preprocessing/augmentation
|
||||
|
||||
Lo script genera varianti controllate:
|
||||
|
||||
- upscale a altezza standard;
|
||||
- contrasto/luminosita';
|
||||
- CLAHE;
|
||||
- sharpening;
|
||||
- blur leggero;
|
||||
- rumore;
|
||||
- compressione JPEG;
|
||||
- rotazione leggera.
|
||||
|
||||
Le preview dei preprocessing per validation/test sono in:
|
||||
|
||||
```text
|
||||
C:\devel\yolo-ocr\paddleocr-recognizer\preprocessed_preview
|
||||
```
|
||||
|
||||
## Baseline multi-pass
|
||||
|
||||
Creato script:
|
||||
|
||||
```text
|
||||
C:\devel\yolo-ocr\tools\paddleocr_multipass_eval.py
|
||||
```
|
||||
|
||||
Scopo:
|
||||
|
||||
- provare piu' preprocessing sullo stesso crop;
|
||||
- passare ogni variante a PaddleOCR;
|
||||
- tenere solo le cifre;
|
||||
- preferire codici della lunghezza attesa;
|
||||
- salvare CSV e immagini varianti.
|
||||
|
||||
## Blocco tecnico
|
||||
|
||||
PaddleOCR e' installato:
|
||||
|
||||
```text
|
||||
paddleocr 3.5.0
|
||||
paddlex 3.5.2
|
||||
paddlepaddle 3.3.1
|
||||
paddlepaddle-gpu 3.3.1
|
||||
```
|
||||
|
||||
Ma l'esecuzione fallisce prima dell'OCR:
|
||||
|
||||
```text
|
||||
OSError: [WinError 127] Impossibile trovare la procedura specificata.
|
||||
Error loading C:\Python313\Lib\site-packages\paddle\..\nvidia\cudnn\bin\cudnn_cnn64_9.dll or one of its dependencies.
|
||||
```
|
||||
|
||||
Ho provato ad aggiungere esplicitamente le cartelle `nvidia\*\bin` al loader DLL Windows nello script, ma non basta.
|
||||
|
||||
Il problema sembra nello stack Paddle GPU/CUDA/cuDNN globale, non nel dataset.
|
||||
|
||||
## Ambiente isolato
|
||||
|
||||
Per non modificare lo stack globale, creato un virtualenv dedicato:
|
||||
|
||||
```text
|
||||
C:\devel\yolo-ocr\.venv-paddle-cpu
|
||||
```
|
||||
|
||||
Installati nel virtualenv:
|
||||
|
||||
```text
|
||||
paddlepaddle==3.3.1
|
||||
paddleocr==3.5.0
|
||||
opencv-python-headless
|
||||
```
|
||||
|
||||
In questo ambiente PaddleOCR parte correttamente e usa i modelli gia' presenti in cache:
|
||||
|
||||
```text
|
||||
PP-OCRv5_server_det
|
||||
en_PP-OCRv5_mobile_rec
|
||||
```
|
||||
|
||||
## Correzione parser
|
||||
|
||||
L'API PaddleOCR 3.5 restituisce i risultati in chiavi:
|
||||
|
||||
```text
|
||||
rec_texts
|
||||
rec_scores
|
||||
```
|
||||
|
||||
Lo script `paddleocr_multipass_eval.py` e' stato corretto per leggere questo formato.
|
||||
|
||||
## Baseline OCR PaddleOCR
|
||||
|
||||
Validation:
|
||||
|
||||
```text
|
||||
images=5
|
||||
ok=5
|
||||
accuracy=1.0000
|
||||
```
|
||||
|
||||
Test:
|
||||
|
||||
```text
|
||||
images=2
|
||||
ok=2
|
||||
accuracy=1.0000
|
||||
```
|
||||
|
||||
File risultati:
|
||||
|
||||
```text
|
||||
C:\devel\yolo-ocr\paddleocr-recognizer\outputs\multipass_val_venv_fixed\multipass_results.csv
|
||||
C:\devel\yolo-ocr\paddleocr-recognizer\outputs\multipass_test_venv_fixed\multipass_results.csv
|
||||
```
|
||||
|
||||
Esempi:
|
||||
|
||||
```text
|
||||
182430 -> 182430
|
||||
182242 -> 182242
|
||||
182519 -> 182519
|
||||
182511 -> 182511
|
||||
187184 -> 187184
|
||||
182368 -> 182368
|
||||
```
|
||||
|
||||
## Conclusione
|
||||
|
||||
La pista PaddleOCR e' molto piu' promettente del previsto per il demo.
|
||||
|
||||
Il dataset e gli script sono pronti, e la baseline standard con preprocessing multi-pass legge correttamente tutti i crop disponibili in validation/test.
|
||||
|
||||
Il campione e' pero' molto piccolo, quindi non e' ancora una prova di robustezza.
|
||||
|
||||
Per il prossimo passo non farei subito fine-tuning: integrerei prima nel server WMS una modalita' OCR sperimentale basata su PaddleOCR multi-pass, con fallback `UDC_NON_DETERMINATO` quando non c'e' un candidato numerico credibile.
|
||||
115
aggiornamento-2026-05-18-14-39.md
Normal file
@@ -0,0 +1,115 @@
|
||||
# Aggiornamento 2026-05-18 14:39
|
||||
|
||||
## Obiettivo
|
||||
|
||||
Migliorare la pista PaddleOCR prima di pensare all'integrazione in `flywms`.
|
||||
|
||||
## Modifiche
|
||||
|
||||
Aggiornato:
|
||||
|
||||
```text
|
||||
C:\devel\yolo-ocr\tools\paddleocr_multipass_eval.py
|
||||
```
|
||||
|
||||
Migliorie introdotte:
|
||||
|
||||
- resize su piu' altezze (`64,96,128`);
|
||||
- variante con bordo bianco per evitare tagli ai caratteri;
|
||||
- CLAHE;
|
||||
- sharpening;
|
||||
- threshold adattivo;
|
||||
- Otsu;
|
||||
- Otsu + close morfologico;
|
||||
- denoise;
|
||||
- scelta finale a consenso.
|
||||
|
||||
La scelta finale ora non dipende solo dal massimo score PaddleOCR.
|
||||
|
||||
Il punteggio considera:
|
||||
|
||||
- codice letto da piu' varianti;
|
||||
- numero di varianti distinte che producono lo stesso codice;
|
||||
- bonus se il codice ha la lunghezza attesa;
|
||||
- penalita' per codici troppo corti o troppo lunghi.
|
||||
|
||||
## Risultati configurazione estesa
|
||||
|
||||
Validation:
|
||||
|
||||
```text
|
||||
images=5
|
||||
ok=5
|
||||
accuracy=1.0000
|
||||
```
|
||||
|
||||
Test:
|
||||
|
||||
```text
|
||||
images=2
|
||||
ok=2
|
||||
accuracy=1.0000
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```text
|
||||
C:\devel\yolo-ocr\paddleocr-recognizer\outputs\multipass_val_consensus
|
||||
C:\devel\yolo-ocr\paddleocr-recognizer\outputs\multipass_test_consensus
|
||||
```
|
||||
|
||||
La lettura corretta e' sostenuta da molti voti, quindi non sembra casuale:
|
||||
|
||||
```text
|
||||
182430 -> 19 voti
|
||||
182242 -> 12 voti
|
||||
182519 -> 20 voti
|
||||
182511 -> 18 voti
|
||||
187184 -> 18/19 voti
|
||||
182368 -> 14 voti
|
||||
```
|
||||
|
||||
## Risultati configurazione leggera
|
||||
|
||||
Testata anche la configurazione con sola altezza `96`, piu' adatta al server:
|
||||
|
||||
```powershell
|
||||
--target-heights 96
|
||||
```
|
||||
|
||||
Validation:
|
||||
|
||||
```text
|
||||
images=5
|
||||
ok=5
|
||||
accuracy=1.0000
|
||||
```
|
||||
|
||||
Test:
|
||||
|
||||
```text
|
||||
images=2
|
||||
ok=2
|
||||
accuracy=1.0000
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```text
|
||||
C:\devel\yolo-ocr\paddleocr-recognizer\outputs\multipass_val_h96
|
||||
C:\devel\yolo-ocr\paddleocr-recognizer\outputs\multipass_test_h96
|
||||
```
|
||||
|
||||
## Conclusione
|
||||
|
||||
Possiamo migliorare ancora raccogliendo nuove immagini reali, ma sul materiale attuale PaddleOCR standard con preprocessing multi-pass e consenso e' gia' solido per una demo.
|
||||
|
||||
La configurazione leggera `--target-heights 96` e' la candidata migliore per la prima integrazione sperimentale nel server WMS.
|
||||
|
||||
L'integrazione dovra' comunque mantenere un fallback:
|
||||
|
||||
```text
|
||||
UDC_NON_DETERMINATO
|
||||
```
|
||||
|
||||
quando non c'e' un candidato a 6 cifre con consenso sufficiente.
|
||||
166
aggiornamento-2026-05-18-14-58.md
Normal file
@@ -0,0 +1,166 @@
|
||||
# Aggiornamento 2026-05-18 14:58
|
||||
|
||||
## Obiettivo
|
||||
|
||||
Integrare PaddleOCR nel server WMS demo, senza modificare la GUI e senza integrare ancora una interfaccia DearPyGUI.
|
||||
|
||||
## Implementazione
|
||||
|
||||
Creato worker persistente:
|
||||
|
||||
```text
|
||||
C:\devel\flywms\flywms_paddleocr_worker.py
|
||||
```
|
||||
|
||||
Il worker gira con il virtualenv isolato:
|
||||
|
||||
```text
|
||||
C:\devel\yolo-ocr\.venv-paddle-cpu\Scripts\python.exe
|
||||
```
|
||||
|
||||
Il server WMS resta nel suo ambiente Python attuale e comunica col worker via stdin/stdout JSON. Questo evita il problema del Paddle GPU globale:
|
||||
|
||||
```text
|
||||
WinError 127 su cudnn_cnn64_9.dll
|
||||
```
|
||||
|
||||
## Server WMS
|
||||
|
||||
Aggiornato:
|
||||
|
||||
```text
|
||||
C:\devel\flywms\flywms_wms_server.py
|
||||
```
|
||||
|
||||
Nuovo backend OCR:
|
||||
|
||||
```text
|
||||
--ocr-mode paddleocr
|
||||
```
|
||||
|
||||
Backend disponibili:
|
||||
|
||||
```text
|
||||
paddleocr
|
||||
easyocr
|
||||
tesseract
|
||||
fake
|
||||
```
|
||||
|
||||
Il worker PaddleOCR resta caricato tra richieste successive, quindi non ricarica il modello a ogni snapshot.
|
||||
|
||||
## Parametri INI
|
||||
|
||||
Aggiornato:
|
||||
|
||||
```text
|
||||
C:\devel\flywms\flywms_navigation.ini
|
||||
```
|
||||
|
||||
Nuovi parametri:
|
||||
|
||||
```text
|
||||
wms_ocr_mode = paddleocr
|
||||
wms_paddle_python = C:\devel\yolo-ocr\.venv-paddle-cpu\Scripts\python.exe
|
||||
wms_paddle_worker_script = C:\devel\flywms\flywms_paddleocr_worker.py
|
||||
wms_paddle_target_heights = 96
|
||||
wms_paddle_variant_set = fast
|
||||
wms_paddle_expected_digits = 6
|
||||
wms_paddle_min_votes = 2
|
||||
wms_paddle_min_confidence = 0.70
|
||||
```
|
||||
|
||||
Aggiornati anche i timeout, perche' PaddleOCR CPU richiede piu' di 2 secondi:
|
||||
|
||||
```text
|
||||
remote_ack_timeout_sec = 10.0
|
||||
wms_timeout_sec = 12.0
|
||||
```
|
||||
|
||||
## Logica OCR
|
||||
|
||||
La configurazione `fast` prova 3 varianti:
|
||||
|
||||
```text
|
||||
originale
|
||||
CLAHE
|
||||
CLAHE + sharpening
|
||||
```
|
||||
|
||||
Il codice viene accettato solo se:
|
||||
|
||||
- e' numerico;
|
||||
- ha 6 cifre;
|
||||
- ha almeno 2 voti tra le varianti;
|
||||
- supera la confidenza minima.
|
||||
|
||||
In caso contrario il server restituisce:
|
||||
|
||||
```text
|
||||
udc non determinato
|
||||
```
|
||||
|
||||
## Test eseguiti
|
||||
|
||||
Compilazione:
|
||||
|
||||
```text
|
||||
python -m py_compile flywms_wms_server.py flywms_paddleocr_worker.py
|
||||
```
|
||||
|
||||
Test worker diretto:
|
||||
|
||||
```text
|
||||
input: snapshot_0019_track_123_label_payload_orig.jpg
|
||||
output: 182368
|
||||
votes: 3
|
||||
backend: paddleocr
|
||||
```
|
||||
|
||||
Test server locale senza GUI:
|
||||
|
||||
```powershell
|
||||
python C:\devel\flywms\flywms_wms_server.py --no-ui --port 8098 --received-dir C:\devel\flywms\wms_received_test --ocr-mode paddleocr --paddle-variant-set fast --fake-processing-sec 0
|
||||
```
|
||||
|
||||
Richiesta 1:
|
||||
|
||||
```text
|
||||
ocr_text: 182368
|
||||
ocr_backend: paddleocr
|
||||
ocr_fallback_used: false
|
||||
ocr_votes: 3
|
||||
processing_ms: circa 8500 ms
|
||||
```
|
||||
|
||||
Richiesta 2 con worker gia' caldo:
|
||||
|
||||
```text
|
||||
ocr_text: 187184
|
||||
ocr_backend: paddleocr
|
||||
ocr_fallback_used: false
|
||||
ocr_votes: 3
|
||||
processing_ms: circa 3200 ms
|
||||
```
|
||||
|
||||
## Nota prestazionale
|
||||
|
||||
Il primo snapshot paga il caricamento del worker PaddleOCR. Gli snapshot successivi sono piu' veloci ma restano nell'ordine di qualche secondo su CPU.
|
||||
|
||||
Per il demo va bene, ma il timeout del client deve restare piu' alto del vecchio valore da 2 secondi.
|
||||
|
||||
## Prossimo passo
|
||||
|
||||
Avviare il server:
|
||||
|
||||
```powershell
|
||||
python flywms_wms_server.py
|
||||
```
|
||||
|
||||
Poi avviare la navigazione:
|
||||
|
||||
```powershell
|
||||
python flywms_navigation.py --wms-enabled
|
||||
```
|
||||
|
||||
Verificare nella finestra comandi che compaia il codice OCR restituito dal WMS.
|
||||
50
aggiornamento-2026-05-18-15-28.md
Normal file
@@ -0,0 +1,50 @@
|
||||
# Aggiornamento 2026-05-18 15:28
|
||||
|
||||
## Problema
|
||||
|
||||
Avviando:
|
||||
|
||||
```powershell
|
||||
python flywms_wms_server.py
|
||||
```
|
||||
|
||||
il server partiva, ma il thread UI OpenCV falliva:
|
||||
|
||||
```text
|
||||
cv2.error: The function is not implemented
|
||||
```
|
||||
|
||||
Causa: nel Python globale e' installata una build OpenCV headless, quindi `cv2.namedWindow` non e' disponibile.
|
||||
|
||||
## Correzione
|
||||
|
||||
Aggiornato:
|
||||
|
||||
```text
|
||||
C:\devel\flywms\flywms_wms_server.py
|
||||
```
|
||||
|
||||
Ora `server_ui_loop()` intercetta l'errore `cv2.error` su `namedWindow`, logga il problema e disabilita solo la UI OpenCV del server.
|
||||
|
||||
FastAPI e PaddleOCR restano attivi.
|
||||
|
||||
## Verifica
|
||||
|
||||
Avvio di test:
|
||||
|
||||
```powershell
|
||||
python C:\devel\flywms\flywms_wms_server.py --port 8099
|
||||
```
|
||||
|
||||
Risultato:
|
||||
|
||||
```text
|
||||
UI OpenCV disabilitata: highgui non disponibile
|
||||
Uvicorn running on http://0.0.0.0:8099
|
||||
```
|
||||
|
||||
Il server non si chiude piu' per l'errore della finestra OpenCV.
|
||||
|
||||
## Nota
|
||||
|
||||
Quando sistemeremo OpenCV non-headless o passeremo a DearPyGUI per il server, la UI potra' essere riabilitata senza cambiare la parte WMS/OCR.
|
||||
107
aggiornamento-2026-05-18-15-42.md
Normal file
@@ -0,0 +1,107 @@
|
||||
# Aggiornamento 2026-05-18 15:42
|
||||
|
||||
## Obiettivo
|
||||
|
||||
Ripristinare OpenCV con supporto CUDA, come nel setup precedente basato sulle wheel `cudawarped/opencv-python-cuda-wheels`.
|
||||
|
||||
## Situazione iniziale
|
||||
|
||||
Dopo la reinstallazione per riavere le finestre OpenCV, lo stato era:
|
||||
|
||||
```text
|
||||
OpenCV GUI: WIN32UI
|
||||
OpenCV CUDA devices: 0
|
||||
```
|
||||
|
||||
Quindi la GUI era tornata, ma CUDA no.
|
||||
|
||||
## Installazione wheel CUDA
|
||||
|
||||
Installata la wheel:
|
||||
|
||||
```text
|
||||
https://github.com/cudawarped/opencv-python-cuda-wheels/releases/download/4.12.0.88/opencv_contrib_python-4.12.0.88-cp37-abi3-win_amd64.whl
|
||||
```
|
||||
|
||||
Motivo della scelta:
|
||||
|
||||
- il sistema ha CUDA Toolkit `v12.9`;
|
||||
- la release `4.12.0.88` e' compilata contro CUDA `12.9`;
|
||||
- la RTX 3050 ha compute capability `(8, 6)`, supportata dalla wheel.
|
||||
|
||||
## Correzione config.py
|
||||
|
||||
Dopo l'installazione, `import cv2` falliva per DLL mancanti.
|
||||
|
||||
Aggiornato:
|
||||
|
||||
```text
|
||||
C:\Python313\Lib\site-packages\cv2\config.py
|
||||
```
|
||||
|
||||
Aggiunti i path alle DLL NVIDIA presenti in:
|
||||
|
||||
```text
|
||||
C:\Python313\Lib\site-packages\nvidia\cudnn\bin
|
||||
C:\Python313\Lib\site-packages\nvidia\cublas\bin
|
||||
C:\Python313\Lib\site-packages\nvidia\cuda_runtime\bin
|
||||
C:\Python313\Lib\site-packages\nvidia\cufft\bin
|
||||
C:\Python313\Lib\site-packages\nvidia\curand\bin
|
||||
C:\Python313\Lib\site-packages\nvidia\cusolver\bin
|
||||
C:\Python313\Lib\site-packages\nvidia\cusparse\bin
|
||||
C:\Python313\Lib\site-packages\nvidia\nvjitlink\bin
|
||||
```
|
||||
|
||||
## Verifica OpenCV
|
||||
|
||||
Risultato:
|
||||
|
||||
```text
|
||||
cv2 4.12.0
|
||||
GUI: WIN32UI
|
||||
NVIDIA CUDA: YES (ver 12.9.86, CUFFT CUBLAS NVCUVID NVCUVENC)
|
||||
cuDNN: YES (ver 9.10.2)
|
||||
cuda devices: 1
|
||||
gpu resize: OK
|
||||
namedWindow: OK
|
||||
```
|
||||
|
||||
Quindi OpenCV ora ha sia GUI sia CUDA.
|
||||
|
||||
## Stato GPU complessivo
|
||||
|
||||
YOLO / Ultralytics:
|
||||
|
||||
```text
|
||||
torch_cuda True
|
||||
NVIDIA GeForce RTX 3050
|
||||
```
|
||||
|
||||
OpenCV:
|
||||
|
||||
```text
|
||||
CUDA attivo
|
||||
cuda devices 1
|
||||
```
|
||||
|
||||
PaddleOCR:
|
||||
|
||||
```text
|
||||
paddle 3.3.1
|
||||
cuda False
|
||||
device cpu
|
||||
```
|
||||
|
||||
PaddleOCR resta volutamente nel virtualenv CPU per evitare il problema precedente sulle DLL/cuDNN Paddle GPU.
|
||||
|
||||
## Nota operativa
|
||||
|
||||
Ora ha senso lavorare sui target:
|
||||
|
||||
```text
|
||||
preview/acquisizione: 24 fps
|
||||
YOLO: circa 14-15 fps
|
||||
OCR/WMS: asincrono, non deve bloccare la preview
|
||||
```
|
||||
|
||||
OpenCV CUDA non accelera automaticamente tutto il codice: serve usare esplicitamente funzioni `cv2.cuda.*` nei punti in cui conviene. Pero' ora la base CUDA e' disponibile.
|
||||
82
aggiornamento-2026-05-18-15-53.md
Normal file
@@ -0,0 +1,82 @@
|
||||
# Aggiornamento 2026-05-18 15:53
|
||||
|
||||
## Obiettivo
|
||||
|
||||
Portare subito le chiamate disponibili verso il percorso piu' veloce possibile, usando CUDA dove il costo di trasferimento CPU/GPU e' giustificato e attivando FP16 per YOLO su GPU.
|
||||
|
||||
## Modifiche
|
||||
|
||||
- Aggiunti helper OpenCV CUDA con fallback CPU:
|
||||
- `opencv_cuda_available()`
|
||||
- `cuda_resize(...)`
|
||||
- `cuda_cvt_color(...)`
|
||||
- Gli helper usano CUDA solo sopra una soglia minima di pixel, per evitare di rallentare crop piccoli con upload/download GPU.
|
||||
- Applicati gli helper a:
|
||||
- preview e resize in `flywms_navigation.py`
|
||||
- preprocessing e preview in `flywms_wms_server.py`
|
||||
- preprocessing nel worker `flywms_paddleocr_worker.py`
|
||||
- conversione BGR/RGBA della GUI DearPyGUI in `flywms_navigation_gui.py`
|
||||
- Aggiunto parametro `yolo_half` in `flywms_navigation.ini`.
|
||||
- Aggiunti flag CLI:
|
||||
- `--yolo-half`
|
||||
- `--no-yolo-half`
|
||||
- `UltralyticsDetector` passa `half=True` a `model.predict(...)` quando il device non e' CPU.
|
||||
- Log iniziale aggiornato con:
|
||||
- stato OpenCV CUDA
|
||||
- stato YOLO half precision
|
||||
|
||||
## Verifiche
|
||||
|
||||
Compilazione:
|
||||
|
||||
```powershell
|
||||
python -m py_compile flywms_navigation.py flywms_wms_server.py flywms_paddleocr_worker.py flywms_navigation_gui.py
|
||||
```
|
||||
|
||||
OpenCV:
|
||||
|
||||
```text
|
||||
cv2 4.12.0
|
||||
cuda_devices 1
|
||||
GUI: WIN32UI
|
||||
NVIDIA CUDA: YES (ver 12.9.86, CUFFT CUBLAS NVCUVID NVCUVENC)
|
||||
cuDNN: YES (ver 9.10.2)
|
||||
```
|
||||
|
||||
Helper CUDA:
|
||||
|
||||
```text
|
||||
opencv_cuda True (720, 1280, 3) (720, 1280)
|
||||
```
|
||||
|
||||
Run headless breve:
|
||||
|
||||
```powershell
|
||||
python flywms_navigation.py --no-display --max-frames 40
|
||||
```
|
||||
|
||||
Risultato rilevante:
|
||||
|
||||
```text
|
||||
OpenCV CUDA: attivo
|
||||
YOLO half precision: attiva
|
||||
```
|
||||
|
||||
Misura inferenza YOLO sullo stesso frame:
|
||||
|
||||
```text
|
||||
iter 0 ms 8430.9
|
||||
iter 1 ms 27.5
|
||||
iter 2 ms 26.7
|
||||
iter 3 ms 28.5
|
||||
iter 4 ms 30.4
|
||||
```
|
||||
|
||||
Il primo giro e' warm-up del modello. A regime YOLO e' circa 27-30 ms/frame sul frame di test, quindi compatibile con un target dimostrativo di 14-15 fps lato inferenza se la pipeline non introduce altri colli di bottiglia.
|
||||
|
||||
## Note tecniche
|
||||
|
||||
- OpenCV CUDA non accelera automaticamente tutte le chiamate: bisogna usare esplicitamente `cv2.cuda.*`.
|
||||
- Per crop piccoli e preprocessing leggero puo' essere piu' veloce restare su CPU.
|
||||
- PaddleOCR resta attualmente nel virtualenv CPU; gli helper nel worker fanno fallback se OpenCV CUDA non e' disponibile in quell'ambiente.
|
||||
- La prossima ottimizzazione importante sara' evitare warm-up visibile all'avvio, eseguendo una inferenza iniziale prima del loop operativo.
|
||||
43
aggiornamento-2026-05-18-18-15.md
Normal file
@@ -0,0 +1,43 @@
|
||||
# Aggiornamento 2026-05-18 18:15
|
||||
|
||||
## Obiettivo
|
||||
|
||||
Rendere espliciti a video i diversi FPS della demo, separando:
|
||||
|
||||
- FPS nominali della sorgente video
|
||||
- target preview
|
||||
- FPS reali del loop
|
||||
- target YOLO
|
||||
- FPS reali di YOLO
|
||||
|
||||
## Modifiche
|
||||
|
||||
- In [flywms_navigation.py](C:/devel/flywms/flywms_navigation.py) ho aggiunto `format_fps_value(...)` per mostrare valori puliti o `n/d`.
|
||||
- All'avvio della navigazione ora viene loggato:
|
||||
- `FPS sorgente=...`
|
||||
- `preview_target=...`
|
||||
- `yolo_target=...`
|
||||
- Nell'overlay della finestra `flywms navigate` ora compare una riga del tipo:
|
||||
|
||||
```text
|
||||
frame=123 src_fps=30.0 preview_target=24.0 fps=9.8 yolo_target=15.0 yolo_fps=9.7 yolo=28ms det=2 labels=2 tracks=2 snap=0
|
||||
```
|
||||
|
||||
- In [flywms_navigation_gui.py](C:/devel/flywms/flywms_navigation_gui.py) ho reso coerente lo stesso overlay.
|
||||
- Nella GUI DearPyGUI ho anche riallineato il costruttore del detector al nuovo parametro `yolo_half`.
|
||||
|
||||
## Verifica
|
||||
|
||||
Compilazione:
|
||||
|
||||
```powershell
|
||||
python -m py_compile flywms_navigation.py flywms_navigation_gui.py
|
||||
```
|
||||
|
||||
Esempio di testo generato:
|
||||
|
||||
```text
|
||||
frame=1 src_fps=30.0 preview_target=24.0 fps=1000.0 yolo_target=15.0 yolo_fps=0.0 yolo=0ms det=0 labels=0 tracks=0 snap=0
|
||||
```
|
||||
|
||||
Il valore `fps=1000.0` in questo micro-test e' artificiale, perche' non deriva da un run reale ma da una costruzione istantanea della stringa. In esecuzione reale il valore utile e' quello mostrato live in overlay.
|
||||
67
aggiornamento-2026-05-18-18-30.md
Normal file
@@ -0,0 +1,67 @@
|
||||
# Aggiornamento 2026-05-18 18:30
|
||||
|
||||
## Obiettivo
|
||||
|
||||
Registrare in un file dedicato le tempistiche dettagliate della pipeline, riducendo allo stesso tempo il costo della preview principale spostando la telemetria fuori dall'overlay.
|
||||
|
||||
## Modifiche
|
||||
|
||||
- Aggiunta classe `PerfLogWriter` in [flywms_navigation.py](C:/devel/flywms/flywms_navigation.py) con:
|
||||
- bufferizzazione in memoria
|
||||
- flush periodico a tempo
|
||||
- flush per numero di righe
|
||||
- Nuovi parametri INI/CLI:
|
||||
- `perf_log_path`
|
||||
- `perf_log_flush_interval_sec`
|
||||
- `perf_log_flush_lines`
|
||||
- Il file di default e' `tempistiche.txt`.
|
||||
- Per ogni frame vengono scritte colonne TSV con:
|
||||
- `read_ms`
|
||||
- `yolo_ms`
|
||||
- `track_ms`
|
||||
- `draw_ms`
|
||||
- `ui_ms`
|
||||
- `snapshot_pause_ms`
|
||||
- `wms_wait_ms`
|
||||
- `loop_ms`
|
||||
- `loop_fps`
|
||||
- `yolo_real_fps`
|
||||
- conteggi oggetti/track/snapshot
|
||||
- ultimo comando navigazione
|
||||
- La finestra principale `flywms navigate` non disegna piu':
|
||||
- riga FPS/metriche
|
||||
- ultimo comando
|
||||
- testo sopra i bbox dei gaylord
|
||||
- testo sopra i bbox etichetta
|
||||
- Restano nella preview principale:
|
||||
- bbox
|
||||
- centri
|
||||
- fascia utile
|
||||
- freccia di movimento simulato
|
||||
- Aggiornata anche [flywms_navigation_gui.py](C:/devel/flywms/flywms_navigation_gui.py) per il nuovo renderer alleggerito e per il costruttore `UltralyticsDetector(..., yolo_half)`.
|
||||
|
||||
## Verifica
|
||||
|
||||
Compilazione:
|
||||
|
||||
```powershell
|
||||
python -m py_compile flywms_navigation.py flywms_navigation_gui.py
|
||||
```
|
||||
|
||||
Run di test:
|
||||
|
||||
```powershell
|
||||
python flywms_navigation.py --no-display --max-frames 20 --perf-log-path tempistiche-test.txt
|
||||
```
|
||||
|
||||
Prime righe del log:
|
||||
|
||||
```text
|
||||
ts frame_id run_yolo read_ms yolo_ms track_ms draw_ms ui_ms snapshot_pause_ms wms_wait_ms loop_ms loop_fps yolo_real_fps src_fps preview_target yolo_target det labels tracks active snapshots command
|
||||
2026-05-18 18:31:14 1 1 39.710 10065.399 0.106 0.000 0.000 0.000 0.000 10150.452 0.099 0.099 30.0 24.0 15.0 2 2 2 2 0 ""
|
||||
2026-05-18 18:31:14 2 1 7.376 38.036 0.222 0.000 0.000 0.000 0.000 47.984 0.196 0.196 30.0 24.0 15.0 2 2 2 2 0 ""
|
||||
```
|
||||
|
||||
## Nota
|
||||
|
||||
Nel test headless `draw_ms` e `ui_ms` sono giustamente nulli. Nel run reale con finestre aperte il file `tempistiche.txt` mostrera' il costo della parte grafica e delle pause simulate, che e' proprio quello che ci serve per capire dove si perde il target FPS.
|
||||
58
aggiornamento-2026-05-18-19-14.md
Normal file
@@ -0,0 +1,58 @@
|
||||
# Aggiornamento 2026-05-18 19:14
|
||||
|
||||
## Obiettivo
|
||||
|
||||
Preparare una versione benchmark della navigazione senza interfaccia, con cattura/preview target a 30 fps, per confrontare il costo della UI rispetto alla pipeline pura.
|
||||
|
||||
## Modifiche
|
||||
|
||||
- Aggiunto profilo `benchmark` in [flywms_navigation.py](C:/devel/flywms/flywms_navigation.py):
|
||||
- `--benchmark-mode`
|
||||
- `--benchmark-preview-fps`
|
||||
- Aggiunte le controparti INI in [flywms_navigation.ini](C:/devel/flywms/flywms_navigation.ini):
|
||||
- `benchmark_mode = false`
|
||||
- `benchmark_preview_fps = 30.0`
|
||||
- Quando `benchmark_mode` e' attivo:
|
||||
- forza `no_display = true`
|
||||
- forza `window_layout_enabled = false`
|
||||
- forza `realtime_playback = true`
|
||||
- forza `preview_fps = benchmark_preview_fps`
|
||||
- se il log tempi e' quello di default, lo sposta su `tempistiche-benchmark.txt`
|
||||
|
||||
## Uso
|
||||
|
||||
```powershell
|
||||
python flywms_navigation.py --benchmark-mode
|
||||
```
|
||||
|
||||
Oppure, con file log esplicito:
|
||||
|
||||
```powershell
|
||||
python flywms_navigation.py --benchmark-mode --perf-log-path tempistiche-benchmark.txt
|
||||
```
|
||||
|
||||
## Verifica
|
||||
|
||||
Compilazione:
|
||||
|
||||
```powershell
|
||||
python -m py_compile flywms_navigation.py
|
||||
```
|
||||
|
||||
Run breve:
|
||||
|
||||
```powershell
|
||||
python flywms_navigation.py --benchmark-mode --max-frames 40
|
||||
```
|
||||
|
||||
Output iniziale verificato:
|
||||
|
||||
```text
|
||||
Profilo benchmark attivo: no_display=true preview_fps=30.0 log=tempistiche-benchmark.txt
|
||||
FPS sorgente=30.0 preview_target=30.0 yolo_target=15.0
|
||||
Log tempistiche: C:\devel\flywms\tempistiche-benchmark.txt
|
||||
```
|
||||
|
||||
## Nota
|
||||
|
||||
Nel run corto di test c'e' stato un warm-up molto pesante di YOLO/NMS al primo frame, quindi quel log non va ancora usato come benchmark finale. Serve un run completo o almeno piu' lungo per avere un confronto sensato con la demo.
|
||||
97
aggiornamento-2026-05-18-19-58.md
Normal file
@@ -0,0 +1,97 @@
|
||||
# Aggiornamento 2026-05-18 19:58
|
||||
|
||||
## Analisi benchmark
|
||||
|
||||
File analizzato:
|
||||
|
||||
- [tempistiche-benchmark.txt](C:/devel/flywms/tempistiche-benchmark.txt)
|
||||
|
||||
Nota metodologica:
|
||||
|
||||
- Il file conteneva due intestazioni (`ts ...`) perche' un run breve di verifica era stato appeso al run completo.
|
||||
- L'analisi e' stata fatta filtrando solo le righe con `frame_id` numerico.
|
||||
|
||||
## Risultati principali
|
||||
|
||||
- Frame validi: `19789`
|
||||
- Snapshot: `69`
|
||||
- Video sorgente: `30.0 fps`
|
||||
- Durata nominale video: circa `658.3 s` = `10.97 min`
|
||||
|
||||
Benchmark completo:
|
||||
|
||||
- `total_loop_s = 2004.19 s`
|
||||
- `total_pause_s = 552.03 s`
|
||||
- `total_wms_s = 690.03 s`
|
||||
- `total_active_s = 762.13 s`
|
||||
|
||||
Interpretazione:
|
||||
|
||||
- Le pause snapshot headless valgono circa `8.0 s` ciascuna.
|
||||
- L'attesa WMS simulata headless vale circa `10.0 s` per snapshot.
|
||||
- Quindi il benchmark completo include ancora il comportamento demo di snapshot+attesa, solo senza finestre.
|
||||
|
||||
## Prestazioni nette della pipeline
|
||||
|
||||
Togliendo pause snapshot e attesa WMS:
|
||||
|
||||
- `active_fps = 25.97`
|
||||
- `active_yolo_fps = 12.69`
|
||||
|
||||
Tempi medi in regime stabile:
|
||||
|
||||
- `mean_loop_ms = 36.90`
|
||||
- `mean_read_ms = 6.10`
|
||||
- `mean_yolo_ms = 31.20`
|
||||
- `mean_track_ms = 0.18`
|
||||
- `mean_draw_ms = 0.00`
|
||||
- `mean_ui_ms = 0.00`
|
||||
|
||||
Percentili:
|
||||
|
||||
- `loop_p50 = 33.91 ms`
|
||||
- `loop_p90 = 68.93 ms`
|
||||
- `loop_p95 = 73.14 ms`
|
||||
- `yolo_p50 = 27.85 ms`
|
||||
- `yolo_p90 = 38.05 ms`
|
||||
- `yolo_p95 = 46.10 ms`
|
||||
|
||||
## Confronto con la demo OpenCV
|
||||
|
||||
Run demo precedente:
|
||||
|
||||
- `demo_active_s = 1092.85 s`
|
||||
- `demo_draw_ui_s = 597.18 s`
|
||||
|
||||
Run benchmark:
|
||||
|
||||
- `benchmark_active_s = 762.13 s`
|
||||
- `benchmark_draw_ui_s = 0`
|
||||
|
||||
Risparmio netto:
|
||||
|
||||
- `active_s_saved = 330.72 s` circa `5.51 min`
|
||||
|
||||
## Conclusione
|
||||
|
||||
La UI OpenCV pesava davvero molto, ma non era l'unico problema.
|
||||
|
||||
Tolte completamente le finestre:
|
||||
|
||||
- la pipeline netta scende a circa `12.70 min`
|
||||
- il video reale dura circa `10.97 min`
|
||||
|
||||
Residuo rispetto all'obiettivo netto:
|
||||
|
||||
- circa `103.8 s` = `1.73 min`
|
||||
|
||||
Questa parte residua dipende principalmente da:
|
||||
|
||||
- inferenza YOLO ancora sotto il target di `15 fps`
|
||||
- costo di `cap.read()`
|
||||
- scheduling single-thread del loop
|
||||
|
||||
Quindi:
|
||||
|
||||
- la demo con interfaccia va ripensata per non ricadere nel costo UI attuale
|
||||
- la pipeline core, senza UI, e' ormai abbastanza vicina all'obiettivo ma non ancora coincidente con la durata del video
|
||||
86
aggiornamento-2026-05-29-16-38.md
Normal file
@@ -0,0 +1,86 @@
|
||||
# Aggiornamento 2026-05-29 16:38
|
||||
|
||||
## Step 1 - Core / Observer
|
||||
|
||||
Completati:
|
||||
|
||||
- documento di progetto Step 1 in [step1_core_observer_design.md](/C:/devel/flywms/step1_core_observer_design.md)
|
||||
- separazione iniziale tra core runtime e observer esterno
|
||||
- configurazione observer aggiunta in [flywms_navigation.ini](/C:/devel/flywms/flywms_navigation.ini)
|
||||
- nuovo entrypoint observer in [flywms_navigation_observer.py](/C:/devel/flywms/flywms_navigation_observer.py)
|
||||
|
||||
## Modifiche implementate
|
||||
|
||||
In [flywms_navigation.py](/C:/devel/flywms/flywms_navigation.py):
|
||||
|
||||
- aggiunto `ObserverPublisher`
|
||||
- il core puo' pubblicare su `localhost`:
|
||||
- telemetria strutturata
|
||||
- preview JPEG a bassa frequenza
|
||||
- quando `observer_enabled = true`:
|
||||
- la UI locale integrata viene disattivata
|
||||
- il core non aspetta l'observer
|
||||
- l'observer puo' essere assente o disconnettersi senza bloccare la pipeline
|
||||
- la sequenza snapshot headless e' stata resa osservabile per fasi:
|
||||
- `move`
|
||||
- `stabilize`
|
||||
- `capture`
|
||||
- `return`
|
||||
- `wait_wms`
|
||||
|
||||
In [flywms_navigation_observer.py](/C:/devel/flywms/flywms_navigation_observer.py):
|
||||
|
||||
- processo separato
|
||||
- connessione TCP locale al core
|
||||
- visualizzazione di:
|
||||
- preview navigazione
|
||||
- pannello comandi/stato
|
||||
- snapshot
|
||||
- crop etichetta
|
||||
|
||||
## Verifiche eseguite
|
||||
|
||||
1. Compilazione Python:
|
||||
|
||||
```bash
|
||||
python -m py_compile flywms_navigation.py flywms_navigation_observer.py
|
||||
```
|
||||
|
||||
Esito: ok.
|
||||
|
||||
2. Smoke test core con observer attivo ma non collegato:
|
||||
|
||||
```bash
|
||||
python flywms_navigation.py --video testhd2_edit.mp4 --observer-enabled --max-frames 30
|
||||
```
|
||||
|
||||
Esito:
|
||||
|
||||
- il core parte regolarmente
|
||||
- la UI locale viene disattivata come previsto
|
||||
- il publisher si mette in ascolto su `127.0.0.1:8765`
|
||||
- il run chiude senza blocchi anche senza observer collegato
|
||||
|
||||
## Stato attuale
|
||||
|
||||
Lo Step 1 e' implementato nella sua forma iniziale e il lato critico del core e' verificato.
|
||||
|
||||
Resta da fare una verifica manuale della GUI observer in esecuzione reale, cioe':
|
||||
|
||||
1. avviare `flywms_navigation_observer.py`
|
||||
2. avviare il core con `--observer-enabled`
|
||||
3. controllare fluidita', frequenza preview e correttezza dei pannelli
|
||||
|
||||
## Comandi di avvio previsti
|
||||
|
||||
Observer:
|
||||
|
||||
```bash
|
||||
python flywms_navigation_observer.py
|
||||
```
|
||||
|
||||
Core:
|
||||
|
||||
```bash
|
||||
python flywms_navigation.py --video testhd2_edit.mp4 --observer-enabled
|
||||
```
|
||||
75
aggiornamento-2026-05-30-18-12.md
Normal file
@@ -0,0 +1,75 @@
|
||||
# Aggiornamento 2026-05-30 18:12
|
||||
|
||||
## Step 2 - Capture / Inference
|
||||
|
||||
Completati:
|
||||
|
||||
- documento di progetto Step 2 in [step2_capture_inference_design.md](/C:/devel/flywms/step2_capture_inference_design.md)
|
||||
- introduzione del pacchetto `CapturedFrame`
|
||||
- introduzione del `CaptureWorker`
|
||||
- propagazione della posa congelata dal capture fino allo snapshot
|
||||
|
||||
## Modifiche implementate
|
||||
|
||||
In [flywms_navigation.py](/C:/devel/flywms/flywms_navigation.py):
|
||||
|
||||
- aggiunto `CapturedFrame` con:
|
||||
- `frame_id`
|
||||
- `timestamp`
|
||||
- `video_time_sec`
|
||||
- `frame`
|
||||
- `pose`
|
||||
- `read_ms`
|
||||
- aggiunto `sample_demo_pose(...)`
|
||||
- aggiunto `CaptureWorker` con coda `maxsize=1`
|
||||
- politica di coda: `latest frame wins`
|
||||
- `cap.read()` spostato fuori dal loop principale
|
||||
- `NavigationController.process_track(...)` ora consuma `CapturedFrame`
|
||||
- `CandidateSnapshot` e `NavigationSnapshot` ora portano anche `capture_pose`
|
||||
- metadata snapshot JSON aggiornati: `drone_pose_simulated` ora deriva dal frame catturato
|
||||
|
||||
## Correzione importante sulle metriche
|
||||
|
||||
Con `latest frame wins`, il `frame_id` della sorgente puo' saltare. Per questo:
|
||||
|
||||
- `frame_id` resta l'identificativo del frame sorgente;
|
||||
- `processed_frames` misura invece quanti frame il core ha davvero consumato.
|
||||
|
||||
Le metriche `loop_fps` e i log prestazionali ora usano `processed_frames`, non `frame_id`.
|
||||
|
||||
## Verifiche eseguite
|
||||
|
||||
1. Compilazione Python:
|
||||
|
||||
```bash
|
||||
python -m py_compile flywms_navigation.py flywms_navigation_observer.py
|
||||
```
|
||||
|
||||
Esito: ok.
|
||||
|
||||
2. Smoke test core senza observer:
|
||||
|
||||
```bash
|
||||
python flywms_navigation.py --video testhd2_edit.mp4 --max-frames 30
|
||||
```
|
||||
|
||||
Esito: ok.
|
||||
|
||||
3. Smoke test core con observer attivo:
|
||||
|
||||
```bash
|
||||
python flywms_navigation.py --video testhd2_edit.mp4 --observer-enabled --max-frames 30
|
||||
```
|
||||
|
||||
Esito: ok.
|
||||
|
||||
## Nota operativa
|
||||
|
||||
Dopo lo Step 2, `--max-frames` resta un limite sui frame della sorgente video, non sui frame effettivamente processati.
|
||||
|
||||
Questo va bene per smoke test rapidi, ma non e' il modo corretto per giudicare la resa finale della pipeline realtime. Il benchmark successivo va fatto sulla durata completa del video, confrontando:
|
||||
|
||||
- durata nominale video;
|
||||
- durata effettiva demo;
|
||||
- `processed_frames`;
|
||||
- `yolo_fps` reale.
|
||||
73
aggiornamento-2026-05-30-19-08.md
Normal file
@@ -0,0 +1,73 @@
|
||||
# Aggiornamento 2026-05-30 19:08
|
||||
|
||||
## Step 3 - Inferenza adattiva
|
||||
|
||||
Documentazione:
|
||||
|
||||
- [step3_adaptive_inference_design.md](/C:/devel/flywms/step3_adaptive_inference_design.md)
|
||||
|
||||
Implementato:
|
||||
|
||||
- scheduler YOLO adattivo con tre stati:
|
||||
- `idle`
|
||||
- `tracking`
|
||||
- `critical`
|
||||
- parametri configurabili:
|
||||
- `adaptive_yolo_enabled`
|
||||
- `idle_yolo_fps`
|
||||
- `tracking_yolo_fps`
|
||||
- `critical_yolo_fps`
|
||||
- telemetria observer aggiornata con `yolo_mode`
|
||||
|
||||
## Esito benchmark
|
||||
|
||||
Run completo con:
|
||||
|
||||
- `adaptive_yolo_enabled = true`
|
||||
- `idle = 8`
|
||||
- `tracking = 12`
|
||||
- `critical = 15`
|
||||
|
||||
Risultato finale:
|
||||
|
||||
- durata demo totale: `874.73 s`
|
||||
- durata demo netta senza WMS: `796.71 s`
|
||||
- durata video: `658.14 s`
|
||||
- scostamento netto: `+138.57 s` = `+21.1%`
|
||||
|
||||
Confronto con run precedente senza adattivo:
|
||||
|
||||
- netto precedente: `756.18 s`
|
||||
- netto con adattivo: `796.71 s`
|
||||
- peggioramento: circa `+40.5 s`
|
||||
|
||||
## Interpretazione
|
||||
|
||||
La riduzione della frequenza YOLO nei tratti idle non ha compensato l'effetto collaterale introdotto sul comportamento del tracking e della logica snapshot.
|
||||
|
||||
In pratica:
|
||||
|
||||
- il costo medio YOLO e' sceso;
|
||||
- ma il comportamento globale della missione e' peggiorato;
|
||||
- quindi questa prima forma di inferenza adattiva non e' vantaggiosa.
|
||||
|
||||
## Decisione
|
||||
|
||||
La feature resta disponibile nel codice come opzione sperimentale, ma viene disattivata di default:
|
||||
|
||||
- [flywms_navigation.py](/C:/devel/flywms/flywms_navigation.py)
|
||||
- [flywms_navigation.ini](/C:/devel/flywms/flywms_navigation.ini)
|
||||
|
||||
Default attuale:
|
||||
|
||||
- `adaptive_yolo_enabled = false`
|
||||
|
||||
## Conclusione
|
||||
|
||||
Lo Step 3, nella forma provata oggi, non va adottato come ottimizzazione di default.
|
||||
|
||||
Se si vorra' tornare su questa strada, servira' una strategia piu' mirata, ad esempio:
|
||||
|
||||
- adattamento solo in assenza totale di target per un certo tempo;
|
||||
- nessuna riduzione di frequenza quando esistono track vive;
|
||||
- oppure un criterio basato su zone del video predefinite, non solo sullo stato istantaneo delle track.
|
||||
61
aggiornamento-2026-06-03-21-10.md
Normal file
@@ -0,0 +1,61 @@
|
||||
## Aggiornamento 2026-06-03 21:10
|
||||
|
||||
### Obiettivo
|
||||
Introdurre una UI DearPyGUI solo per i componenti esterni:
|
||||
- observer di `flywms_navigation`
|
||||
- server `flywms_wms_server`
|
||||
|
||||
Lasciare invariata la parte intelligente del core:
|
||||
- acquisizione
|
||||
- inferenza
|
||||
- tracking
|
||||
- logica di navigazione e snapshot
|
||||
|
||||
### Baseline salvata
|
||||
- Commit locale: `e86c05a`
|
||||
- Tag locale: `gui-observer-in-opencv`
|
||||
|
||||
Nota: il push su Gitea non e' riuscito per problema di risoluzione DNS dell'host remoto.
|
||||
|
||||
### Documentazione aggiunta
|
||||
- `dearpygui_observer_server_spec.md`
|
||||
|
||||
### Modifiche implementate
|
||||
|
||||
#### `flywms_navigation_observer.py`
|
||||
- aggiunto supporto backend UI:
|
||||
- `dearpygui`
|
||||
- `opencv`
|
||||
- `auto`
|
||||
- mantenuto il protocollo socket esistente con il core
|
||||
- aggiunta UI DearPyGUI con:
|
||||
- preview principale navigazione
|
||||
- preview snapshot
|
||||
- preview crop etichetta
|
||||
- pannello stato
|
||||
- pannello metriche
|
||||
- pannello comandi
|
||||
- mantenuto fallback OpenCV
|
||||
|
||||
#### `flywms_wms_server.py`
|
||||
- aggiunto supporto backend UI:
|
||||
- `dearpygui`
|
||||
- `opencv`
|
||||
- `auto`
|
||||
- lasciata invariata la logica FastAPI/OCR/ACK
|
||||
- aggiunta UI DearPyGUI con:
|
||||
- immagine ricevuta
|
||||
- stato server
|
||||
- payload OCR / WMS
|
||||
- mantenuto fallback OpenCV
|
||||
|
||||
### Verifiche eseguite
|
||||
- `python -m py_compile flywms_navigation_observer.py flywms_wms_server.py`
|
||||
- import e selezione backend:
|
||||
- `flywms_navigation_observer.choose_backend('auto') -> dearpygui`
|
||||
- `flywms_wms_server.choose_ui_backend('auto') -> dearpygui`
|
||||
|
||||
### Stato attuale
|
||||
- core intelligente invariato
|
||||
- observer e server pronti per prova con DearPyGUI
|
||||
- fallback OpenCV ancora disponibile per debug
|
||||
2
data/img/classes.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
gaylord
|
||||
etichetta
|
||||
13
dataset_yolo/README.md
Normal file
@@ -0,0 +1,13 @@
|
||||
# FlyWMS YOLO dataset
|
||||
|
||||
Classi:
|
||||
|
||||
- 0 gaylord
|
||||
- 1 etichetta
|
||||
|
||||
Regole annotazione:
|
||||
|
||||
- gaylord: corpo visibile dell unita di carico, senza pallet per ora.
|
||||
- etichetta: rettangolo bianco dell etichetta.
|
||||
- annotare tutti gli oggetti visibili e riconoscibili.
|
||||
- se un oggetto e tagliato dal bordo, annotare la parte visibile.
|
||||
2
dataset_yolo/classes.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
gaylord
|
||||
etichetta
|
||||
7
dataset_yolo/data.yaml
Normal file
@@ -0,0 +1,7 @@
|
||||
path: C:/devel/flywms/dataset_yolo
|
||||
train: images/train
|
||||
val: images/val
|
||||
|
||||
names:
|
||||
0: gaylord
|
||||
1: etichetta
|
||||
BIN
dataset_yolo/export_val/project-val-cleaned-2026-05-15.zip
Normal file
25
dataset_yolo/export_val/quality_check/remap_report.json
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"zip": "C:\\devel\\flywms\\dataset_yolo\\export_val\\project-val-cleaned-2026-05-15.zip",
|
||||
"export_classes": [
|
||||
"etichetta",
|
||||
"gaylord"
|
||||
],
|
||||
"remap": {
|
||||
"0": 1,
|
||||
"1": 0
|
||||
},
|
||||
"val_images": 16,
|
||||
"export_label_files": 15,
|
||||
"missing_from_export_written_empty": [
|
||||
"testhd_f002172_s1539"
|
||||
],
|
||||
"counts": {
|
||||
"gaylord": 50,
|
||||
"etichetta": 43
|
||||
},
|
||||
"empty_final_files": 1,
|
||||
"issues": [],
|
||||
"final_issues": [],
|
||||
"backup": "C:\\devel\\flywms\\dataset_yolo\\labels\\val_backup_before_remap_20260515_151934",
|
||||
"preview": "C:\\devel\\flywms\\dataset_yolo\\export_val\\quality_check\\val_remapped_preview.jpg"
|
||||
}
|
||||
BIN
dataset_yolo/export_val/quality_check/val_remapped_preview.jpg
Normal file
|
After Width: | Height: | Size: 314 KiB |
493
dataset_yolo/exports_train/quality_check/report.json
Normal file
@@ -0,0 +1,493 @@
|
||||
{
|
||||
"label_files": 61,
|
||||
"empty_files": [
|
||||
"testhd_f000543_s0574"
|
||||
],
|
||||
"box_counts": {
|
||||
"etichetta": 177,
|
||||
"gaylord": 133
|
||||
},
|
||||
"issues": [
|
||||
"testhd_f000000_s0582.txt:2 coord out of range (0.8337236533957847, 0.5000000000000001, 0.33255269320843084, 1.0000000000000002)"
|
||||
],
|
||||
"boxes_per_image": [
|
||||
[
|
||||
"testhd2_f000000_s0559",
|
||||
2,
|
||||
{
|
||||
"gaylord": 1,
|
||||
"etichetta": 1
|
||||
}
|
||||
],
|
||||
[
|
||||
"testhd2_f000522_s0480",
|
||||
2,
|
||||
{
|
||||
"gaylord": 1,
|
||||
"etichetta": 1
|
||||
}
|
||||
],
|
||||
[
|
||||
"testhd2_f001044_s1361",
|
||||
5,
|
||||
{
|
||||
"gaylord": 2,
|
||||
"etichetta": 3
|
||||
}
|
||||
],
|
||||
[
|
||||
"testhd2_f002610_s1316",
|
||||
2,
|
||||
{
|
||||
"gaylord": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
"testhd2_f003132_s1532",
|
||||
2,
|
||||
{
|
||||
"etichetta": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
"testhd2_f003828_s1406",
|
||||
6,
|
||||
{
|
||||
"gaylord": 2,
|
||||
"etichetta": 4
|
||||
}
|
||||
],
|
||||
[
|
||||
"testhd2_f004350_s1655",
|
||||
4,
|
||||
{
|
||||
"gaylord": 2,
|
||||
"etichetta": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
"testhd2_f005394_s2116",
|
||||
6,
|
||||
{
|
||||
"gaylord": 2,
|
||||
"etichetta": 4
|
||||
}
|
||||
],
|
||||
[
|
||||
"testhd2_f005916_s1944",
|
||||
3,
|
||||
{
|
||||
"gaylord": 3
|
||||
}
|
||||
],
|
||||
[
|
||||
"testhd2_f006438_s2196",
|
||||
3,
|
||||
{
|
||||
"gaylord": 3
|
||||
}
|
||||
],
|
||||
[
|
||||
"testhd2_f006960_s2179",
|
||||
3,
|
||||
{
|
||||
"gaylord": 3
|
||||
}
|
||||
],
|
||||
[
|
||||
"testhd2_f008004_s1307",
|
||||
6,
|
||||
{
|
||||
"gaylord": 2,
|
||||
"etichetta": 4
|
||||
}
|
||||
],
|
||||
[
|
||||
"testhd2_f008526_s1167",
|
||||
8,
|
||||
{
|
||||
"gaylord": 4,
|
||||
"etichetta": 4
|
||||
}
|
||||
],
|
||||
[
|
||||
"testhd2_f009048_s1165",
|
||||
5,
|
||||
{
|
||||
"gaylord": 2,
|
||||
"etichetta": 3
|
||||
}
|
||||
],
|
||||
[
|
||||
"testhd2_f009570_s1661",
|
||||
7,
|
||||
{
|
||||
"gaylord": 3,
|
||||
"etichetta": 4
|
||||
}
|
||||
],
|
||||
[
|
||||
"testhd2_f010788_s2001",
|
||||
9,
|
||||
{
|
||||
"gaylord": 3,
|
||||
"etichetta": 6
|
||||
}
|
||||
],
|
||||
[
|
||||
"testhd2_f011310_s1307",
|
||||
4,
|
||||
{
|
||||
"gaylord": 2,
|
||||
"etichetta": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
"testhd2_f011832_s1219",
|
||||
6,
|
||||
{
|
||||
"gaylord": 2,
|
||||
"etichetta": 4
|
||||
}
|
||||
],
|
||||
[
|
||||
"testhd2_f012354_s1318",
|
||||
5,
|
||||
{
|
||||
"gaylord": 2,
|
||||
"etichetta": 3
|
||||
}
|
||||
],
|
||||
[
|
||||
"testhd2_f013398_s1856",
|
||||
11,
|
||||
{
|
||||
"gaylord": 3,
|
||||
"etichetta": 8
|
||||
}
|
||||
],
|
||||
[
|
||||
"testhd2_f013920_s1830",
|
||||
9,
|
||||
{
|
||||
"gaylord": 3,
|
||||
"etichetta": 6
|
||||
}
|
||||
],
|
||||
[
|
||||
"testhd2_f014442_s2191",
|
||||
5,
|
||||
{
|
||||
"gaylord": 1,
|
||||
"etichetta": 4
|
||||
}
|
||||
],
|
||||
[
|
||||
"testhd2_f014964_s1402",
|
||||
8,
|
||||
{
|
||||
"gaylord": 2,
|
||||
"etichetta": 6
|
||||
}
|
||||
],
|
||||
[
|
||||
"testhd2_f016008_s1424",
|
||||
4,
|
||||
{
|
||||
"gaylord": 2,
|
||||
"etichetta": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
"testhd2_f016530_s1153",
|
||||
6,
|
||||
{
|
||||
"gaylord": 2,
|
||||
"etichetta": 4
|
||||
}
|
||||
],
|
||||
[
|
||||
"testhd2_f017052_s0719",
|
||||
4,
|
||||
{
|
||||
"gaylord": 2,
|
||||
"etichetta": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
"testhd2_f017748_s0986",
|
||||
4,
|
||||
{
|
||||
"gaylord": 2,
|
||||
"etichetta": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
"testhd2_f018792_s1435",
|
||||
8,
|
||||
{
|
||||
"gaylord": 4,
|
||||
"etichetta": 4
|
||||
}
|
||||
],
|
||||
[
|
||||
"testhd2_f019314_s1231",
|
||||
6,
|
||||
{
|
||||
"gaylord": 3,
|
||||
"etichetta": 3
|
||||
}
|
||||
],
|
||||
[
|
||||
"testhd2_f019836_s1049",
|
||||
6,
|
||||
{
|
||||
"gaylord": 2,
|
||||
"etichetta": 4
|
||||
}
|
||||
],
|
||||
[
|
||||
"testhd2_f020358_s1742",
|
||||
4,
|
||||
{
|
||||
"gaylord": 2,
|
||||
"etichetta": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
"testhd_f000000_s0582",
|
||||
3,
|
||||
{
|
||||
"etichetta": 2,
|
||||
"gaylord": 1
|
||||
}
|
||||
],
|
||||
[
|
||||
"testhd_f000543_s0574",
|
||||
0,
|
||||
{}
|
||||
],
|
||||
[
|
||||
"testhd_f001086_s0908",
|
||||
1,
|
||||
{
|
||||
"etichetta": 1
|
||||
}
|
||||
],
|
||||
[
|
||||
"testhd_f001629_s1334",
|
||||
4,
|
||||
{
|
||||
"etichetta": 2,
|
||||
"gaylord": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
"testhd_f002715_s1348",
|
||||
3,
|
||||
{
|
||||
"gaylord": 3
|
||||
}
|
||||
],
|
||||
[
|
||||
"testhd_f003258_s1453",
|
||||
2,
|
||||
{
|
||||
"gaylord": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
"testhd_f003982_s1755",
|
||||
2,
|
||||
{
|
||||
"etichetta": 1,
|
||||
"gaylord": 1
|
||||
}
|
||||
],
|
||||
[
|
||||
"testhd_f004525_s1283",
|
||||
2,
|
||||
{
|
||||
"gaylord": 1,
|
||||
"etichetta": 1
|
||||
}
|
||||
],
|
||||
[
|
||||
"testhd_f005611_s2120",
|
||||
4,
|
||||
{
|
||||
"etichetta": 2,
|
||||
"gaylord": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
"testhd_f006154_s2426",
|
||||
2,
|
||||
{
|
||||
"gaylord": 1,
|
||||
"etichetta": 1
|
||||
}
|
||||
],
|
||||
[
|
||||
"testhd_f008326_s1493",
|
||||
4,
|
||||
{
|
||||
"gaylord": 2,
|
||||
"etichetta": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
"testhd_f008869_s1403",
|
||||
6,
|
||||
{
|
||||
"gaylord": 2,
|
||||
"etichetta": 4
|
||||
}
|
||||
],
|
||||
[
|
||||
"testhd_f009412_s1102",
|
||||
4,
|
||||
{
|
||||
"gaylord": 2,
|
||||
"etichetta": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
"testhd_f009955_s1320",
|
||||
6,
|
||||
{
|
||||
"gaylord": 3,
|
||||
"etichetta": 3
|
||||
}
|
||||
],
|
||||
[
|
||||
"testhd_f011222_s1666",
|
||||
7,
|
||||
{
|
||||
"gaylord": 3,
|
||||
"etichetta": 4
|
||||
}
|
||||
],
|
||||
[
|
||||
"testhd_f011765_s1527",
|
||||
6,
|
||||
{
|
||||
"gaylord": 3,
|
||||
"etichetta": 3
|
||||
}
|
||||
],
|
||||
[
|
||||
"testhd_f012308_s1235",
|
||||
6,
|
||||
{
|
||||
"gaylord": 2,
|
||||
"etichetta": 4
|
||||
}
|
||||
],
|
||||
[
|
||||
"testhd_f012851_s1496",
|
||||
4,
|
||||
{
|
||||
"gaylord": 2,
|
||||
"etichetta": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
"testhd_f013937_s1949",
|
||||
11,
|
||||
{
|
||||
"gaylord": 3,
|
||||
"etichetta": 8
|
||||
}
|
||||
],
|
||||
[
|
||||
"testhd_f014480_s2048",
|
||||
11,
|
||||
{
|
||||
"gaylord": 3,
|
||||
"etichetta": 8
|
||||
}
|
||||
],
|
||||
[
|
||||
"testhd_f015023_s1996",
|
||||
6,
|
||||
{
|
||||
"gaylord": 2,
|
||||
"etichetta": 4
|
||||
}
|
||||
],
|
||||
[
|
||||
"testhd_f015566_s1402",
|
||||
8,
|
||||
{
|
||||
"gaylord": 3,
|
||||
"etichetta": 5
|
||||
}
|
||||
],
|
||||
[
|
||||
"testhd_f016652_s1419",
|
||||
4,
|
||||
{
|
||||
"gaylord": 2,
|
||||
"etichetta": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
"testhd_f017195_s1173",
|
||||
6,
|
||||
{
|
||||
"gaylord": 2,
|
||||
"etichetta": 4
|
||||
}
|
||||
],
|
||||
[
|
||||
"testhd_f017738_s0715",
|
||||
4,
|
||||
{
|
||||
"gaylord": 2,
|
||||
"etichetta": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
"testhd_f018462_s1305",
|
||||
6,
|
||||
{
|
||||
"gaylord": 4,
|
||||
"etichetta": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
"testhd_f019548_s1342",
|
||||
6,
|
||||
{
|
||||
"gaylord": 3,
|
||||
"etichetta": 3
|
||||
}
|
||||
],
|
||||
[
|
||||
"testhd_f020091_s0989",
|
||||
5,
|
||||
{
|
||||
"gaylord": 2,
|
||||
"etichetta": 3
|
||||
}
|
||||
],
|
||||
[
|
||||
"testhd_f020634_s1195",
|
||||
6,
|
||||
{
|
||||
"gaylord": 3,
|
||||
"etichetta": 3
|
||||
}
|
||||
],
|
||||
[
|
||||
"testhd_f021177_s2394",
|
||||
8,
|
||||
{
|
||||
"gaylord": 3,
|
||||
"etichetta": 5
|
||||
}
|
||||
]
|
||||
],
|
||||
"preview": "C:\\devel\\flywms\\dataset_yolo\\exports_train\\quality_check\\train_annotation_preview.jpg"
|
||||
}
|
||||
|
After Width: | Height: | Size: 269 KiB |
|
After Width: | Height: | Size: 298 KiB |
|
After Width: | Height: | Size: 266 KiB |
|
After Width: | Height: | Size: 279 KiB |
|
After Width: | Height: | Size: 268 KiB |
|
After Width: | Height: | Size: 26 KiB |
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"zip": "C:\\devel\\flywms\\dataset_yolo\\exports_train_v2\\project-train-cleaned-2026-05-15.zip",
|
||||
"export_classes": [
|
||||
"etichetta",
|
||||
"gaylord"
|
||||
],
|
||||
"target_classes": {
|
||||
"0": "gaylord",
|
||||
"1": "etichetta"
|
||||
},
|
||||
"remap": {
|
||||
"0": 1,
|
||||
"1": 0
|
||||
},
|
||||
"train_images": 64,
|
||||
"export_label_files": 63,
|
||||
"missing_from_export_written_empty": [
|
||||
"testhd2_f001566_s1309"
|
||||
],
|
||||
"counts": {
|
||||
"gaylord": 175,
|
||||
"etichetta": 135
|
||||
},
|
||||
"issues": [],
|
||||
"backup": "C:\\devel\\flywms\\dataset_yolo\\labels\\train_backup_before_remap_20260515_145941",
|
||||
"previews": [
|
||||
"C:\\devel\\flywms\\dataset_yolo\\exports_train_v2\\quality_check\\train_remapped_preview_p1.jpg",
|
||||
"C:\\devel\\flywms\\dataset_yolo\\exports_train_v2\\quality_check\\train_remapped_preview_p2.jpg",
|
||||
"C:\\devel\\flywms\\dataset_yolo\\exports_train_v2\\quality_check\\train_remapped_preview_p3.jpg",
|
||||
"C:\\devel\\flywms\\dataset_yolo\\exports_train_v2\\quality_check\\train_remapped_preview_p4.jpg",
|
||||
"C:\\devel\\flywms\\dataset_yolo\\exports_train_v2\\quality_check\\train_remapped_preview_p5.jpg"
|
||||
]
|
||||
}
|
||||
|
After Width: | Height: | Size: 299 KiB |
|
After Width: | Height: | Size: 268 KiB |
|
After Width: | Height: | Size: 289 KiB |
|
After Width: | Height: | Size: 272 KiB |
|
After Width: | Height: | Size: 76 KiB |
2
dataset_yolo/images/train/classes.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
gaylord
|
||||
etichetta
|
||||
BIN
dataset_yolo/images/train/testhd2_f000000_s0559.jpg
Normal file
|
After Width: | Height: | Size: 147 KiB |
BIN
dataset_yolo/images/train/testhd2_f000522_s0480.jpg
Normal file
|
After Width: | Height: | Size: 161 KiB |
BIN
dataset_yolo/images/train/testhd2_f001044_s1361.jpg
Normal file
|
After Width: | Height: | Size: 211 KiB |
BIN
dataset_yolo/images/train/testhd2_f001566_s1309.jpg
Normal file
|
After Width: | Height: | Size: 365 KiB |
BIN
dataset_yolo/images/train/testhd2_f002610_s1316.jpg
Normal file
|
After Width: | Height: | Size: 336 KiB |
BIN
dataset_yolo/images/train/testhd2_f003132_s1532.jpg
Normal file
|
After Width: | Height: | Size: 318 KiB |
BIN
dataset_yolo/images/train/testhd2_f003828_s1406.jpg
Normal file
|
After Width: | Height: | Size: 272 KiB |
BIN
dataset_yolo/images/train/testhd2_f004350_s1655.jpg
Normal file
|
After Width: | Height: | Size: 279 KiB |
BIN
dataset_yolo/images/train/testhd2_f005394_s2116.jpg
Normal file
|
After Width: | Height: | Size: 316 KiB |
BIN
dataset_yolo/images/train/testhd2_f005916_s1944.jpg
Normal file
|
After Width: | Height: | Size: 356 KiB |
BIN
dataset_yolo/images/train/testhd2_f006438_s2196.jpg
Normal file
|
After Width: | Height: | Size: 359 KiB |
BIN
dataset_yolo/images/train/testhd2_f006960_s2179.jpg
Normal file
|
After Width: | Height: | Size: 343 KiB |
BIN
dataset_yolo/images/train/testhd2_f008004_s1307.jpg
Normal file
|
After Width: | Height: | Size: 235 KiB |
BIN
dataset_yolo/images/train/testhd2_f008526_s1167.jpg
Normal file
|
After Width: | Height: | Size: 252 KiB |
BIN
dataset_yolo/images/train/testhd2_f009048_s1165.jpg
Normal file
|
After Width: | Height: | Size: 268 KiB |
BIN
dataset_yolo/images/train/testhd2_f009570_s1661.jpg
Normal file
|
After Width: | Height: | Size: 250 KiB |
BIN
dataset_yolo/images/train/testhd2_f010788_s2001.jpg
Normal file
|
After Width: | Height: | Size: 257 KiB |
BIN
dataset_yolo/images/train/testhd2_f011310_s1307.jpg
Normal file
|
After Width: | Height: | Size: 250 KiB |
BIN
dataset_yolo/images/train/testhd2_f011832_s1219.jpg
Normal file
|
After Width: | Height: | Size: 304 KiB |
BIN
dataset_yolo/images/train/testhd2_f012354_s1318.jpg
Normal file
|
After Width: | Height: | Size: 349 KiB |
BIN
dataset_yolo/images/train/testhd2_f013398_s1856.jpg
Normal file
|
After Width: | Height: | Size: 256 KiB |
BIN
dataset_yolo/images/train/testhd2_f013920_s1830.jpg
Normal file
|
After Width: | Height: | Size: 237 KiB |
BIN
dataset_yolo/images/train/testhd2_f014442_s2191.jpg
Normal file
|
After Width: | Height: | Size: 273 KiB |
BIN
dataset_yolo/images/train/testhd2_f014964_s1402.jpg
Normal file
|
After Width: | Height: | Size: 228 KiB |
BIN
dataset_yolo/images/train/testhd2_f016008_s1424.jpg
Normal file
|
After Width: | Height: | Size: 299 KiB |
BIN
dataset_yolo/images/train/testhd2_f016530_s1153.jpg
Normal file
|
After Width: | Height: | Size: 280 KiB |
BIN
dataset_yolo/images/train/testhd2_f017052_s0719.jpg
Normal file
|
After Width: | Height: | Size: 237 KiB |
BIN
dataset_yolo/images/train/testhd2_f017748_s0986.jpg
Normal file
|
After Width: | Height: | Size: 244 KiB |
BIN
dataset_yolo/images/train/testhd2_f018792_s1435.jpg
Normal file
|
After Width: | Height: | Size: 261 KiB |
BIN
dataset_yolo/images/train/testhd2_f019314_s1231.jpg
Normal file
|
After Width: | Height: | Size: 227 KiB |
BIN
dataset_yolo/images/train/testhd2_f019836_s1049.jpg
Normal file
|
After Width: | Height: | Size: 260 KiB |
BIN
dataset_yolo/images/train/testhd2_f020358_s1742.jpg
Normal file
|
After Width: | Height: | Size: 340 KiB |
BIN
dataset_yolo/images/train/testhd_f000000_s0582.jpg
Normal file
|
After Width: | Height: | Size: 142 KiB |
BIN
dataset_yolo/images/train/testhd_f000543_s0574.jpg
Normal file
|
After Width: | Height: | Size: 183 KiB |
BIN
dataset_yolo/images/train/testhd_f001086_s0908.jpg
Normal file
|
After Width: | Height: | Size: 204 KiB |