[PYTHON] Créer un lecteur vidéo avec PySimpleGUI + OpenCV

introduction

OpenCV (Open Source Computer Vision Library) est une collection de bibliothèques de traitement d'images / vidéo open source sous licence BSD. Diverses bibliothèques telles que divers filtres, correspondance de modèles, reconnaissance d'objets et apprentissage automatique pour les images et les vidéos sont disponibles.

https://opencv.org/

Nous allons créer un lecteur vidéo en utilisant PySimpleGUI afin que vous puissiez définir le ROI, le masque, etc. tout en vérifiant l'image lors de l'analyse de la vidéo.

À propos de cet article

Pour la première fois, nous allons créer une interface graphique afin que vous puissiez lire / arrêter la vidéo et définir l'image de début / fin. La vitesse de lecture de la vidéo et le nombre de sauts d'images peuvent être définis. pic1-3.jpg

Nombre de sauts d'images = 1: test.gif

Nombre de sauts d'images = 5: test.gif

Lire le fichier

Créez une interface graphique de lecture de fichier à l'aide de PySimpleGUI. pic1-1.jpg

Cliquez sur Soumettre pour afficher la boîte de dialogue de sélection de fichier. pic1-2.jpg

import numpy as np
import PySimpleGUI as sg
import cv2
from pathlib import Path

def file_read():
    '''
Sélectionnez et chargez un fichier
    '''
    fp = ""
    #Disposition GUI
    layout = [
        [
            sg.FileBrowse(key="file"),
            sg.Text("Fichier"),
            sg.InputText()
        ],
        [sg.Submit(key="submit"), sg.Cancel("Exit")]
    ]
    #Génération WINDOW
    window = sg.Window("Sélection de fichiers", layout)

    #Boucle d'événement
    while True:
        event, values = window.read(timeout=100)
        if event == 'Exit' or event == sg.WIN_CLOSED:
            break
        elif event == 'submit':
            if values[0] == "":
                sg.popup("Aucun fichier n'a été saisi.")
                event = ""
            else:
                fp = values[0]
                break
    window.close()
    return Path(fp)

Chargement de la vidéo

Chargez la vidéo et définissez divers paramètres. S'il ne peut pas être chargé, une fenêtre contextuelle s'affiche et le processus se termine.

class Main:
    def __init__(self):
        self.fp = file_read()
        self.cap = cv2.VideoCapture(str(self.fp))

        #Obtenez la première image
        #Vérifiez s'il peut être obtenu
        self.ret, self.f_frame = self.cap.read()

        if self.ret:

            self.cap.set(cv2.CAP_PROP_POS_FRAMES, 0)
            #Acquisition d'informations vidéo
            self.fps = self.cap.get(cv2.CAP_PROP_FPS)
            self.width = int(self.cap.get(cv2.CAP_PROP_FRAME_WIDTH))
            self.height = int(self.cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
            self.total_count = self.cap.get(cv2.CAP_PROP_FRAME_COUNT)

            #Lié au cadre
            self.frame_count = 0
            self.s_frame = 0
            self.e_frame = self.total_count

            #Lire l'indicateur de pause
            self.stop_flg = False

            cv2.namedWindow("Movie")

        else:
            sg.Popup("Impossible de lire le fichier.")
            return

Paramètres et affichage de l'interface graphique

Réglez la fenêtre GUI pour l'opération vidéo. Avec PySimpleGUI, vous pouvez ajouter divers objets simplement en les ajoutant à la liste, ce qui est plus utile qu'une journée lors de la création d'une interface graphique simple.


    def run(self):
        # GUI #######################################################
        #Disposition GUI
        layout = [
            [
                sg.Text("Start", size=(8, 1)),
                sg.Slider(
                    (0, self.total_count - 1),
                    0,
                    1,
                    orientation='h',
                    size=(45, 15),
                    key='-START FRAME SLIDER-',
                    enable_events=True
                )
            ],
            [
                sg.Text("End ", size=(8, 1)),
                sg.Slider(
                    (0, self.total_count - 1), self.total_count - 1,
                    1,
                    orientation='h',
                    size=(45, 15),
                    key='-END FRAME SLIDER-',
                    enable_events=True
                )
            ],
            [sg.Slider(
                (0, self.total_count - 1),
                0,
                1,
                orientation='h',
                size=(50, 15),
                key='-PROGRESS SLIDER-',
                enable_events=True
            )],
            [
                sg.Button('<<<', size=(5, 1)),
                sg.Button('<<', size=(5, 1)),
                sg.Button('<', size=(5, 1)),
                sg.Button('Play / Stop', size=(9, 1)),
                sg.Button('Reset', size=(7, 1)),
                sg.Button('>', size=(5, 1)),
                sg.Button('>>', size=(5, 1)),
                sg.Button('>>>', size=(5, 1))
            ],
            [
                sg.Text("Speed", size=(6, 1)),
                sg.Slider(
                    (0, 240),
                    10,
                    10,
                    orientation='h',
                    size=(19.4, 15),
                    key='-SPEED SLIDER-',
                    enable_events=True
                ),
                sg.Text("Skip", size=(6, 1)),
                sg.Slider(
                    (0, 300),
                    0,
                    1,
                    orientation='h',
                    size=(19.4, 15),
                    key='-SKIP SLIDER-',
                    enable_events=True
                )
            ],
            [sg.HorizontalSeparator()],
            [sg.Output(size=(65, 5), key='-OUTPUT-')],
            [sg.Button('Clear')]
        ]


        #Générer la fenêtre
        window = sg.Window('OpenCV Integration', layout, location=(0, 0))
        #Affichage des informations vidéo
        self.event, values = window.read(timeout=0)
        print("Le fichier a été lu.")
        print("File Path: " + str(self.fp))
        print("fps: " + str(int(self.fps)))
        print("width: " + str(self.width))
        print("height: " + str(self.height))
        print("frame count: " + str(int(self.total_count)))

Lecture vidéo

Tournez la boucle principale pour lire la vidéo. Pendant la lecture window.read (lecture des événements GUI)   ↓ cap.read (lecture des images vidéo)   ↓ Traitement d'image divers   ↓ cv2.imshow (afficher la vidéo)   ↓ frame_count + = 1 (augmenter le nombre d'images) Et tournez la boucle.

