8 Commits

Author SHA1 Message Date
administrator
aa17d7ffd3 Add DearPyGUI observer/server UI and demo launcher 2026-06-04 08:57:36 +02:00
administrator
e86c05a885 External observer with OpenCV UI baseline 2026-06-03 15:28:27 +02:00
administrator
f728524ee6 pipeline in linea single thread 2026-05-19 08:52:44 +02:00
administrator
98b43ce903 aggiorna video test tagliato 2026-05-17 15:00:25 +02:00
administrator
1186c3bb35 configura fps preview e yolo 2026-05-16 09:10:48 +02:00
administrator
16458d98e9 aggiunta gui 2026-05-15 20:39:06 +02:00
administrator
8a8bea1211 Milestone navigation simulator with config 2026-05-15 18:40:07 +02:00
administrator
a92dcf2659 Milestone YOLO11 navigation planning baseline 2026-05-15 16:52:54 +02:00
270 changed files with 10763 additions and 65 deletions

6
.gitignore vendored
View File

@@ -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*/

View 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.

View 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.

View 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
```

View 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.

View 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.

View 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.

View 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.

View 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.

View 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.

View 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`.

View 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)
```

View 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.

View 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`.

View 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"
```

View 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.

View 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.

View 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.

View 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.

View 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.

View 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.

View 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.

View 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.

View 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.

View 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.

View 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.

View 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.

View 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.

View 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.

View 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.

View 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.

View 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.

View 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.

View 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.

View 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.

View 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.

View 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.

View 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

View 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
```

View 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.

View 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.

View 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
View File

@@ -0,0 +1,2 @@
gaylord
etichetta

13
dataset_yolo/README.md Normal file
View 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
View File

@@ -0,0 +1,2 @@
gaylord
etichetta

7
dataset_yolo/data.yaml Normal file
View File

@@ -0,0 +1,7 @@
path: C:/devel/flywms/dataset_yolo
train: images/train
val: images/val
names:
0: gaylord
1: etichetta

View 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"
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 314 KiB

View 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"
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 269 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 298 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 266 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 279 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 268 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

View File

@@ -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"
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 299 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 268 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 289 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 272 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

View File

@@ -0,0 +1,2 @@
gaylord
etichetta

Binary file not shown.

After

Width:  |  Height:  |  Size: 147 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 161 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 211 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 365 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 336 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 318 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 272 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 279 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 316 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 356 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 359 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 343 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 235 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 252 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 268 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 250 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 257 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 250 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 304 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 349 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 256 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 237 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 273 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 228 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 299 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 280 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 237 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 244 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 261 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 227 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 260 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 340 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 142 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 183 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 204 KiB

Some files were not shown because too many files have changed in this diff Show More