Milestone YOLO11 navigation planning baseline

This commit is contained in:
administrator
2026-05-15 16:52:54 +02:00
parent 6a18517743
commit a92dcf2659
212 changed files with 1691 additions and 63 deletions

255
flywms_navigate_spec.rtf Normal file
View File

@@ -0,0 +1,255 @@
{\rtf1\ansi\deff0
{\fonttbl{\f0 Calibri;}{\f1 Consolas;}}
\fs24
\b Specifica flywms_navigate - navigazione geometrica e snapshot UDC\b0\par
\par
\b 1. Obiettivo\b0\par
Realizzare uno script separato, chiamato flywms_navigate.py, che usi solo la parte detector YOLO/Ultralytics per simulare la navigazione laterale di un drone davanti a una scaffalatura.\par
\par
Lo script non deve ancora fare OCR. Deve invece osservare i gaylord rilevati nel video, seguirli per alcuni frame, capire quando uno di essi si trova in posizione utile al centro della visuale, e generare un evento testuale equivalente a:\par
\f1
STOP\par
SCATTA_FOTO\par
ASSOCIA_POSIZIONE gaylord_N\par
RIPARTI_DESTRA\par
\f0
\par
In questa fase la posizione reale del drone viene simulata con una sequenza logica: gaylord 1, gaylord 2, gaylord 3, ecc.\par
\par
Il punto fondamentale e' separare la guida dal riconoscimento codice. Il detector lavora sul flusso video live e decide quando congelare uno snapshot. L'OCR lavorera' dopo, su uno snapshot gia' scelto, insieme alla posizione del drone registrata nel momento corretto.\par
\par
\b 2. Problema che vogliamo risolvere\b0\par
Nella pipeline attuale il video continua a scorrere mentre YOLO e OCR lavorano in asincrono. Questo va bene per misurare prestazioni, ma non va bene per la geometria della navigazione: quando arriva il risultato OCR, la posizione del drone potrebbe essere gia' cambiata.\par
\par
Per la navigazione non dobbiamo aspettare l'OCR per decidere dove siamo. Dobbiamo invece creare un pacchetto dati congelato nel momento in cui la geometria dice che il gaylord e' nella posizione giusta.\par
\par
\f1
NavigationSnapshot\par
snapshot_id\par
frame_id\par
timestamp_video\par
simulated_position = "gaylord N"\par
drone_pose_simulata\par
track_id\par
gaylord_bbox\par
gaylord_center\par
gaylord_area\par
frame_image\par
quality_score opzionale\par
\f0
\par
Questo oggetto potra' poi essere mandato all'OCR o al backend WMS senza perdere il legame con la posizione.\par
\par
\b 3. Concetto di tracking leggero\b0\par
Il tracking leggero serve a capire che un bbox rilevato nel frame corrente e' probabilmente lo stesso oggetto visto nei frame precedenti.\par
\par
Non serve ancora un tracker complesso come DeepSORT. Per questa prima versione basta associare i bbox di frame consecutivi usando regole geometriche semplici:\par
\par
- vicinanza del centro bbox;\par
- sovrapposizione tra bbox, cioe' IoU;\par
- continuita' della dimensione/area;\par
- coerenza del movimento orizzontale.\par
\par
Ogni gaylord seguito nel tempo diventa una traccia, cioe' una Track.\par
\par
\f1
Track\par
id\par
bbox corrente\par
center corrente\par
area corrente\par
bbox_history ultimi N frame\par
center_history ultimi N frame\par
area_history ultimi N frame\par
first_seen_frame\par
last_seen_frame\par
hits = quante volte e' stato visto\par
missed = quanti frame consecutivi non e' stato visto\par
state = entering | candidate | centered | snapshotted | exiting | lost\par
already_snapshotted = true/false\par
\f0
\par
Se in un frame YOLO rileva tre gaylord, il tracker mantiene tre tracce diverse. Una puo' uscire verso sinistra, una puo' essere al centro, una puo' entrare da destra.\par
\par
\b 4. Associazione detection-track\b0\par
Per ogni frame:\par
\par
1. YOLO produce una lista di bbox di classe gaylord.\par
2. Per ogni detection si cerca la Track esistente piu' compatibile.\par
3. La compatibilita' puo' essere calcolata con uno score:\par
\par
\f1
score = 0.7 * IoU(track.bbox, detection.bbox)\par
+ 0.3 * center_similarity(track.center, detection.center)\par
\f0
\par
4. Se lo score supera una soglia, la detection aggiorna quella Track.\par
5. Se nessuna Track e' compatibile, nasce una nuova Track.\par
6. Le Track non aggiornate aumentano missed.\par
7. Se missed supera una soglia, la Track diventa lost e viene rimossa.\par
\par
Per una prima implementazione possiamo anche partire con una regola piu' semplice: associare al track piu' vicino se la distanza tra centri e' minore di una certa percentuale della larghezza immagine. Poi raffiniamo con IoU.\par
\par
\b 5. Come decidere quando scattare\b0\par
Lo snapshot deve avvenire quando una Track rappresenta un gaylord utile, cioe' non tagliato, abbastanza grande, stabile e vicino al centro della visuale.\par
\par
Criteri iniziali proposti:\par
\par
- classe = gaylord;\par
- bbox non tagliato dai bordi immagine, con margine minimo configurabile;\par
- area bbox sopra una soglia minima;\par
- centro X bbox dentro una fascia centrale configurabile;\par
- centro Y dentro una fascia utile verticale configurabile;\par
- Track vista per almeno N frame;\par
- area non sta piu' crescendo in modo forte, oppure e' abbastanza stabile;\par
- la Track non ha gia' generato snapshot.\par
\par
La fascia centrale puo' essere visualizzata nella finestra debug con due linee verticali:\par
\par
\f1
center_x = frame_width / 2\par
tolerance = frame_width * 0.10\par
zona_centrale = [center_x - tolerance, center_x + tolerance]\par
\f0
\par
Quando il centro del gaylord entra in questa zona e i criteri sono soddisfatti, lo script genera:\par
\par
\f1
[NAV] track=4 centered frame=1234 pos=gaylord 7\par
[CMD] STOP\par
[CMD] SCATTA_FOTO snapshot_0007.jpg\par
[CMD] ASSOCIA_POSIZIONE gaylord 7\par
[CMD] RIPARTI_DESTRA delay=1.0s\par
\f0
\par
\b 6. Gestione del migliore snapshot\b0\par
Invece di scattare una sola immagine esattamente quando il centro entra nella fascia, possiamo raccogliere un piccolo gruppo di candidate snapshot per la stessa Track.\par
\par
Esempio:\par
\par
- quando la Track entra nella fascia centrale, si apre una finestra temporale di selezione;\par
- per i successivi K frame compatibili si calcola un punteggio;\par
- alla fine si salva solo il migliore.\par
\par
Punteggio iniziale:\par
\par
\f1
center_score = 1 - abs(bbox_center_x - frame_center_x) / center_tolerance\par
size_score = normalized_bbox_area\par
cut_score = 1 se bbox non tagliato, 0 se tagliato\par
sharpness_score = opzionale, non obbligatorio per la geometria\par
\par
snapshot_score = 0.50 * center_score\par
+ 0.30 * size_score\par
+ 0.20 * cut_score\par
\f0
\par
Per ora non usiamo OCR e non usiamo il filtro blur come vincolo primario, perche' il detector riesce a localizzare anche immagini leggermente sfocate. La nitidezza potra' entrare solo come criterio secondario per scegliere la foto migliore da passare all'OCR.\par
\par
\b 7. Pseudocodice generale\b0\par
\f1
inizializza YOLO Ultralytics\par
apri video o camera\par
inizializza tracker vuoto\par
inizializza snapshot_counter = 0\par
inizializza simulated_position_counter = 0\par
\par
per ogni frame:\par
frame_id += 1\par
detections = yolo.detect(frame)\par
gaylord_detections = filtra detections dove classe == "gaylord"\par
\par
tracker.update(gaylord_detections, frame_id)\par
\par
per ogni track attiva:\par
calcola center_x, center_y, area\par
calcola se bbox e' tagliato\par
calcola trend area: crescente, stabile, decrescente\par
calcola distanza dal centro frame\par
\par
se track e' eleggibile per snapshot:\par
aggiungi frame corrente ai candidati della track\par
aggiorna miglior candidato in base a snapshot_score\par
\par
se finestra candidati della track e' completa:\par
snapshot_counter += 1\par
simulated_position_counter += 1\par
salva miglior frame candidato su disco\par
crea NavigationSnapshot\par
stampa comandi:\par
STOP\par
SCATTA_FOTO\par
ASSOCIA_POSIZIONE gaylord simulated_position_counter\par
RIPARTI_DESTRA\par
marca track.already_snapshotted = true\par
\par
disegna debug:\par
bbox gaylord\par
track id\par
centro bbox\par
fascia centrale\par
stato track\par
ultimo comando generato\par
\par
mostra finestra flywms navigate\par
\f0
\par
\b 8. Stati della Track\b0\par
\f1
entering\par
\f0
La Track e' appena nata o sta entrando nella visuale. Area spesso crescente, centro lontano dal centro frame.\par
\par
\f1
candidate\par
\f0
La Track e' stabile, visibile da alcuni frame, non e' tagliata e si sta avvicinando alla zona centrale.\par
\par
\f1
centered\par
\f0
Il centro bbox e' dentro la fascia centrale. La Track puo' produrre candidati snapshot.\par
\par
\f1
snapshotted\par
\f0
La Track ha gia' prodotto uno snapshot. Non deve produrne altri, anche se resta visibile.\par
\par
\f1
exiting\par
\f0
Il gaylord si sta allontanando dal centro o sta uscendo dalla visuale.\par
\par
\f1
lost\par
\f0
La Track non viene piu' rilevata da troppi frame e viene rimossa.\par
\par
\b 9. Parametri iniziali suggeriti\b0\par
\f1
--center-tolerance-ratio 0.10\par
--usable-y-min-ratio 0.15\par
--usable-y-max-ratio 0.85\par
--min-track-hits 3\par
--max-track-missed 8\par
--min-gaylord-area-ratio 0.04\par
--edge-margin-ratio 0.02\par
--snapshot-window-frames 5\par
--snapshot-output-dir navigate_snapshots\par
\f0
\par
\b 10. Output atteso della prima versione\b0\par
La prima versione di flywms_navigate.py deve produrre:\par
\par
- una finestra video con bbox gaylord, track id e zona centrale;\par
- log testuali dei comandi simulati;\par
- immagini snapshot salvate su disco;\par
- un file log CSV o JSONL con frame_id, track_id, bbox, posizione simulata e nome file snapshot;\par
- nessuna dipendenza dall'OCR.\par
\par
\b 11. Nota sulla direzione di movimento\b0\par
Per ora assumiamo movimento da sinistra verso destra del drone rispetto alla scaffalatura, come nel ragionamento iniziale. Nel video, pero', gli oggetti possono apparire con moto apparente non perfettamente regolare per via della ripresa manuale. Per questo la prima versione deve basarsi soprattutto sul centro del bbox e sulla continuita' della Track, non su un modello cinematico troppo rigido.\par
\par
\b 12. Passo successivo dopo questa specifica\b0\par
Implementare flywms_navigate.py usando il detector Ultralytics gia' integrato in flywms.py, ma senza OCR. Quando la scelta degli snapshot sara' visivamente corretta, collegheremo ogni NavigationSnapshot alla pipeline OCR e poi alla logica WMS.\par
}