Logo Mon Club Elec

PyQt Lab’ : PyQt + OpenCV + pyqtcv + webcam : Capture simple d’un flux vidéo webcam avec GSVideo

PyQt Lab est un outil puissant qui permet aux développeurs de créer des applications interactives et des interfaces graphiques. Il combine PyQt, OpenCV, pyqtcv et une webcam pour capturer facilement un flux vidéo. Grâce à ces technologies, les développeurs peuvent créer des applications qui peuvent capturer des images et des vidéos à partir d’une webcam et les traiter avec OpenCV. PyQt Lab offre également des fonctionnalités avancées telles que le traitement d’image et le traitement du signal. Dans cet article, nous allons vous montrer comment capturer simplement un flux vidéo webcam avec GSVideo et PyQt Lab.

PyQt Lab’ : PyQt + OpenCV + pyqtcv + webcam : Capture simple d’un flux vidéo webcam avec GSVideo

Par X. HINAULT – Octobre 2013

PyQt Lab’ : PyQt + OpenCV + pyqtcv + webcam : Capture simple d’un flux vidéo webcam avec GSVideo

Ce que l’on va faire ici

  • Dans ce code PyQt, une interface affichant une simple capture d’un flux webcam en utilisant GSVideo. Ce code pourra servir de base pour des applications utilisant la capture vidéo.

L’utilisation de GSVideo permet d’obtenir une vitesse de capture optimisée comparativement à la fonction native de capture de OpenCV… Ici, une image sera capturée en quelques millisecondes, permettant des framerate élevés, y compris sur de petites machines.

  • Ce code nécessite une webcam connectée et opérationnelle :
    • on pourra tester la webcam au préalable avec Guvcview. Refermer l’application une fois le test fait.
    • on pourra connaître l’indice de la webcam utilisée avec la commande :
ls dev/video*
  • Typiquement la première caméra a l’indice 0, la 2ème, l’indice 1, etc…

Résultat

  • Avec une webcam eye PS3, sous Ubuntu 12.04LTS, sur un Intel(R) Core(TM)2 Quad CPU Q8200 @ 2.33GHz, en capture 320×240, une fréquence de capture de 100fps est atteinte !
PyQt Lab’ : PyQt + OpenCV + pyqtcv + webcam : Capture simple d’un flux vidéo webcam avec GSVideo
  • Noter que dans la mesure où la capture est réalisée par signal, le temps de traitement n’est pas corrélé à la fps.

Pré-requis

  • python 2.7
  • pyqt4.x
  • modules :
    • python-opencv
    • python-numpy
    • ma librairie perso pyqtcv qui implémente plusieurs fonctions utiles pour utiliser facilement Opencv avec PyQt.
    • python-gst0.10

Test préalable

  • Dans le mesure où l’on utilise ici Gstreamer, il est possible de tester le bon fonctionnement à l’aide d’un pipeline en ligne de commande. Le pipeline suivant doit afficher votre image webcam :
gst-launch v4l2src device=/dev/video1 ! ‘video/x-raw-yuv,width=320,height=240,framerate=30/1’ ! xvimagesink

Pour mémoire, pour lister la liste des plugins gstreamer installés, faire :

gst-inspect

Téléchargement :

Le fichier d’interface *.py

  • Fichier obtenu automatiquement avec l’utilitaire pyuic4 à partir du fichier *.ui créé avec QtDesigner :
# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file
#
# Created: Thu Oct 24 12:33:08 2013
#      by: PyQt4 UI code generator 4.9.1
#
# WARNING! All changes made in this file will be lost!

from PyQt4 import QtCore, QtGui

try:
    _fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
    _fromUtf8 = lambda s: s

class Ui_Form(object):
    def setupUi(self, Form):
        Form.setObjectName(_fromUtf8(« Form »))
        Form.resize(331, 250)
        self.labelImage = QtGui.QLabel(Form)
        self.labelImage.setGeometry(QtCore.QRect(5, 5, 320, 240))
        self.labelImage.setFrameShape(QtGui.QFrame.Box)
        self.labelImage.setFrameShadow(QtGui.QFrame.Sunken)
        self.labelImage.setText(_fromUtf8(«  »))
        self.labelImage.setObjectName(_fromUtf8(« labelImage »))

        self.retranslateUi(Form)
        QtCore.QMetaObject.connectSlotsByName(Form)

    def retranslateUi(self, Form):
        Form.setWindowTitle(QtGui.QApplication.translate(« Form », « PyQt+Pyqtcv+webcam : Capture image », None, QtGui.QApplication.UnicodeUTF8))

if __name__ == « __main__ »:
    import sys
    app = QtGui.QApplication(sys.argv)
    Form = QtGui.QWidget()
    ui = Ui_Form()
    ui.setupUi(Form)
    Form.show()
    sys.exit(app.exec_())

 

Le fichier d’application *Main.py

#!/usr/bin/python
# -*- coding: utf-8 -*-

# Par X. HINAULT – Tous droits réservés
# Mars 2013 – www.mon-club-elec.fr
# GPLv3

from PyQt4.QtGui import *
from PyQt4.QtCore import * # inclut QTimer..
import os,sys

from cv2 import * # pour opencv – intègre sous module cv d’où accès avec forme cv.fonction
import time # pour millis

