Lire le flux d’une Webcam / Caméra / Vidéo avec OpenCV

OpenCV est une librairie de traitement d’image qui offre un bon éventail de fonctions intégrées et puissantes. Dans ce tutorial nous allons voir comment lire une vidéo, mais aussi comment récupérer le flux vidéo d’une caméra || webcam tout en analysant chaque commande pour bien vous faire comprendre leur utilité. Je vais par ce topic décortiquer chaque commande (dans un ordre logique). Pour le résultat final veuillez vous référer à la fin de la page !

Ouvrir le flux d’une vidéo / caméra

Avant de pouvoir lire un quelconque flux vidéo il faut déjà l’ouvrir. Définissez premièrement la variable qui va stocker ce flux :

CvCapture *capture;

Ouvrir une vidéo

Ouvrir une vidéo est chose relativement aisée. Par contre il se peut que vous ne puissiez pas ouvrir tout type de vidéo. Ceci peut entre autre varier selon la version d’OpenCV mais aussi selon les différentes librairies installées sur votre système d’exploitation.

capture = cvCreateFileCapture("/path/to/your/video/test.avi");

Ouvrir le flux d’une Webcam / Caméra

Avec un flux vidéo récupéré en temps réel les capacités d’OpenCV prennent tout leur sens. Que ce soit une webcam ou une caméra, il est possible de récupérer ce qu’elles voient. De manière générale il est facile de lire le flux d’une webcam. Si vous souhaitez utiliser une caméra analogique (non numérique) il vous faudra probablement utiliser un convertisseur pour pouvoir la brancher en USB sur votre ordinateur. Notez par ailleurs que selon ce convertisseur (Dazzle, Easy Cap etc) vous aurez très probablement besoin du driver approprié selon votre système d’exploitation.

capture = cvCreateCameraCapture( CV_CAP_ANY );
  • Le paramètre dans cvCreateCameraCapture() permet de définir quel flux vidéo récupérer. Généralement le CV_CAP_ANY permet de prendre le premier disponible (donc par exemple une webcam intégrée à votre ordinateur). Il se peut que cela ne marche pas tout le temps, donc si vous rencontrez un problème mettez 0 à la place ! Les valeurs diffèrent ensuite selon le port utilisé (usb, firewire). Pour plus d’information sur les valeurs disponibles, référez-vous au fichier highgui.h
  • Toujours dans la même optique, vous pouvez y indiquer un autre chiffre pour ne pas récupérer le premier flux vidéo (par exemple /dev/video0 sur Linux) mais un autre. Ainsi si vous avez une Webcam intégrée et une caméra branchée en USB, et que vous souhaitez récupérer le flux de cette dernière, indiquez 1 à la méthode.
LIRE AUSSI  Installer SVN sur Ubuntu : le paquet Subversion, le dépôt et le port 3690

Vérifier que le flux est bien ouvert

Il est possible qu’ouvrir le flux vidéo ne se passe pas comme prévu. Pour pallier à ce problème, il est fortement conseillé de réaliser une petite vérification sur la variable “capture”.

if (!capture) {

   printf("Ouverture du flux vidéo impossible !n");
   return 1;

}

Pour améliorer la vérification vous pourriez même retenter l’ouverture du flux X fois jusqu’à décider d’arrêter (pour éviter une boucle infinie). En effet dans certains cas, la webcam/caméra n’est pas détectée immédiatement. Si l’on ne laisse pas un petit intervalle de temps à l’ouverture, alors il faudrait lancer le programme plusieurs fois de suite jusqu’à ce qu’il ne fasse plus l’erreur.

Récupérer une image et l’afficher

Le principe du traitement vidéo est de procéder à une analyse du flux image par image. A chaque traitement d’image terminé vous affichez l’image résultante dans une fenêtre.

Créer une fenêtre

Ce qui est bien avec OpenCV c’est que la création d’une fenêtre ne change pas en fonction du système d’exploitation. Par ailleurs vous pouvez créer plusieurs fenêtres pour afficher dedans plusieurs résultats (images ou vidéos). Une fenêtre est définie par un nom :

cvNamedWindow("GeckoGeek Window", CV_WINDOW_AUTOSIZE);

Le flag “CV_WINDOW_AUTOSIZE” (qui est en fait un nombre : 0 ou 1) permet d’indiquer si la fenêtre doit s’adapter automatiquement ou non.

Récupérer une image

Une image est stockée dans une classe spécifique à OpenCV : IplImage. Donc quelque part dans votre code avant de commencer vous devez la définir :

IplImage *image;

Il existe deux façons de récupérer une image du flux vidéo. La première (et la plus utilisée) est la suivante :

image  = cvQueryFrame(capture);

Il faut indiquer en paramètre le flux vidéo à utiliser pour récupérer l’image. Cela devient vital dans le cas où vous utilisez plusieurs sources de vidéo !
L’autre possibilité pour lire l’image est d’utiliser deux méthodes séparées. La première permet de demander à OpenCV de récupérer une image du flux vidéo et de la stocker en mémoire. La méthode retourne 0 ou 1 en fonction du résultat.

cvGrabFrame(capture);

Ensuite il suffit de récupérer l’image dans la variable appropriée :

