Reconnaissance faciale – TP1 : La vidéo en python

Affichage des performances

Création de la classe

Alors ce qui serait bien maintenant, c’est qu’on ait une idée des performances. Pour ça, on va créer une classe que l’on va appeler PerfImage. On crée donc un nouveau fichier python. Dans spyder : Fichier -> Nouveau fichier . Il s’appelle certainement sanstitre0.py . Et on va enregistrer ce fichier dans notre répertoire outils sous le nom de perfImage.py .

Si tu es consciencieux, tu auras pris soin de respecter les majuscules et les minuscules. En général, les classes commencent toujours par une majuscule. Même si ça marcherait très bien avec une minuscule. Mais c’est une règle implicite qui simplifie grandement la lecture du code.

Donc si tu vas dans le répertoire outils depuis l’explorateur de fichier dans spyder (à droite) tu devrais avoir ça :

Si tu as besoin de naviguer à travers les fichiers, n’hésite pas à utiliser les petites flèches que je t’ai délicatement entourées en rouge. Si tu es complètement perdu, tu peux aussi retourner sur le script tp_reco_face.py et cliquer sur “Définir le répertoire de travail” comme nous l’avons vu dans l’article précédent.

Le fonctionnement va être basique. On va créer une méthode (une méthode est une fonction qui appartient à une classe) qui va s’appeler textePerf. En fait, cette méthode va renvoyer une chaine de caractère à chaque fois qu’elle sera appelée et contenant les éléments suivant :

  • La fréquence en chronométrant le temps entre 2 appels
  • Le taux d’utilisation du cpu à l’instant t
  • La consommation totale de la mémoire

Je vais quand même expliquer un peu plus cette notion de fréquence. en fait, nous allons appeler cette méthode à chaque fois qu’on va afficher une image. Donc si je connais le temps qui s’est écoulé entre 2 images, je peux en déduire une estimation du nombre d’images par seconde. Par exemple, si ma boucle appelle la méthode toutes les 10 ms, sachant qu’il y a 100 fois 10ms pour faire une seconde, j’aurais donc un affichage de 100 images par seconde.

Alors, soyons précis tout de suite. Cela ne voudra absolument pas dire que notre caméra envoie 100 images par seconde ! Ça voudra juste dire que notre boucle affiche 100 images par seconde. Mais si la caméra n’envoie que 30 images par seconde, alors notre boucle traitera environ 3 fois de suite la même image. Ça donnerait un truc du genre :

Donc la fréquence FPS renvoyée ne sera pas la fréquence d’image envoyée par la caméra mais bel et bien la fréquence d’affichage de notre fenêtre.

Allez, retourne sur le script perfImage.py , on va commencer.

Déjà, on déclare ce dont on va avoir besoin

## On importe les librairies dont on va avoir besoin
import psutil
import time

psutil va nous servir pour récupérer les infos cpu et mémoire. time, bah pour récupérer le temps exact à instant t

On crée notre classe. Rapide rappel, une classe c’est comme un modèle ou par exemple le plan d’une maison. Depuis ce modèle de maison, on va pouvoir construire tout un tas de maisons. Les maisons construites, on appelle ça un objet.

On initialise les attributs. Les attributs pour rappel sont des variables qui vivront avec notre objet. SI j’ai 2 objets créés depuis la même classe, les attributs seront propres à chaque objet et certainement avec des valeurs différentes.

class PerfImage:
    def __init__(self):
        ## On déclare proprement les attributs que l'on va utiliser dans notre
        ## classe. 
        self.__tempsPrecedent = 0

On déclare notre méthode et on récupère le temps exact en cet instant

    def textePerf(self):
        ## On prend le temps exact à l'instant t 
        tempsActuel = time.time()

Ensuite on récupère la fréquence grâce au temps écoulé entre 2 appels.

        ## Petite sécurité histoire d'éviter la division par 0 lors du premier
        ## appel
        if self.__tempsPrecedent != 0:

            ## On récupère le temps écoulé entre le temps actuel t et le temps 
            ## lors du précédent appel
            tempsEcoule = tempsActuel - self.__tempsPrecedent

            ## Tu peux décommenter la ligne ci dessous si tu souhaites voir
            ## le temps écoulé entre 2 appels
            print("Temps écoulé : {:2.2f} - FPS : {:2.0f}".format(tempsEcoule, fps))        

            ## On calcul notre fréquence d'image affichée par seconde
            fps = 1 / (tempsEcoule)
        else:
            fps = 0