Si vous appuyez sur le bouton Lecture / Arrêt window.read (lecture des événements GUI)   ↓ cap.read (lecture des images vidéo)   ↓ Traitement d'image divers   ↓ cv2.imshow (afficher la vidéo)   ↓ Est-ce la même chose jusqu'à cap.set(cv2.CAP_PROP_POS_FRAMES, self.frame_count) En renvoyant le nombre de trames, divers traitements d'image peuvent être effectués sur la même trame sans augmenter le nombre de trames.


    #Boucle principale#########################################################
        try:
            while True:
                self.event, values = window.read(
                    timeout=values["-SPEED SLIDER-"]
                )

                if self.event == "Clear":
                    pass

                if self.event != "__TIMEOUT__":
                    print(self.event)
                #Quitter lorsque vous appuyez sur le bouton Quitter ou lorsque vous appuyez sur le bouton de fermeture de fenêtre
                if self.event in ('Exit', sg.WIN_CLOSED, None):
                    break

                #Recharger la vidéo
                #Fonctionne lorsque l'image de départ est définie
                if self.event == 'Reset':
                    self.cap.set(cv2.CAP_PROP_POS_FRAMES, self.s_frame)
                    self.frame_count = self.s_frame
                    window['-PROGRESS SLIDER-'].update(self.frame_count)

                    #Continuer à refléter les modifications apportées au curseur de progression
                    continue

                #Fonctionnement du cadre################################################
                #La priorité est donnée si le curseur est modifié directement
                if self.event == '-PROGRESS SLIDER-':
                    #Définissez le nombre d'images sur la barre de progression
                    self.frame_count = int(values['-PROGRESS SLIDER-'])
                    self.cap.set(cv2.CAP_PROP_POS_FRAMES, self.frame_count)
                    if values['-PROGRESS SLIDER-'] > values['-END FRAME SLIDER-']:
                        window['-END FRAME SLIDER-'].update(
                            values['-PROGRESS SLIDER-'])

                #Si vous modifiez l'image de départ
                if self.event == '-START FRAME SLIDER-':
                    self.s_frame = int(values['-START FRAME SLIDER-'])
                    self.cap.set(cv2.CAP_PROP_POS_FRAMES, self.s_frame)
                    self.frame_count = self.s_frame
                    window['-PROGRESS SLIDER-'].update(self.frame_count)
                    if values['-START FRAME SLIDER-'] > values['-END FRAME SLIDER-']:
                        window['-END FRAME SLIDER-'].update(
                            values['-START FRAME SLIDER-'])
                        self.e_frame = self.s_frame

                #Si vous modifiez le cadre de fin
                if self.event == '-END FRAME SLIDER-':
                    if values['-END FRAME SLIDER-'] < values['-START FRAME SLIDER-']:
                        window['-START FRAME SLIDER-'].update(
                            values['-END FRAME SLIDER-'])
                        self.s_frame = self.e_frame

                    #Paramètres du cadre de fin
                    self.e_frame = int(values['-END FRAME SLIDER-'])

                if self.event == '<<<':
                    self.frame_count = np.maximum(0, self.frame_count - 150)
                    window['-PROGRESS SLIDER-'].update(self.frame_count)
                    self.cap.set(cv2.CAP_PROP_POS_FRAMES, self.frame_count)

                if self.event == '<<':
                    self.frame_count = np.maximum(0, self.frame_count - 30)
                    window['-PROGRESS SLIDER-'].update(self.frame_count)
                    self.cap.set(cv2.CAP_PROP_POS_FRAMES, self.frame_count)

                if self.event == '<':
                    self.frame_count = np.maximum(0, self.frame_count - 1)
                    window['-PROGRESS SLIDER-'].update(self.frame_count)
                    self.cap.set(cv2.CAP_PROP_POS_FRAMES, self.frame_count)

                if self.event == '>':
                    self.frame_count = self.frame_count + 1
                    window['-PROGRESS SLIDER-'].update(self.frame_count)
                    self.cap.set(cv2.CAP_PROP_POS_FRAMES, self.frame_count)

                if self.event == '>>':
                    self.frame_count = self.frame_count + 30
                    window['-PROGRESS SLIDER-'].update(self.frame_count)
                    self.cap.set(cv2.CAP_PROP_POS_FRAMES, self.frame_count)

                if self.event == '>>>':
                    self.frame_count = self.frame_count + 150
                    window['-PROGRESS SLIDER-'].update(self.frame_count)
                    self.cap.set(cv2.CAP_PROP_POS_FRAMES, self.frame_count)

                #Si le compteur dépasse la trame de fin, redémarrez à partir de la trame de début
                if self.frame_count >= self.e_frame:
                    self.cap.set(cv2.CAP_PROP_POS_FRAMES, self.s_frame)
                    self.frame_count = self.s_frame
                    window['-PROGRESS SLIDER-'].update(self.frame_count)
                    continue

                #Suspendre le chargement de la vidéo avec le bouton d'arrêt
                if self.event == 'Play / Stop':
                    self.stop_flg = not self.stop_flg

                #Sauf si l'indicateur d'arrêt est défini et qu'un événement se produit, compte
                #Arrêtez l'opération

                #Si le bouton d'arrêt est enfoncé, le traitement vidéo sera arrêté, mais quelque chose
                #Si un événement se produit, ne mettez à jour que l'image
                #La même chose s'applique lors de l'utilisation de la souris
                if(
                    (
                        self.stop_flg
                        and self.event == "__TIMEOUT__"
                    )
                ):
                    window['-PROGRESS SLIDER-'].update(self.frame_count)
                    continue

                #Ignorer les cadres
                if not self.stop_flg and values['-SKIP SLIDER-'] != 0:
                    self.frame_count += values["-SKIP SLIDER-"]
                    self.cap.set(cv2.CAP_PROP_POS_FRAMES, self.frame_count)

                #Cadre de charge##############################################
                self.ret, self.frame = self.cap.read()
                self.valid_frame = int(self.frame_count - self.s_frame)
                #Quand la dernière image est sur soi.s_Reprendre du cadre
                if not self.ret:
                    self.cap.set(cv2.CAP_PROP_POS_FRAMES, self.s_frame)
                    self.frame_count = self.s_frame
                    continue

                #Décrivez le traitement de la trame après cela##################################
                #Effectuez d'abord le traitement pour toute la trame##############################
                #Affichage du nombre d'images et des secondes écoulées
                cv2.putText(
                    self.frame, str("framecount: {0:.0f}".format(self.frame_count)), (
                        15, 20), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (240, 230, 0), 1, cv2.LINE_AA
                )
                cv2.putText(
                    self.frame, str("time: {0:.1f} sec".format(
                        self.frame_count / self.fps)), (15, 40), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (240, 230, 0), 1, cv2.LINE_AA
                )

                #Afficher l'image
                cv2.imshow("Movie", self.frame)

                if self.stop_flg:
                    self.cap.set(cv2.CAP_PROP_POS_FRAMES, self.frame_count)

                else:
                    self.frame_count += 1
                    window['-PROGRESS SLIDER-'].update(self.frame_count + 1)

        finally:
            cv2.destroyWindow("Movie")
            self.cap.release()
            window.close()


