Comment capturer une image fixe à partir d’une webcam sur Linux

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

Mais j’ai rencontré quelques problèmes. Le principal problème est que le pilote linux standard de classe UVC (usb video device class) ne supporte actuellement pas la capture directe d’images fixes: http://www.ideasonboard.org/uvc/ .

Il y a donc deux manières possibles de capturer une image fixe. Vous pouvez prendre une image du stream vidéo de la caméra ou prendre une photo distincte, comme une caméra portable numérique. La seconde méthode n’est pas prise en charge dans le pilote Linux uvc. La première méthode est donc la seule. Mais le problème est que si vous souhaitez extraire une image du stream vidéo, la taille de la photo ne peut pas dépasser la taille de la vidéo dans la fenêtre de prévisualisation vidéo. Donc, si je veux prendre une photo de 2 mégapixels, je dois lancer videotream avec la taille 1600×1200, ce qui n’est pas très confortable (au moins, dans Qt, la taille de la vidéo dépend de la taille de la fenêtre de vidéopreview).

Je sais qu’il existe une vidéo pour 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 peux pas maintenant comprendre comment faire ce dont j’ai besoin en utilisant 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, l’API v4l2 et d’autres choses spécifiques à Linux.

Par ailleurs, 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 cadre peut m’aider à le faire. Peut-être vous savez.

Malheureusement, les appels C4V2 en mode opencv n’ont pas fonctionné pour la capture d’images fixes avec n’importe quelle caméra que j’ai essayée en utilisant le pilote UVC.

Pour déboguer le problème, j’ai essayé de faire cela avec le code c appelant directement c4v2.

J’ai joué avec l’exemple de code trouvé ici . Il utilise la méthode d’extraction des images du stream vidéo.

Vous pouvez le comstackr avec:

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

J’ai expérimenté avec 3 caméras logitech. Le meilleur du lot semble être le Logitech C910. Mais même cela a 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 à 1920×1080.

Lorsque j’interroge d’autres possibilités directement depuis la ligne de commande en utilisant par exemple:

 v4l2-ctl --list-formats-ext 

et j’essaie quelques-unes des plus petites tailles “disponibles”, il est bloqué dans la sélection en attendant que la caméra libère le tampon.

Aussi lorsque j’essaie de définir d’autres tailles directement depuis la ligne de commande en utilisant par exemple:

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

Ensuite, vérifiez avec

 v4l2-ctl -V 

Je trouve qu’il renvoie le format de pixel correct mais pas souvent la taille correcte.

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

J’ai fait quelques tests sur le LogitechC910 après avoir posté ceci. Je pensais que je posterais les résultats au cas où cela aiderait quelqu’un d’autre.

J’ai écrit un script pour tester le code v4l2 grabber mentionné ci-dessus sur tous les formats que la caméra prétend prendre en charge lorsqu’il est interrogé 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 paramètre par défaut de 640×480 ne fonctionne pas et c’est ce qui a piégé moi et la plupart des personnes qui ont posté des messages sur les forums.

Comme il prend une image vidéo, la première image qu’elle capture lors du démarrage peut avoir une exposition incorrecte (souvent noire ou proche). Je crois que c’est parce que, étant utilisé comme une caméra vidéo, il ajuste l’exposition au fur et à mesure et ne se soucie pas des premières images. Je crois que cela a aussi piégé moi et d’autres qui ont vu le premier cadre comme noir ou presque noir et a pensé que c’était une sorte d’erreur. Les images ultérieures ont l’exposition correcte

Il s’avère que opencv avec les wrappers python fonctionne bien avec cette caméra si vous évitez les mines terrestres listé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, elle ne répond pas correctement. Donc, si vous définissez la largeur, elle est définie correctement, mais sa largeur est incorrecte.

Pour exécuter sous opencv avec les wrappers python, vous pouvez procéder comme suit:

 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) 
 **Download And Install 'mplayer'** mplayer -vo png -frames 1 tv:// 
 mplayer -vo png -frames 1 tv:// 

peut donner un écran vert comme 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 numéro à partir duquel la caméra donne des images correctes.

Qu’en est-il de ce programme?

 #include 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 va capturer une image de la taille maximale autorisée par votre webcam. Maintenant, vous pouvez append des effets ou redimensionner l’image capturée avec Qt. Et OpenCV est très très facile à intégrer avec Qt, 🙂