[Tutorial OpenCV] “Ball Tracker” con Filtro di Kalman

Kalman Tracking and OpenCV
Kalman Tracking and OpenCV
Kalman Tracking and OpenCV

Tempo fa ho pubblicato su YouTube un video di un “semplice” software in grado di identificare una pallina blu su un tavolo e di inseguirne i movimenti stimando la sua posizione anche in caso di occlusione. Il video, riproposto qui di seguito, ha riscontrato molto successo e ha superato le 5000 visite. In tantissimi mi hanno chiesto un tutorial o il codice sorgente… il codice sorgente ha girato il mondo, ora è arrivato il momento di scrivere il tutorial.

Il codice sorgente che ho utilizzato per realizzare il video è il seguente:

Il codice è calibrato in modo da riconoscere e inseguire una pallina blu. Potete modificare il colore semplicemente cambiando i valori di tinta (HUE) “MIN_H_BLUE” and “MAX_H_BLUE” all’inizio del codice sorgente. Sebbene il codice è molto breve, la teoria che vi è nascosta è molto complicata è richiede delle conoscenze matematiche di alto livello. Il tracking della pallina blu sfrutta quello che è noto in letteratura come “Filtro di Kalman“, che è uno “Stimatore asintotico dello stato del sistema”, cioè è uno strumento matematico che permette di stimare la futura posizione dell’oggetto che stiamo “inseguendo”, utilizzando il modello cinematico dell’oggetto e la sua “storia”. La pagina di Wikipedia dedicata al Filtro di Kalman ne da una spiegazione molto completa, anche se non molto facile da comprendere. Semplicemente si può dire che un filtro di Kalman è realizzato in due fasi: STIMA (o PREDIZIONE) e AGGIORNAMENTO. La fase di STIMA permette di predirre la posizione dell’oggetto inseguito conoscendone la storia, cioè la velocità con cui si è mosso in passato e conoscendo le equazioni che ne controllano il moto. La stima è corretta ogni qualvolta che è disponibile una misura dello stato del sistema (posizione, velocità, ecc), questa correzione realizza la fase di AGGIORNAMENTO. Purtroppo la misura dello stato non è “certa”, ogni misura si porta dietro degli errori, per questo le due fasi di STIMA e AGGIORNAMENTO sono utilizzate in modo pesato considerando anche le informazioni sull’errore di misura e l’errore di predizione. Dopo questo breve tentativo di descrivere in “parole semplici” il Filtro di Kalman, possiamo passare alla spiegazione del codice. Innanzitutto definiamo lo stato del nostro sistema, cioè le informazioni relative alla “pallina” ad ogni istante “t“. Lo stato è definito dal vettore [x,y,v_x,v_y,w,h] (riga 45):

  • x, y: coordinate del baricentro della pallina all’interno dell’immagine
  • v_x, v_y: velocità di spostamento del baricentro (pixel/sec)
  • w, h: larghezza e altezza del bounding box della pallina

Definito il “vettore di stato” è necessario definire il vettore della “misura” [z_x,z_y,z_w,z_h] (riga 46):

  • z_x, z_y: coordinate del baricentro della pallina INDIVIDUATA nell’immagine corrente
  • z_w, z_h: dimensioni del bounding box della pallina INDIVIDUATA nell’immagine corrente

