Non farò più il babysitter di Claude Code
Applicare la Computer Vision a riprese amatoriali per mappare le partite in 2D
C’era un progetto che da un po’ mi frullava per la testa. L’idea era quella di sviluppare un modello in grado di trasformare delle riprese amatoriali di partite di futsal (calcio a 5) in modo da ottenerne una rappresentazione in 2D.
Il video amatoriale è un caso difficile perché viola sistematicamente ogni assunzione ragionevole che faresti su un video “pulito”. La camera segue il gioco a mano libera, quindi l’inquadratura cambia continuamente e una calibrazione statica del campo non basta. L’angolazione è bassa, il che significa giocatori che si sovrappongono e le linee del campo spariscono in prospettiva. La luce artificiale crea riflessi e zone di sovraesposizione che rendono difficile la calibrazione del modello. Nei video di scarsa qualità, il pallone in movimento diventa un blob indistinguibile. E nell’inquadratura finiscono inevitabilmente anche persone da escludere: allenatori a bordo campo, riserve in panchina, spettatori fuori dal campo.
I modelli e i dataset più maturi per il tracking sportivo sono stati sviluppati per il calcio a 11, ripreso dall’alto in stadi con infrastruttura professionale. Il futsal è sostanzialmente terra di nessuno dal punto di vista dei dati.
Insomma, una bella sfida, ma quale occasione migliore per mettere alla prova il tanto decantato Claude Code?
Take #1: Futsal
Il primo passo è stato usare YOLOv8n, un modello di object detection, ossia un sistema che impara a riconoscere e localizzare oggetti in un’immagine, a sua volta pre-addestrato su COCO, un dataset generico con decine di categorie di oggetti comuni. Il modello analizza il video fotogramma per fotogramma e restituisce le posizioni di tutto ciò che riconosce. Per i giocatori funziona: su 460 frame produce circa 4.370 rilevamenti. Per la palla è un disastro: 14 rilevamenti totali. Il motivo è semplice: un pallone da calcio a 5 in movimento è piccolo, sfocato, e un modello addestrato su immagini generiche di internet non è attrezzato per trovarlo.
Il passo successivo è stato calcolare la matrice di omografia: una trasformazione matematica che mette in corrispondenza ogni pixel del video con una coordinata reale sul campo. In pratica, è ciò che permette di dire “questo pixel corrisponde a quel punto del campo” e quindi di proiettare le posizioni dei giocatori sulla mappa 2D. L’approccio automatico, che consiste nell’isolare le linee bianche del campo tramite filtri sul colore (HSV masking), trovare le rette con un algoritmo classico di computer vision (HoughLinesP) e stimare la trasformazione con RANSAC, ha prodotto zero risultati validi su 83 frame campionati. La luce artificiale e la bassa qualità delle riprese a disposizione rendevano le linee irriconoscibili per i parametri del filtro. La soluzione è stata un’annotazione manuale: ho costruito un tool interattivo in cui si cliccano manualmente i punti corrispondenti tra il template 2D del campo e il frame estratto dal video.
Ho annotato 28 fotogrammi chiave, poi propagato la calibrazione agli altri frame tracciando le feature visive tra un frame e il successivo (ORB feature tracking).
C’era però un problema aggiuntivo: la videocamera si muove di continuo seguendo il gioco, quindi una singola matrice statica non basta. In altre parole, serviva collegare i pallini sparsi frame per frame in traiettorie continue: un giocatore che si muove deve mantenere la stessa identità nel tempo, non diventare un oggetto nuovo ad ogni fotogramma. Per questo si usa un tracker, in questo caso OC-SORT: un algoritmo che combina la posizione attuale dei rilevamenti con una previsione del movimento per mantenere gli ID coerenti nel tempo. Il risultato è stato 70 ID distinti per circa 10-12 giocatori reali. Il tracker perdeva continuamente il filo a causa delle occlusioni e dei movimenti rapidi tipici del futsal (quantomeno quando non gioco io).
Per ricondurre questi 70 frammenti a identità stabili ho usato OSNet, un modello specializzato nella re-identification, cioè nel riconoscere la stessa persona in momenti e inquadrature diverse, basandosi sull’aspetto visivo. Il modello produce per ogni frammento di traccia un vettore numerico (embedding) che descrive l’aspetto del giocatore. Questi vettori vengono poi confrontati tra loro per capire quali frammenti appartengono alla stessa persona, usando il colore della maglia come ulteriore criterio di raggruppamento. Il risultato: da 54 frammenti validi si arriva a 3 identità. Una riduzione del 94% che è però troppo aggressiva, per cui molti giocatori reali finiscono fusi in un unico ID perché le maglie si assomigliano e i frammenti sono troppo brevi per distinguerli con sicurezza.
La minimap finale doveva affiancare la clip originale, ma produrla ha richiesto di risolvere una serie di problemi: persone fuori dal campo proiettate dentro per via di errori nell'omografia, palla che sfarfalla per i rilevamenti intermittenti, e una dipendenza dall'annotazione manuale dei punti chiave del campo.
A un certo punto ho dovuto ammettere che il problema non era risolvibile nel breve con gli strumenti che avevo, e che anche con riprese migliori la situazione non sarebbe migliorata significativamente. Servivano dati annotati che non esistevano, modelli che nessuno aveva addestrato su quel dominio, e soprattutto la pazienza che ho perso da anni.
Take #2: Tennis
Ho deciso di cambiare strada e provare con il tennis, un dominio più controllato, con riprese stabili e dove almeno avrei potuto verificare il resto della pipeline.
Per il rilevamento dei giocatori ho usato ancora YOLOv8n, che ha portato a risultati incoraggianti: 20.580 rilevamenti, contro i 4.370 del calcio a 5.
Per la palla ho abbandonato del tutto YOLO. La pallina da tennis ha delle caratteristiche (gialla, piccola, sempre in movimento) che si prestano a un approccio più diretto: si calcola la differenza tra frame consecutivi per isolare i pixel in movimento, si filtra per colore con una maschera HSV sul range giallo-verde, si scartano le forme che non assomigliano a una pallina (troppo grandi, troppo allungate, non abbastanza circolari), e si escludono i candidati che cadono all’interno delle sagome dei giocatori (Alcaraz doveva proprio indossare dei pantaloncini giallo limone?). Nessuna rete neurale, e palla rilevata in 819 frame su 1.341, contro i 14 del calcio a 5.
La registrazione del campo è stata la conferma più netta che il problema precedente era di dominio, non di metodo. Il campo è fisso, le linee bianche sono ad alto contrasto, la luce è stabile. Queste condizioni rendevano l’annotazione molto più rapida e precisa. Il metodo era lo stesso rispetto al futsal, ossia la selezione manuale dei punti chiave del campo, con la differenza che questa volta ha funzionato bene al primo tentativo, senza dover gestire il pan della camera o propagare la calibrazione frame per frame.
Il tracking con OC-SORT ha prodotto 54 ID come nel calcio a 5, ma questa volta ricondurli a identità stabili è stato molto più semplice: con solo 2 giocatori in campo, è bastato filtrare i track troppo corti o troppo statici e clusterizzare per colore maglia con K-means e k=2, senza bisogno di OSNet. Sulla palla ho aggiunto un filtro di Kalman, un algoritmo che combina i rilevamenti osservati con un modello predittivo del movimento per stimare la posizione anche nei frame in cui la palla non viene rilevata, riempiendo i gap fino a 15 frame consecutivi e ottenendo una traiettoria continua.
Il risultato finale, benché decisamente migliore rispetto al futsal, ha presentato diversi problemi. La pallina sfarfalla in modo fastidioso ogni volta che rallenta o rimbalza, perché senza movimento non c’è segnale e il rilevamento semplicemente scompare. La detection dei giocatori crolla senza preavviso in alcune zone del campo, rendendo le traiettorie discontinue e poco affidabili. E il tentativo di plottare la traiettoria della palla in 2D si è rivelato sostanzialmente inutile: la pallina da tennis viaggia in tre dimensioni, rimbalza, si alza da terra, per cui l’omografia, che assume per definizione che tutto giaccia sullo stesso piano, produce distorsioni talmente grandi da rendere la proiezione priva di senso. Un problema che nel futsal non si era nemmeno posto, e che nel tennis è invece centrale.
Il babysitter di Claude Code
Il punto di partenza è stata la pubblicazione SoccerNet Game State Reconstruction: End-to-End Athlete Tracking and Identification on a Minimap* di Somers et al., un lavoro che formalizza esattamente il problema che volevo affrontare, costruendo una pipeline completa per ricostruire le posizioni e le identità dei giocatori su una minimap a partire da video broadcast di calcio a 11.
Il progetto mi spaventava, ma si è rivelata l’occasione giusta per sperimentare la fantomatica Agentic AI. Il mio approccio è stato quello di scegliere personalmente l’architettura, gli strumenti e le clip su cui applicare i modelli. Ho inoltre descritto i problemi man mano che emergevano, ad esempio la minimap confusionaria, l’omografia del campo sballata, la pallina che spariva e riappariva, e ho annotato manualmente i keypoint del campo nei frame video. Ho delegato a Claude Code la scrittura del codice, la scelta dei parametri e il debug.
L’esperienza? Frustrante come lo è sempre quando si ha a che fare con l’intelligenza artificiale per più di 5 minuti. Adesso si chiama Agentic AI, perché è in grado di pianificare, “ragionare” e valutare iterativamente i risultati, ma quello che c’è sotto sono gli stessi modelli di prima, ossia i modelli che non sanno contare quante lettere “A” ci sono in una parola, ma a cui affidiamo ciecamente le nostre vite (e tristemente le vite degli altri a quanto pare). Sono gli stessi di prima, ma messi in sequenza uno dopo l’altro, in modo da sollevarci anche del peso di valutare la strada che stanno prendendo, e rendendoci ancor meno coscienti di quello che sta avvenendo dietro le quinte. Quando qualcosa non va, devi sperare che l’agente sia in grado di risolvere il problema da solo, perché tu ormai sei fuorigioco (per rimanere in tema): la codebase in pochi secondi diventa un labirinto pieno di immondizia non richiesta, impossibile da comprendere e debuggare, e perciò non puoi che affidarti al modello ancora di più, fino a che tutto non diventa incomprensibile e bisogna ricominciare da capo.
Ma questo è la direzione che ha preso questo mondo, e il singolo non può resistere, perché rischia di rimanere indietro (oltre che passare per un retrogrado, noioso e bacchettone). Non ci si può fermare, perché bisogna fare sempre di più. Tutto, malissimo e subito.