image = cvRetrieveFrame(capture);

Notez toutefois que c’est cette dernière méthode qui prend le plus de temps (5 à 10 fois plus que cvGrabFrame).

LIRE AUSSI  CSR, SSR ou SSG : quel frontend haute performance choisir selon le rendu, le bundle et l’hydratation ?

Afficher une image

Une fois l’image stockée dans une variable il suffit de l’afficher dans une fenêtre préalablement créée.

cvShowImage("GeckoGeek Window", image);

Notez qu’en général, avant d’afficher l’image, on effectue des traitements sur cette dernière : zoom, contraste, reconnaissances variées (faciale par exemple), etc. Prenez en compte que la communauté d’OpenCV offre de nombreux codes en exemple qu’il est conseillé de parcourir pour vous faire une idée des possibilités.

Boucler et temporiser

Pour récupérer les images petit à petit il vous faudra créer une boucle et faire une petite pause entre chaque image.

Faire une pause

Faire une pause dans OpenCV permet en même temps de récupérer une interaction clavier. Cela permet ainsi d’analyser la touche qui a subie une interaction et de procéder à certaines actions en conséquence. Notez que ce système peut malheureusement entrer en conflit selon votre programme. Par exemple si vous utilisez en plus une librairie graphique (comme QT) avec des champs texte, il vous faudra trouver une solution pour partager ces événements clavier.

key = cvWaitKey(10);

La commande cvWaitKey() attente X ms et renvoie l’interaction clavier (s’il y en a eu une).
Le temps d’attente varie en fonction de framerate que vous souhaitez imposer. Par contre vous ne pourrez pas aller au-delà de ce que propose votre caméra. Notez par ailleurs que mettre un temps d’attente trop court peut causer un freeze sur certaines versions de Linux. Mettez donc en général au moins 5 ms.

Faire une boucle !

Et enfin il vous faut assembler tous les aspects dont on a parlé ci-dessus pour lire et afficher la vidéo ! Ici nous nous basons sur l’interaction clavier pour arrêter la boucle while. Il existe d’autres moyens d’arrêter la boucle (comme se baser sur le retour de cvGrabFrame).

// Boucle tant que l'utilisateur n'appuie pas sur la touche q (ou Q)
while(key != 'q' && key != 'Q') {

   // On récupère une image
   image = cvQueryFrame(capture);

   // On affiche l'image dans une fenêtre
   cvShowImage("GeckoGeek Window", image);

   // On attend 10ms
   key = cvWaitKey(10);

}

Libérer la mémoire utilisée !

Etape très (très) importante, libérer toute la mémoire que vous avez utilisé en créant ces divers objets.

LIRE AUSSI  Clés immuables, get() et items() : maîtriser le dictionnaire Python sans KeyError

Libérer la fenêtre

Une seule fonction suffit à fermer toutes les fenêtres :

cvDestroyAllWindows();

Toutefois dans le cas où vous ne souhaiteriez que fermer une seule et unique fenêtre, vous pouvez utilisez cette dernière :

cvDestroyWindow("GeckoGeek Window");

Libérer la variable d’image !

Lorsque vous récupérez une image d’un flux vidéo vous n’avez pas besoin de la “libérer” dans la boucle while, ni même après. OpenCV gère ceci automatiquement et vous n’avez qu’à votre charge de désallouer une image créée par vos soins. Si vous veniez à le faire, pensez donc à faire ceci :

cvReleaseImage(&uneAutreImage);

Libérer la capture vidéo !

Et enfin, il vous faut libérer la capture vidéo (entre autre pour que la webcam/caméra ne soit plus utilisée par le programme).

cvReleaseCapture(&capture);

Tout en un

Voici l’ensemble du programme que je viens de décortiquer pour vous.

/*
 * Code written by Vinz (GeckoGeek.fr)
 */

#include 
#include "highgui.h"
#include "cv.h"

int main() {

	// Touche clavier
	char key;
	// Image
	 IplImage *image;
	// Capture vidéo
	CvCapture *capture;

	// Ouvrir le flux vidéo
	//capture = cvCreateFileCapture("/path/to/your/video/test.avi"); // chemin pour un fichier
	capture = cvCreateCameraCapture(CV_CAP_ANY);

	// Vérifier si l'ouverture du flux est ok
	if (!capture) {

	   printf("Ouverture du flux vidéo impossible !n");
	   return 1;

	}

	// Définition de la fenêtre
	cvNamedWindow("GeckoGeek Window", CV_WINDOW_AUTOSIZE);

	// Boucle tant que l'utilisateur n'appuie pas sur la touche q (ou Q)
	while(key != 'q' && key != 'Q') {

	   // On récupère une image
	   image = cvQueryFrame(capture);

	   // On affiche l'image dans une fenêtre
	   cvShowImage( "GeckoGeek Window", image);

	   // On attend 10ms
	   key = cvWaitKey(10);

	}

	cvReleaseCapture(&capture);
	cvDestroyWindow("GeckoGeek Window");

	return 0;

}

Si vous avez une question ou si ce billet vous a été utile, n’hésitez pas à laisser un commentaire pour nous le faire savoir ! Bientôt des tutoriaux un peu plus compliqués :-]

Partager cet article

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Retour en haut