if __name__ == '__main__':
    Main().run()

environnement

Windows10(64bit) python 3.5.2 OpenCV 4.1.0

Lien de référence

PySimpleGUI PySimpleGUI: popup_get_text Utilisation de base de l'interface graphique PySimple Créer une visionneuse de traitement d'image avec l'interface graphique PySimple

OpenCV J'ai créé mon propre outil d'analyse de vidéos de tennis avec Python

Recommended Posts

Créer un lecteur vidéo avec PySimpleGUI + OpenCV
Créer un lecteur vidéo avec PySimpleGUI + OpenCV 3 Ajout de la fonction de masque
Créez un lecteur vidéo avec PySimpleGUI + OpenCV 2 Ajoutez le paramètre ROI et la fonction d'enregistrement (DIVX, MJPG, GIF)
Chargement de la vidéo en boucle avec opencv
Créer une fonction pour décrire les polices japonaises avec OpenCV
Faites une loterie avec Python
Faire un feu avec kdeplot
Créez facilement des miniatures à partir de dossiers vidéo érotiques avec opencv
Créez un outil d'analyse vidéo simple avec python wxpython + openCV
Faisons une interface graphique avec python.
Faites un son avec le notebook Jupyter
Effacez des couleurs spécifiques avec OpenCV + PySimpleGUI
Faisons une rupture de bloc avec wxPython
Créer un système de recommandation avec python
Créer un filtre avec un modèle django
Faisons un graphe avec python! !!
Faisons un spacon avec xCAT
Créer un itérateur de modèle avec PySide
Faire un joli graphique avec plotly
Découpage avec OpenCV-Faire une vidéo voyante-
Comment créer une caméra de surveillance (caméra de sécurité) avec Opencv et Python
Créez un simple OMR (lecteur de feuille de marque) avec Python et OpenCV
Créez un effecteur pour la visioconférence avec Spout + OpenCV + dlib (Partie 1)
Faisons un jeu de shiritori avec Python
Enregistrer la vidéo image par image avec Python OpenCV
Créez un simulateur de gacha rare avec Flask
Créez un pipeline de notebook avec Kedro + Papermill
Faire une figure partiellement zoomée avec matplotlib
Créez un quiz de dessin avec kivy + PyTorch
Faisons la voix lentement avec Python
Créez un classificateur en cascade avec Google Colaboratory
Faisons un langage simple avec PLY 1
Faire un circuit logique avec Perceptron (Perceptron multicouche)
Faire Oui Non Popup avec Kivy
Faire une minuterie de lavage-séchage avec Raspberry Pi
Créer une animation GIF avec surveillance des dossiers
Créez un framework Web avec Python! (1)
Faisons une IA à trois yeux avec Pylearn 2
Créez une application de bureau avec Python avec Electron
Faisons un bot Twitter avec Python!
Créez un framework Web avec Python! (2)
Un mémorandum pour faire WebDAV uniquement avec nginx
Suivez les objets de votre vidéo avec OpenCV Tracker
Créer un bot Twitter Trend avec heroku + Python
Fabriquer un appareil de surveillance avec un capteur infrarouge
Créez un simple générateur d'images par points avec Flask
Comment créer un dictionnaire avec une structure hiérarchique.
Je veux faire un jeu avec Python
Essayez de créer un code de "décryptage" en Python
Rendre OpenCV3 disponible à partir de python3 installé avec pyenv
Remplaçons UWSC par Python (5) Faisons un robot
Essayez de créer un groupe de dièdre avec Python
[Chat De Tornado] Créez un chat en utilisant WebSocket dans Tornado
Transformez les données de vacances en une trame de données avec les pandas
Créer un bot LINE WORKS avec Amazon Lex
(Mémorandum) Créer un diagramme de dispersion 3D avec matplodlib