#sys.path.insert(0,’/home/xavier/ownCloud2/libs_python’) # si pas path système
from pyqtcv import * # importe librairie perso comportant fonctions utiles pour utiliser opencv avec pyqt
import bufferscv as buffers # importe module pyqtcv pour partage des buffers OpenCV utiles

from tuto_pyqt_pyqtcv_webcam_captureGS_simple import *

class myApp(QWidget, Ui_Form): # la classe reçoit le Qwidget principal ET la classe définie dans test.py obtenu avec pyuic4

        def __init__(self, parent=None): # Constructeur principal
                QWidget.__init__(self) # initialise le Qwidget principal
                self.setupUi(parent) # Obligatoire

                #Ici, personnalisez vos widgets si nécessaire

                #Réalisez les connexions supplémentaires entre signaux et slots – Ne pas oublier +++
                #self.connect(self.pushButton, SIGNAL(« clicked() »), self.pushButtonClicked) # connecte le signal Clicked de l’objet bouton à l’appel de la fonction voulue

                #========= variables de classe utiles ==========
                self.micros0=0 # variable pour calculs délais exécution
                self.qImageTrans=None

                #========= paramètres graphiques généraux ========
                self.framerate=30 # nombre d’image par secondes (rafraîchissement de l’affichage)              
                self.widthCapture=320 # largeur image capture en pixels
                self.heightCapture=240 # hauteur image capture en pixels
                # la résolution utilisée doit être supportée par la webcam – 320×240 est un bon compromis –            
                self.nChannels=3 # nombre de canaux pour les images buffer – RGB par défaut = 3 canaux

                #======== config capture openCV ==========
                #– initialisation de la caméra
                self.indexCam=0 # index de la webcam à utiliser – voir ls /dev/video* – utiliser -1 si pas d’indice
                #self.webcam=initWebcam(self.indexCam, self.widthCapture, self.heightCapture, self.framerate)
                initWebcamGS(self.indexCam, self.widthCapture, self.heightCapture, self.framerate) # equivalent – utilise objet webcam interne pyqtcv

                #– initialisation OpenCV —
                allocate(self.widthCapture, self.heightCapture) # initialise les buffers OpenCV à la taille voulue – allocate : fonction de classe ci-dessous

                # connexion evenement capture image
                buffers.sink.connect(‘new-buffer’, self.newFrame) # connexion signal nouvelle image a fonction lecture data

                # affiche l’image une premiere fois dans Qt – necessaire ici car utilisation thread GSVideo
                self.qImage=IplToQImage(buffers.RGB) # récupère l’IplImage dans un QImage – obligé utiliser qImage différent
                self.qPixmap=QPixmap.fromImage(self.qImage) # récupère le QImage dans un QPixmap
                self.labelImage.setPixmap(self.qPixmap) # affiche l’image dans le label
                # NB : pour éviter les problèmes, les objets de manipulation d’image doivent être « self »

        # les fonctions appelées, utilisées par les signaux
        #def pushButtonClicked(self):
                #print(« Bouton appuyé »

        # fonction lecture des data images
        def newFrame(self,sinkIn): # appelée par le signal new-buffer.. la fonction reçoit la source

                #– évaluation durée entre 2 appels de la fonction newFrame et donc du fps
                print(str(1000000/(micros()self.micros0)) +  » fps »)
                self.micros0=micros() # mémorise millis précédent

                #– capture l’image GS —
                buffers.RGB=captureImageGS(sinkIn)

                #– +/- traitement de l’image
                #threshold(200)

                # affiche l’image resultante dans Qt
                self.qImage=IplToQImage(buffers.RGB) # récupère l’IplImage dans un QImage – obligé utiliser qImage différent
                #self.qPixmap=QPixmap.fromImage(self.qImage) # récupère le QImage dans un QPixmap
                self.qPixmap.convertFromImage(self.qImage) # recharge le QImage dans le QPixmap existant – met à jour le QPixmap – evite erreur safe
                self.labelImage.setPixmap(self.qPixmap) # affiche l’image dans le label
                # NB : pour éviter les problèmes, les objets de manipulation d’image doivent être « self »

                print(« Duree traitement : » + str(round((micros()self.micros0)/1000.0,2)) +  » ms »)

        # — fin newFrame

#— fonction main exécutée en premier —                             
def main(args):
        a=QApplication(args) # crée l’objet application
        f=QWidget() # crée le QWidget racine
        c=myApp(f) # appelle la classe contenant le code de l’application
        f.show() # affiche la fenêtre QWidget
        r=a.exec_() # lance l’exécution de l’application
        return r

#— obligatoire pour code exécutable —-
if __name__==« __main__ »: # pour rendre le code exécutable
        main(sys.argv) # appelle la fonction main

 

Utilisation

  • Les 2 fichiers suivants sont à enregistrer dans un même répertoire, l’un en nom.py et l’autre en nomMain.py.
  • Régler au besoin le fps et la taille d’image
  • Puis lancer l’application depuis Geany ou équivalent, en exécutant le fichier nomMain.py
  • Sélectionner un fichier : l’image video de la webcam doit s’afficher dans le fenêtre de sortie.
Noter cet article

Laisser un commentaire

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

Archive Mon Club Elec

Articles populaires

Newsletter

Inscrivez-vous maintenant et bénéficiez d'un soutien continu pour réaliser vos travaux électriques en toute sécurité.