Afin d’éviter la division par zéro et lever une erreur bêtement au premier appel, on se met une sécurité. Au premier appel donc, le nombre de fps renvoyé dans notre texte sera 0. Mais rassure-toi, ça ira tellement vite que tu n’auras pas le temps de le voir !

J’ai rajouté aussi un petit affichage du temps écoulé histoire de constater un petit truc rigolo. Tu pourras le commenter à nouveau après.

Ensuite on récupère le pourcentage d’utilisation du cpu et la quantité de mémoire utilisée.

        ## on récupère le pourcentage d'utilisation du cpu
        cpu = psutil.cpu_percent()
        
        ## On récupère la quantité de mémoire total utilisée
        mem = (psutil.virtual_memory().used)/1024/1024/1024

Si on veut pouvoir calculer le temps écoulé, il faut bien faire la soustraction entre le temps exact du précédent appel et l’appel en cours. Donc, pour le tour suivant, le temps précédent correspond au temps actuel de cette boucle. Tu me suis ?

du coup, ça donne ça

        ## On en profite pour affecter le temps actuel à notre attribut 
        ## __tempsPrecedent. Comme ça, ce sera prêt pour la prochaine
        ## exécution         
        self.__tempsPrecedent = tempsActuel

Il nous reste plus qu’à construire notre belle ligne contenant les infos

        ## On prépare notre chaine de caractère contenant les infos
        self.__texte = 'FPS: {:2.1f} - CPU: {:2.0f}% - MEM: {:2.2f}Go'.format(fps,cpu,mem)

Et on renvoie tout ça

        ## On retourne notre chaine de caractère là où ça a été demandé
        return self.__texte

Ajout du texte des performances dans l’image

Il nous reste plus qu’à intégrer ça dans notre script d’affichage de flux vidéo

## On importe CV2 et notre nouvelle classe
import cv2
import outils.perfImage as perfImage

On récupère notre ligne contenant les infos et on l’ajoute à l’image grâce à cv2.putText.

    ## on s'assurer qu'aucune erreur n'a été rencontrée
    if valeurRetour:
        
        ## On récupère notre texte avec les performances
        textePerf = monPerfImage.textePerf()
        
        ## On ajoute notre ligne à l'image
        cv2.putText(imageWebcam, textePerf, (10, 15),
                cv2.FONT_HERSHEY_SIMPLEX , 0.5, (0, 0, 0), thickness=2, lineType=1)
                
        ## On affiche l'image 
        cv2.imshow('Image de la webcam', imageWebcam)        

Je n’ai pas remis tout le script car si tu as bien tout suivi le TP, tu sauras apporter les modifications ci-dessus 🙂

Un petit F5 pour lancer notre script et OOOOOooooohh ! Une ligne est apparue en haut de l’image avec les infos.

Bon, par contre, la valeur des fps varie quand même vachement… Voici ce que j’ai à la sortie de la console :

Temps écoulé : 0.01 - FPS : 91
Temps écoulé : 0.05 - FPS : 19
Temps écoulé : 0.01 - FPS : 91
Temps écoulé : 0.05 - FPS : 19
Temps écoulé : 0.06 - FPS : 16
Temps écoulé : 0.01 - FPS : 91
Temps écoulé : 0.07 - FPS : 14

A quoi ça pourrait être dû ? On en reparlera tout à l’heure, mais si tu es malin, tu verras que j’ai déjà donné une piste un peu plus haut 😉

Comment optimiser ça ? …hmmm… L’idéal en fait serait de prendre la moyenne des temps écoulés et le nombre d’image lors de la dernière seconde par exemple. C’est pas mal ça comme idée.

2 Comments

  1. Bonjour, j’ai essayé de rentrer le code mais lorsque je dois installer le module outils, je tape pip install outils, je redémarre le kernel mais après, spyder me dit:”No module named ‘outils'”. Quelqu’un saurait ce que je devrais faire?

    • Bonjour Jeremy,

      Effectivement, je ne vois pas la trace du fichier outils.py dans l’article.
      Essaye de remplacer outils.perfImage as perfImage par perfImage
      Cela dépend de la où tu as mis la classe perfImage.

      Ced

Poster un Commentaire

Votre adresse de messagerie ne sera pas publiée.


*


Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.