GeckoGeek.fr

Paradigme d'un lézard

Lundi 22 Octobre 2018

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

Par Vinz le 14/03/2010 dans Programmation | 64 commentaires

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.

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).

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.

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 <stdio.h>
#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 :-]

Commentaires (64)
  1. nopasaran le 8 Aug 2013 à 07:29

    @antho… il faut que tu renseignes correctement les références d’include et de linkage… (de mémoire mais cela fait longtemps que je ne développe plus sous windobe …. tu trouveras cela au niveau des propriétés du projet.)…
    Si tu cherches sur les internets tu trouveras un tuto la dessus.

  2. InspiracionV le 16 Sep 2013 à 23:33

    J’ai acheté un boitier d’acquisition Video USB, mis lorsque je le connecte eet que je lance mon programme avec OpenCv j’obtiens un bsod (bluescreen). Y a t il un moyen de remedier a cela ?

  3. abdessamad le 2 Dec 2013 à 22:42

    bonjour
    j’ai n problème qand je lance ton programme il n’y a qu’une fenêtre qui s’ouvre je ne sais pas pourquoi
    j’utilise opencv 2.4.7 sous microsoft visual studio 2013 sous windows

  4. KM le 10 Jan 2014 à 11:15

    Bonjour,

    Sais-tu comment on ouvre le flux d’une webcam (Opencv) dans une fenêtre Qt?
    Merci

  5. reka le 1 Feb 2014 à 10:53

    j’ai un projet concernant un robot guidé qui a le rôle de récupérer une vidéo dans une conférence et il va la diffuser en temps réelle
    svp est ce que je peux utiliser les onctions ci dessus de la récupération de vidéo
    et aidez moi comment il va la diffuser en temps réelle?

  6. refka le 1 Feb 2014 à 11:01

    j’ai un projet concernant un robot guidé qui a le rôle de récupérer une vidéo dans une conférence et il va la diffuser en temps réelle
    svp est ce que je peux utiliser les onctions ci dessus de la récupération de vidéo
    et aidez moi comment il va la diffuser en temps réelle?

  7. Akimiru le 15 Apr 2014 à 16:04

    Salut, déjà bravo pour le tuto.
    Maintenant dis moi ? Ce tuto marche pour les utilisateur de Python ?

    Moi j’utilise les codes suivant

    import cv2.cv as cv
    ma_camera=cv.CaptureFromCAM(0)
    ma_frame = cv.QueryFrame(ma_caméra)
    cv.NamedWindow(“Test_Webcam”)

    Au fur et à mesure que je tape le code j’ai la cam qui s’allume et la fênetre qui s’ouvre mais il n’y a aucune video qui s’affiche.

  8. pako le 18 Mar 2015 à 11:39

    super le code! facilitation et bonne suite.
    je suis un projet de comptage d’objet;
    comment peut puis je faire en sorte que parlant de distance ou sera la camera et de la largueur de l’objet que ce programme puis comptabilise les pixel et me donné le nombre d’objets que la camera a totaliser?

  9. safaa le 7 Apr 2016 à 10:20

    Merci pour ce tuto! Très clair 🙂

  10. samu le 9 May 2016 à 15:11

    bonjour d’abort merci pour ce tuto je voudrai savoir comment recuperer une image de la video comment insererer “”””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);
    dans le programme.
    merci

  11. momo le 10 May 2016 à 15:21

    Bonjour et merci pour ce tuto
    Toutefois je rencontre un problème, Ma fenêtre s’ouvre bien, je peux choisir ma webcam (1.3M HD webcam) mais dès que je clic “ok”, la fenêtre se ferme et me sort du debuggage et me dit que le programme s’est arreter avec le code 1. Merci à ceux qui me guideront sur une solution pour enfin recevoir mon flux video 🙂

  12. Legallium le 14 Jun 2016 à 10:24

    Bonjour
    merci pour le tuto.
    Il est vraiment explicite

  13. Gachengo le 5 Nov 2016 à 04:17

    vraiment un cours !

  14. lyra le 9 Dec 2016 à 11:42

    comment faire si on veut le passer sur android ? genre choisir la camera de la tablette android ?


Laisser un commentaire