web-dev-qa-db-fra.com

Comment capturer une image fixe de la webcam sous Linux

J'essaie d'écrire un programme C++/Qt pour Linux, où je prends une photo en image fixe depuis une webcam, transforme une photo (recadrage, redimensionnement, etc.) et l'enregistre dans un fichier jpeg.

Mais j'ai rencontré des problèmes. Le principal problème est que le pilote linux standart UVC (classe de périphérique vidéo usb) ne prend actuellement pas en charge la capture d’images fixes: http://www.ideasonboard.org/uvc/ .

Il existe donc deux manières possibles de capturer une image fixe. Vous pouvez prendre une image du flux vidéo de la caméra ou prendre une photo distincte, comme une caméra numérique portable. La seconde façon n'est pas supportée par le pilote uvc sous linux, la première méthode est donc la seule. Mais le problème est que si vous voulez prendre une image du flux vidéo, la taille de la photo ne peut pas être supérieure à celle de la vidéo dans la fenêtre d'aperçu vidéo. Donc, si je veux prendre une photo de 2 mégapixels, je dois démarrer le flux vidéo au format 1600x1200, ce qui n’est pas très confortable (au moins, en Qt, la taille du flux vidéo dépend de la taille de la fenêtre de visualisation vidéo).

Je sais qu'il existe une vidéo pour l'API Linux 2, qui peut être utile dans cette tâche, mais je ne sais pas comment l'utiliser. J'apprends actuellement gstreamer, mais je ne sais pas comment faire ce dont j'ai besoin à l'aide de ces outils.

Donc, j'apprécierai toute aide. Je pense que ce n'est pas un problème difficile pour les personnes qui connaissent Linux, GStreamer, v4l2 API et d'autres choses spécifiques à Linux.

En passant, le programme ne sera utilisé qu'avec la caméra Web Logitech C270 HD.

Aidez-moi, s'il vous plaît. Je ne sais pas quelle API ou quel framework peut m'aider à faire cela. Peut-être que vous savez.

10
locomotion

Malheureusement, les appels C4V2 en mode opencv ne fonctionnaient pas pour la capture d’images fixes avec les appareils photo que j’avais essayés en utilisant le pilote UVC.

Pour résoudre le problème que je joue avec essayer d’accomplir cela avec du code c appelant directement c4v2.

J'ai joué avec l'exemple de code trouvé here . Il utilise la méthode d'extraction des images du flux vidéo. 

Vous pouvez le compiler avec:

gcc -O2 -Wall `pkg-config --cflags --libs libv4l2` filename.c -o filename

J'ai expérimenté 3 caméras logitech. Le meilleur du lot semble être le Logitech C910. Mais même cela pose des problèmes importants. 

Voici les problèmes que j'ai rencontrés en essayant d'accomplir la même tâche avec ce code.

Cela fonctionne à peu près chaque fois avec la largeur et la hauteur réglées sur 1920x1080. 

Quand j'interroge d'autres possibilités directement à partir de la ligne de commande en utilisant par exemple:

v4l2-ctl --list-formats-ext

et j’essaie quelques-unes des autres tailles "disponibles" plus petites qu’il bloque dans l’attente en attendant que l’appareil photo libère le tampon. 

Aussi, lorsque j'essaie de définir d'autres tailles directement à partir de la ligne de commande, en utilisant par exemple:

v4l2-ctl -v height=320 -v width=240 -v pixelformat=YUYV

Alors vérifiez avec 

v4l2-ctl -V

Je trouve que cela retourne le bon format de pixel mais souvent pas la bonne taille. 

Apparemment, cette caméra répertoriée sur le site UVC comme étant UVC et donc compatible v4l2 n’est pas à la hauteur. Je soupçonne que c'est tout aussi mauvais pour les autres caméras. Les deux autres que j'ai essayés étaient également répertoriés comme compatibles sur le site mais avaient des problèmes plus graves.

J'ai fait quelques tests supplémentaires sur le Logitech C910 après avoir posté ceci. Je pensais publier les résultats au cas où cela aiderait quelqu'un d'autre.

J'ai écrit un script pour tester le code de capture v4l2 mentionné ci-dessus sur tous les formats que la caméra prétend prendre en charge lorsqu'elle est interrogée avec v4l2. Voici les résultats: 

640x480 => Hangs on clearing buffer
160x120 => Works
176x144 => Works
320x176 => Works
320x240 => Works
432x240 => Works
352x288 => Works
544x288 => Works
640x360 =>  Works
752x416 => Hangs on clearing buffer
800x448 => Hangs on clearing buffer
864x480 => Works
960x544 => Works
1024x576 => Works
800x600 => Works
1184x656 => Works
960x720 => Works
1280x720 => Works
1392x768 => Works
1504x832 => Works
1600x896 => Works
1280x960 => Works
1712x960 => Works
1792x1008 => Works
1920x1080 => Works
1600x1200 => Works
2048x1536 => Works
2592x1944 => Hangs on clearing buffer.

Il s’avère que le réglage par défaut de 640x480 ne fonctionne pas et c’est ce qui m’a piégé, ainsi que la plupart des autres personnes qui ont posté sur des forums de discussion. 

Puisqu'il saisit une image vidéo, la première image qu'il saisit au démarrage peut avoir une exposition incorrecte (souvent noire ou proche de celle-ci). Je pense que c’est parce que, comme elle est utilisée comme caméra vidéo, elle ajuste l’exposition au fur et à mesure et ne se soucie pas des premières images. Je crois que cela m'a aussi piégé, ainsi que d'autres personnes qui voyaient le premier cadre comme noir ou presque noir et pensaient que c'était une sorte d'erreur. Les derniers cadres ont l'exposition correcte 

Il s’avère qu’opencv avec des enveloppes en python fonctionne bien avec cette caméra si vous évitez les mines antipersonnel énumérées ci-dessus et ignorez tous les messages d’erreur. Les messages d'erreur sont dus au fait que la caméra accepte les commandes v4l2 mais ne répond pas correctement. Donc, si vous définissez la largeur, celle-ci est correctement définie, mais sa largeur est incorrecte. 

Pour fonctionner sous opencv avec des wrappers Python, vous pouvez effectuer les opérations suivantes:

import cv2
import numpy

cap = cv2.VideoCapture(0)  #ignore the errors
cap.set(3, 960)        #Set the width important because the default will timeout
                       #ignore the error or false response
cap.set(4, 544)        #Set the height ignore the errors
r, frame = cap.read()
cv2.imwrite("test.jpg", frame)
3
Sani Elfishawy
**Download And Install 'mplayer'** 
mplayer -vo png -frames 1 tv://
2
M. Haris Azfar
mplayer -vo png -frames 1 tv://

peut donner une sortie d'écran vert car la caméra n'est pas encore prête. 

mplayer -vo png -frames 2 tv://

Vous pouvez essayer d'augmenter le nombre d'images et choisir un nombre à partir duquel l'appareil photo donnera les images correctes.

1
Dave

Qu'en est-il de ce programme?

#include<opencv2/opencv.hpp>
using namespace cv;
int main()
{
    VideoCapture webcam;
    webcam.open(0);
    Mat frame;
    char key;

    while(true)
    {
        webcam >> frame;
        imshow("My Webcam",frame);
        key = waitKey(10);

        if(key=='s')
        break;
    }
    imwrite("webcam_capture.jpg", frame);
    webcam.release();
    return 0;
}

Cela capturera une image de taille maximale autorisée par votre webcam. Vous pouvez maintenant ajouter des effets ou redimensionner l'image capturée avec Qt. Et OpenCV est très très facile à intégrer à Qt :)

0