PjE: suivi des objets

<< | Liste des exercices | >>

Code source C++

Le listing complet du code source contenant la structure principale du programme C++ est disponible dans la page suivante. Les principales parties du code source sont explicitées ci-après.

Structure globale

Le code source a une structure similaire à ceux utilisés dans les semaines précédentes du PjE. Dans la fonction main (), on retrouve une boucle dans laquelle les images successives de la séquence sont acquises et traitées jusqu'à ce que l'utilisateur appuie sur la touche ESC.

// Boucler pour afficher les images
while (iKey != 27) {

    // Definir les variables locales
    CBlobResult sNewBlobs; // Blobs pour l'analyse de connexite

    ...

    // Envoyer la mise a jour TUIO
    psTuioServer->commitFrame ();
    // Copier les nouveaux blobs dans les anciens
    sOldBlobs = sNewBlobs;
    // Afficher l'image
    cvShowImage ("Acquisition", psImageCouleur);
    // Attendre 20 ms que l'utilisateur appuie sur une touche
    iKey = cvWaitKey (20);
}

Dans cette boucle, on trouve tout d'abord une série d'instructions qui sert à déterminer une liste de blobs dans l'image fournie par la caméra. Ces instructions correspondent globalement au code qui a été étudié lors de la séance précédente:

// Retourner l'image selon l'axe x
cvFlip (psImageBlobs, NULL, 1);
// Binariser l'image
cvThreshold (psImageBlobs, psImageBlobs, iSeuil, 255,
    CV_THRESH_BINARY);
// Extraire les blobs dans l'image binarisee
sNewBlobs = CBlobResult (psImageBlobs, NULL, 0);
// Eliminer les blobs de surface inférieure à un seuil
sNewBlobs.Filter (sNewBlobs, B_EXCLUDE, CBlobGetArea (),
    B_LESS, uiBlobMinSize);
sNewBlobs.Filter (sNewBlobs, B_EXCLUDE, CBlobGetArea (),
    B_GREATER, uiBlobMaxSize);
sNewBlobs.Filter (sNewBlobs, B_EXCLUDE, CBlobGetAxisRatio (),
    B_LESS, fBlobMinRatio);

Ensuite, on trouve une série de blocs de code qui visent à associer les blobs calculés pour l'image courante (stockés dans la variable sNewBlobs) et ceux calculés pour l'image précédente (stockés dans la variable sOldBlobs). C'est principalement cette partie du code source qui sera modifiée dans les différents exercices de cette sixième séance du PjE.

// Preparer la mise a jour de la liste TUIO
psTuioServer->initFrame (TuioTime::getSessionTime ());
iOldBlobs = sOldBlobs.GetNumBlobs ();
iNewBlobs = sNewBlobs.GetNumBlobs ();

// S'il n'y a pas de blobs dans la nouvelle liste et
// s'il y en avait dans l'ancienne...
if (!iNewBlobs && iOldBlobs)

...

/* ------------------------------------------------------
Liberer la memoire des distances
------------------------------------------------------ */
free (dDistance);

La boucle de traitement se termine par un affichage de l'image des blobs avec les étiquettes calculées lors de l'étape d'association. Il n'y a pas lieu de modifier cette partie du code:

// Generer une image couleur a partir de 3 plans niveaux de gris
cvMerge (psImageBlobs, psImageBlobs, psImageBlobs, NULL,
    psImageCouleur);
// Afficher les caracteristiques des blobs extraits
for (i = 0; i < sNewBlobs.GetNumBlobs (); i++) {

    // Definir les variables locales
    char pcEtiquette[6];

    // Acces au blob dans la liste
    psBlob = sNewBlobs.GetBlob (i);
    // Ellipse englobante et centre du blob
    sEllipse = psBlob->GetEllipse ();
    // Remplissage du blob avec une couleur propre
    psBlob->FillBlob (psImageCouleur, sColors[psBlob->GetID ()]);
    // Trace d'un point au centre du blob
    cvLine (psImageCouleur, cvPoint ( (int) sEllipse.center.x,
            (int) sEllipse.center.y),
        cvPoint ( (int) sEllipse.center.x, (int) sEllipse.center.y),
        CV_RGB (0, 150, 0), 4, 8, 0);
    // Etiquetage du blob avec son ID
    sprintf (pcEtiquette, "%d", psBlob->GetID ());
    cvPutText (psImageCouleur, pcEtiquette,
        cvPointFrom32f (sEllipse.center),
        &sFont, CV_RGB (255, 255, 255));
    // Affichage de l'ellipse des contours de chaque blob
    cvEllipse (psImageCouleur, cvPointFrom32f (sEllipse.center),
        cvSize ( (int) sEllipse.size.width, (int) sEllipse.size.height),
        sEllipse.angle, 0, 360, CV_RGB (255, 0, 0));
}