Una nota: il vettore della “misura” è utilizzato nella fase di AGGIORNAMENTO, fase che può essere realizzata solo se la pallina è individuata nell’immagine corrente, altrimenti (caso di OCCLUSIONE) si procede con la sola STIMA della sua posizione e dimensione. Nelle righe da 50 a 88 sono definite le MATRICI che implementano le fasi di misura e aggiornamento dello stato. La matrice A implementa il modello “lineare” del movimento della pallina. Per questo esempio è stata fatta l’assunzione FORTE che la pallina si muove in modo lineare, cosa purtroppo non vera per la maggior parte dei sistemi dinamici più complicati. La matrice H implementa la misura. La matrice Q è la matrice di “covarianza del processo“, un nome altisonante per identificare il “rumore” del sistema, cioè la stima dell’errore sullo stato della pallina ad ogni suo istante. Impostati i parametri del Filtro di Kalman possiamo avviare la nostra webcam e iniziare a tracciare i movimenti della pallina nel ciclo “while”. La variabile “dT” contiene la misura del tempo intercorso tra una fase e la successiva, tempo fondamentale per la predizione dello stato. Se la pallina è stata “identificata” in qualche istante precedente (found è TRUE e il “tracking” è in esecuzione, dalla riga 132 alla riga 156 realizziamo la fase di STIMA, utilizzando la funzione OpenCV “predict“. Dalla riga 158 alla riga 208 è eseguita la “classica” procedura di identificazione di un oggetto colorato: blurring, conversione HSV, filtraggio morfologico, thresholding e filtraggio per dimensioni e area. Dalla riga 231 alla riga 277 è eseguita la fase di AGGIORNAMENTO dello stato della pallina con le misure effettuate durante la fase di identificazione in particolare dalla riga 162 alla riga 266 la posizione e la dimensione iniziali sono impostate con quelle misurate la prima volta che la pallina è vista nel flusso video (found è FALSE). La variabile “found” indica che una pallina è stata precedentemente identificata e il tracking è in esecuzione. Se la pallina viene “persa di vista” per 10 frame consecutivi “found” diventa FALSE e il processo di tracking viene interrotto per essere ripreso ad una successiva identificazione. Nelle righe da 212 a 229 il risultato del tracking è messo a schermo. Il rettangolo verde mostra il bounding box della pallina “identificata” nella fase di misura. Il rettangolo rosso mostra invece lo STATO STIMATO dal filtro di Kalman. Interessante notare come lo stato della pallina coincida con lo stato reale fin quando la pallina si muove in “modo lineare”, ma soprattutto è interessante notare che la stima della posizione della pallina rimane valida anche quando la pallina scompare dietro la bottiglia e ricompare successivamente sull’altro lato. Il tutorial è concluso, OpenCV mette a disposizione di tutti un potente strumento matematico di non facile comprensione e implementazione quale è il Filtro di Kalman. Spero che questa breve guida possa aiutarvi nel capire come utilizzarlo nei vostri progetti. Per qualsiasi domanda potete scrivermi al mio solito indirizzo email: myzhar@robot-home.it

Il codice sorgente è disponibile su Github:

71 Responses

  1. lukey says:

    how to change the saturation value? i want to tracking white ball, thanks

  2. ha has says:

    Hello , how can i write code kalman filter + camshift in c++? can you show me how to use camshift to track the object and kalman filter to estimate the object ?

    • Myzhar says:

      Sure you can… you can use Kalman Filter with each “object detection algorithm”, simply replace the “color thresholding” part with your “camshift”

  3. Hi, Your post is awesome and help me. But i still do not understand with your value that you use in the code, like :
    kf.measurementMatrix.at(0) = 1.0f;
    kf.measurementMatrix.at(7) = 1.0f;
    kf.measurementMatrix.at(16) = 1.0f;
    kf.measurementMatrix.at(23) = 1.0f;

    kf.processNoiseCov.at(0) = 1e-2;
    kf.processNoiseCov.at(7) = 1e-2;
    kf.processNoiseCov.at(14) = 2.0f;
    kf.processNoiseCov.at(21) = 1.0f;
    kf.processNoiseCov.at(28) = 1e-2;
    kf.processNoiseCov.at(35) = 1e-2;
    why do you use those value ? You said at the previous post, that you get try and error. So you try and try till you get the correct value, is that so ?
    or Do you have any reference for me to learn ?
    Thank you very much for helping me

  4. Mebratu says:

    what are the lines 17 – 21 i’m getting error

    // Output
    #include

    // Vector
    #include

  5. chunshengwu says:

    so happy when I found your project, then I try to modify the color range to find my hand, but failed ,I tried the Scalar(20, 20, 16)and Scalar(150, 161, 208),and other range ,but it does not work ,what should I do ,hope your help, thank you.

  6. Hysis says:

    Thank you for this really well-explained tutorial, it really was a good start for my application and make development way easier for me. I hope every tutorial would be like this one.

  7. silva says:

    I’m beginner for this. So please, give your help to run this source code. What are the basic steps I want to do for run this code on NetBeans?

Lascia un Commento

This site uses cookies. Find out more about this site’s cookies.
%d bloggers like this: