[PYTHON] Créer un lecteur vidéo avec PySimpleGUI + OpenCV 3 Ajout de la fonction de masque

introduction

En plus de l'article précédent, nous ajouterons une région ROI (Region of Interest) à sélectionner comme cible de l'opération et un processus (masque) qui ne cible qu'une partie spécifique.

Créer un lecteur vidéo avec PySimpleGUI + OpenCV 2 Ajouter le paramètre ROI et enregistrer la fonction (DIVX, MJPG, GIF)

Que pouvez-vous faire avec cet article

Vous pouvez appliquer le traitement à une pièce spécifique (masque) dans le ROI. La sélection de masque convertit l'image en HSV et chaque curseur vous permet de sélectionner une valeur numérique. La partie masque est affichée dans une fenêtre séparée afin que vous puissiez la vérifier. 3-1.jpg

Lors de la sélection du rouge, il est nécessaire de sélectionner deux plages de valeurs de teinte, environ 0-20 et 110-255, alors créez une case à cocher appelée Hue Reverse, et si la case est cochée, La valeur en dehors des deux curseurs est définie comme plage de masque.

Inverser la teinte [Off]

La plage entre les curseurs gauche et droit de Hue est la plage de masque. クリップボード一時ファイル01.jpg

Inverser la teinte [Oui]

L'extérieur des curseurs gauche et droit de Hue est la plage de masque. Vous pouvez inverser la plage de masque. クリップボード一時ファイル02.jpg

Vous pouvez enregistrer une plage spécifiée de vidéos au format DIVX, MJEG, GIF. test.gif

Lire le fichier

Sélectionnez le fichier à charger à l'aide de l'interface graphique.

import PySimpleGUI as sg
import cv2
import numpy as np
from PIL import Image
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)

Détection de couleur par HSV

Conversion HSV → Le traitement du masque est transformé en fonction. Créez un masque à partir des valeurs min et max de H, S et V reçues de l'interface graphique et créez une image de masque avec cv2.bitwize_and ().


def hsv(frame, H_max, H_min, S_max, S_min, V_max, V_min, reverse=False):
    frame_hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
    if reverse:
        lower1 = np.array([0, int(S_min), int(V_min)])
        upper1 = np.array([int(H_min), int(S_max), int(V_max)])
        mask1 = cv2.inRange(frame_hsv, lower1, upper1)
        lower2 = np.array([int(H_max), int(S_min), int(V_min)])
        upper2 = np.array([255, int(S_max), int(V_max)])
        mask2 = cv2.inRange(frame_hsv, lower2, upper2)
        mask = mask1 + mask2
        frame = cv2.bitwise_and(frame, frame, mask=mask)
        # mask = cv2.bitwise_and(frame, mask, mask=mask)

    else:
        lower = np.array([int(H_min), int(S_min), int(V_min)])
        upper = np.array([int(H_max), int(S_max), int(V_max)])
        mask = cv2.inRange(frame_hsv, lower, upper)
        frame = cv2.bitwise_and(frame, frame, mask=mask)

    return frame


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

        #Drapeau d'enregistrement vidéo
        self.rec_flg = False

        #Obtenez la première image
        #Vérifiez s'il peut être obtenu
        self.ret, self.f_frame = self.cap.read()
        self.cap.set(cv2.CAP_PROP_POS_FRAMES, 0)
        #Si vous pouvez obtenir le cadre, obtenez divers paramètres
        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)

            # ROI
            self.frames_roi = np.zeros((5, self.height, self.width))

En tant qu'image de masque, préparez une image de masque en échelle de gris de la même taille que le ROI.



            #Définition de l'image de masque
            self.mask = np.zeros_like(self.f_frame[:, :, 0])

            #Enregistrer la taille d'origine
            self.org_width = self.width
            self.org_height = self.height

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

            #Position de découpe de l'image
            self.x1 = 0
            self.y1 = 0
            self.x2 = self.width
            self.y2 = self.height

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

            #Contrôle du mouvement de la souris
            #Si le bouton de la souris est enfoncé
            self.mouse_flg = False
            self.event = ""
            #S'il faut appliquer le calcul au retour sur investissement
            self.roi_flg = True
            cv2.namedWindow("Movie")

            #Enregistrement de rappel pour les événements de souris
            cv2.setMouseCallback("Movie", self.onMouse)
        #Quitter si le cadre n'a pas pu être obtenu
        else:
            sg.Popup("Impossible de lire le fichier.")
            return

    #Événement souris
    def onMouse(self, event, x, y, flags, param):
        #Click gauche
        if event == cv2.EVENT_LBUTTONDOWN:
            self.x1 = self.x2 = x
            self.y1 = self.y2 = y
            #Commencez à dessiner un rectangle. Appuyez une fois sur la souris pour commencer à dessiner un rectangle.
            self.mouse_flg = True
            #Suspendre le calcul de la partie ROI
            self.roi_flg = False
            return

        elif event == cv2.EVENT_LBUTTONUP:
            #Arrêter de mettre à jour les rectangles
            self.mouse_flg = False
            #Démarrez le calcul du ROI
            self.roi_flg = True
            #Si la sélection de ROI est 0, réinitialisez-la et arrêtez le calcul de ROI.
            if (
                x == self.x1
                or y == self.y1
                or x <= 0
                or y <= 0
            ):
                self.x1 = 0
                self.y1 = 0
                self.x2 = self.width
                self.y2 = self.height
                return

            # x1 <Faites-le x2
            elif self.x1 < x:
                self.x2 = x
            else:
                self.x2 = self.x1
                self.x1 = x

            if self.y1 < y:
                self.y2 = y
            else:
                self.y2 = self.y1
                self.y1 = y

            #Afficher la plage de retour sur investissement
            print(
                "ROI x:{0}:{1}  y:{2}:{3}".format(
                    str(self.x1),
                    str(self.x2),
                    str(self.y1),
                    str(self.y2)
                )
            )
            return

        #Continue d'afficher le rectangle lorsque la souris est enfoncée
        if self.mouse_flg:
            self.x2 = x
            self.y2 = y

            return

    def run(self):
        # GUI #######################################################
        #Disposition GUI

        #Onglet 1
        T1 = sg.Tab("Basic", [
            [
                sg.Text("Resize     ", size=(13, 1)),
                sg.Slider(
                    (0.1, 4),
                    1,
                    0.01,
                    orientation='h',
                    size=(40, 15),
                    key='-RESIZE SLIDER-',
                    enable_events=True
                )
            ],
            [
                sg.Checkbox(
                    'blur',
                    size=(10, 1),
                    key='-BLUR-',
                    enable_events=True
                ),
                sg.Slider(
                    (1, 10),
                    1,
                    1,
                    orientation='h',
                    size=(40, 15),
                    key='-BLUR SLIDER-',
                    enable_events=True
                )
            ],


        ])

        T2 = sg.Tab("processing", [
            [
                sg.Checkbox(
                    'gray',
                    size=(10, 1),
                    key='-GRAY-',
                    enable_events=True
                )
            ],
        ])

GUI pour le réglage du masque

Préparez un onglet pour le traitement du masque. Si Masquage est sélectionné avec le bouton radio, le masquage sera effectué.

        T3 = sg.Tab("mask", [
            [
                sg.Radio(
                    'Rectangle',
                    "RADIO2",
                    key='-RECTANGLE_MASK-',
                    default=True,
                    size=(8, 1)
                ),
                sg.Radio(
                    'Masking',
                    "RADIO2",
                    key='-MASKING-',
                    size=(8, 1)
                )
            ],
            [
                sg.Checkbox(
                    "Blue",
                    size=(10, 1),
                    default=True,
                    key='-BLUE_MASK-',
                    enable_events=True
                ),
                sg.Checkbox(
                    "Green",
                    size=(10, 1),
                    default=True,
                    key='-GREEN_MASK-',
                    enable_events=True
                ),
                sg.Checkbox(
                    "Red",
                    size=(10, 1),
                    default=True,
                    key='-RED_MASK-',
                    enable_events=True
                )
            ],
            [
                sg.Text(
                    'hsv',
                    size=(10, 1),
                    key='-HSV_MASK-',
                    enable_events=True
                ),
                sg.Button('Blue', size=(10, 1)),
                sg.Button('Green', size=(10, 1)),
                sg.Button('Red', size=(10, 1))
            ],
            [
                sg.Checkbox(
                    'Hue Reverse',
                    size=(10, 1),
                    key='-Hue Reverse_MASK-',
                    enable_events=True
                )
            ],
            [
                sg.Text('Hue', size=(10, 1), key='-Hue_MASK-'),
                sg.Slider(
                    (0, 255),
                    0,
                    1,
                    orientation='h',
                    size=(19.4, 15),
                    key='-H_MIN SLIDER_MASK-',
                    enable_events=True
                ),
                sg.Slider(
                    (1, 255),
                    125,
                    1,
                    orientation='h',
                    size=(19.4, 15),
                    key='-H_MAX SLIDER_MASK-',
                    enable_events=True
                )
            ],
            [
                sg.Text('Saturation', size=(10, 1), key='-Saturation_MASK-'),
                sg.Slider(
                    (0, 255),
                    50,
                    1,
                    orientation='h',
                    size=(19.4, 15),
                    key='-S_MIN SLIDER_MASK-',
                    enable_events=True
                ),
                sg.Slider(
                    (1, 255),
                    255,
                    1,
                    orientation='h',
                    size=(19.4, 15),
                    key='-S_MAX SLIDER_MASK-',
                    enable_events=True
                )
            ],
            [
                sg.Text('Value', size=(10, 1), key='-Value_MASK-'),
                sg.Slider(
                    (0, 255),
                    50,
                    1,
                    orientation='h',
                    size=(19.4, 15),
                    key='-V_MIN SLIDER_MASK-',
                    enable_events=True
                ),
                sg.Slider(
                    (1, 255),
                    255,
                    1,
                    orientation='h',
                    size=(19.4, 15),
                    key='-V_MAX SLIDER_MASK-',
                    enable_events=True
                )
            ]
        ])
        T4 = sg.Tab("Save", [
            [
                sg.Button('Write', size=(10, 1)),
                sg.Radio(
                    'DIVX',
                    "RADIO1",
                    key='-DIVX-',
                    default=True,
                    size=(8, 1)
                ),
                sg.Radio('MJPG', "RADIO1", key='-MJPG-', size=(8, 1)),
                sg.Radio('GIF', "RADIO1", key='-GIF-', size=(8, 1))
            ],
            [
                sg.Text('Caption', size=(10, 1)),
                sg.InputText(
                    size=(32, 50),
                    key='-CAPTION-',
                    enable_events=True
                )
            ]
        ])

        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.TabGroup(
                    [[T1, T2, T3, T4]],
                    tab_background_color="#ccc",
                    selected_title_color="#fff",
                    selected_background_color="#444",
                    tab_location="topleft"
                )
            ],
            [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)))


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

                #Afficher l'événement dans la fenêtre
                if self.event != "__TIMEOUT__":
                    print(self.event)
                #Quitter lorsque le bouton Quitter est enfoncé ou lorsque le bouton de fermeture de fenêtre est enfoncé
                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)

                    self.video_stabilization_flg = False
                    self.stab_prepare_flg = False

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

                #Exporter la vidéo
                if self.event == 'Write':
                    self.rec_flg = True
                    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["-GIF-"]:
                        images = []
                    else:
                        #Enregistrer en vidéo
                        #Sélection de code
                        #DIVX a un taux de compression élevé
                        #MJEG peut être analysé avec ImageJ
                        if values["-DIVX-"]:
                            codec = "DIVX"
                        elif values["-MJPG-"]:
                            codec = "MJPG"
                        fourcc = cv2.VideoWriter_fourcc(*codec)
                        out = cv2.VideoWriter(
                            str((
                                self.fp.parent / (self.fp.stem + '_' + codec + '.avi')
                            )),
                            fourcc,
                            self.fps,
                            (int(self.x2 - self.x1), int(self.y2 - self.y1))
                        )
                    continue

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

                    self.play_count = int(self.e_frame - self.s_frame)
                    self.video_stabilization_flg = True
                    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, comptez
                #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__"
                        and self.mouse_flg is False
                    )
                ):
                    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##############################
                #redimensionner
                self.width = int(self.org_width * values['-RESIZE SLIDER-'])
                self.height = int(self.org_height * values['-RESIZE SLIDER-'])
                self.frame = cv2.resize(self.frame, (self.width, self.height))
                if self.event == '-RESIZE SLIDER-':
                    self.x1 = self.y1 = 0
                    self.x2 = self.width
                    self.y2 = self.height
                #Effectuer le traitement pour le retour sur investissement##########################################
                if self.roi_flg:
                    self.frame_roi = self.frame[
                        self.y1:self.y2, self.x1:self.x2, :
                    ]

Traitement du masque RVB

Décrivez le traitement du masque. La spécification de couleur est en RVB au lieu de HSV. Après avoir spécifié la couleur avec RVB, vous pouvez spécifier la plage de masque avec V (luminosité) de HSV. Dans ce cas, Hue doit spécifier toute la plage 0-255 et changer uniquement V.

                    #Traitement en images MASK##################################################################
                    if values['-MASKING-']:
                        #Séparation RVB
                        self.mask = np.copy(self.frame_roi)
                        if not values['-BLUE_MASK-']:
                            self.mask[:, :, 0] = 0
                        if not values['-GREEN_MASK-']:
                            self.mask[:, :, 1] = 0
                        if not values['-RED_MASK-']:
                            self.mask[:, :, 2] = 0

Traitement du masque HSV

Décrit le traitement des masques dans HSV. Les boutons Rouge, Vert et Bleu vous permettent de sélectionner chaque couleur dans une certaine plage. Vous pouvez masquer l'objet en ajustant le seuil tout en regardant la vidéo originale et la vidéo du masque.

                        if self.event == 'Blue':
                            window['-H_MIN SLIDER_MASK-'].update(70)
                            window['-H_MAX SLIDER_MASK-'].update(110)
                            window['-S_MIN SLIDER_MASK-'].update(70)
                            window['-S_MAX SLIDER_MASK-'].update(255)
                            window['-V_MIN SLIDER_MASK-'].update(0)
                            window['-V_MAX SLIDER_MASK-'].update(255)
                            window['-Hue Reverse_MASK-'].update(False)

                        if self.event == 'Green':
                            window['-H_MIN SLIDER_MASK-'].update(20)
                            window['-H_MAX SLIDER_MASK-'].update(70)
                            window['-S_MIN SLIDER_MASK-'].update(70)
                            window['-S_MAX SLIDER_MASK-'].update(255)
                            window['-V_MIN SLIDER_MASK-'].update(0)
                            window['-V_MAX SLIDER_MASK-'].update(255)
                            window['-Hue Reverse_MASK-'].update(False)

                        if self.event == 'Red':
                            window['-H_MIN SLIDER_MASK-'].update(20)
                            window['-H_MAX SLIDER_MASK-'].update(110)
                            window['-S_MIN SLIDER_MASK-'].update(70)
                            window['-S_MAX SLIDER_MASK-'].update(255)
                            window['-V_MIN SLIDER_MASK-'].update(0)
                            window['-V_MAX SLIDER_MASK-'].update(255)
                            window['-Hue Reverse_MASK-'].update(True)

                        self.mask = hsv(
                            self.mask,
                            values['-H_MAX SLIDER_MASK-'],
                            values['-H_MIN SLIDER_MASK-'],
                            values['-S_MAX SLIDER_MASK-'],
                            values['-S_MIN SLIDER_MASK-'],
                            values['-V_MAX SLIDER_MASK-'],
                            values['-V_MIN SLIDER_MASK-'],
                            values['-Hue Reverse_MASK-']
                        )

                        #Échelle de gris
                        self.mask = cv2.cvtColor(
                            self.mask,
                            cv2.COLOR_BGR2GRAY
                        )
                    #Brouiller
                    if values['-BLUR-']:
                        self.frame_roi = cv2.GaussianBlur(
                            self.frame_roi, (21, 21), values['-BLUR SLIDER-']
                        )
                    if values['-GRAY-']:
                        self.frame_roi = cv2.cvtColor(
                            self.frame_roi,
                            cv2.COLOR_BGR2GRAY
                        )
                        self.frame_roi = cv2.cvtColor(
                            self.frame_roi,
                            cv2.COLOR_GRAY2BGR
                        )

Appliquer le traitement uniquement à la plage de masques dans le ROI. J'utilise cv2.bitwise_not de manière imbriquée, mais il existe peut-être une meilleure façon de le faire.

                    if values['-MASKING-']:
                        # frame_Appliquer le masque en ROI
                        #Seule la partie de traitement du masque est frame_Passer au ROI
                        self.frame_roi = cv2.bitwise_not(
                            cv2.bitwise_not(self.frame_roi),
                            self.frame[self.y1:self.y2, self.x1:self.x2, :],
                            mask=self.mask
                        )
                    #Renvoyer le retour sur investissement traité au cadre
                    self.frame[self.y1:self.y2, self.x1:self.x2, :] = self.frame_roi
                #Enregistrer la vidéo
                if self.rec_flg:
                    #Réduisez à nouveau le retour sur investissement après la correction du tremblement de la caméra
                    self.frame_roi = self.frame[
                        self.y1:self.y2, self.x1:self.x2, :
                    ]
                    if values["-GIF-"]:
                        images.append(
                            Image.fromarray(
                                cv2.cvtColor(
                                    self.frame_roi, cv2.COLOR_BGR2RGB
                                )
                            )
                        )
                    else:
                        out.write(self.frame_roi)

                    #Affichage pendant la sauvegarde
                    cv2.putText(
                        self.frame,
                        str("Now Recording"),
                        (20, 60),
                        cv2.FONT_HERSHEY_SIMPLEX,
                        0.5,
                        (10, 10, 255),
                        1,
                        cv2.LINE_AA
                    )

                    # e_Terminer quand il devient un cadre
                    if self.frame_count >= self.e_frame - values["-SKIP SLIDER-"] - 1:
                        if values["-GIF-"]:
                            images[0].save(
                                str((self.fp.parent / (self.fp.stem + '.gif'))),
                                save_all=True,
                                append_images=images[1:],
                                optimize=False,
                                duration=1000 // self.fps,
                                loop=0
                            )
                        else:
                            out.release()
                        self.rec_flg = False

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

                #Lors du calcul du ROI ou en appuyant sur le bouton gauche de la souris
                #Dessinez un rectangle
                if self.roi_flg or self.mouse_flg:
                    cv2.rectangle(
                        self.frame,
                        (self.x1, self.y1),
                        (self.x2 - 1, self.y2 - 1),
                        (128, 128, 128)
                    )

L'image du masque s'affiche uniquement lorsque Masquage est sélectionné.

                #Afficher l'image
                cv2.imshow("Movie", self.frame)
                if values['-MASKING-']:
                    cv2.imshow("Mask", cv2.cvtColor(self.mask, cv2.COLOR_GRAY2BGR))
                    cv2.setWindowProperty("Mask", cv2.WND_PROP_VISIBLE, 0)
                elif not values['-MASKING-'] and cv2.getWindowProperty("Mask", cv2.WND_PROP_VISIBLE):
                    cv2.destroyWindow("Mask")

                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)

                #Autre traitement###############################################
                #Effacer la fenêtre du journal
                if self.event == 'Clear':
                    window['-OUTPUT-'].update('')

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


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

Lien de référence

Reconnaissons les objets rouges avec python Wikipédia: espace colorimétrique HSV Fusion alpha et masquage d'images avec Python, OpenCV, NumPy

Recommended Posts

Créer un lecteur vidéo avec PySimpleGUI + OpenCV 3 Ajout de la fonction de masque
Créer un lecteur vidéo avec PySimpleGUI + OpenCV
Créez un outil d'analyse vidéo simple avec python wxpython + openCV
Créer un décorateur de fonction Python avec Class
Créez une roue de votre propre module OpenCV
Créer une table avec le notebook IPython
Créer une fonction pour décrire les polices japonaises avec OpenCV
Créez un lot d'images et gonflez avec ImageDataGenerator
Créer une application Todo avec Django ⑤ Créer une fonction d'édition de tâches
Créez une caméra de surveillance WEB avec Raspberry Pi et OpenCV
Créez un bot Mastodon avec une fonction pour répondre automatiquement avec Python
Créer une fonction en Python
Créer une page d'accueil avec django
Chargement de la vidéo en boucle avec opencv
Créer un répertoire avec python
Prouvons le théorème d'addition d'une fonction triangulaire en remplaçant la fonction par une fonction dans SymPy (≠ substitution)
Créez une illusion rayée avec correction gamma pour Python3 et openCV3
Si vous donnez une liste avec l'argument par défaut de la fonction ...
J'ai essayé de créer une liste de nombres premiers avec python
Comment créer une étiquette (masque) pour la segmentation avec labelme (masque de segmentation sémantique)
Créez une fonction pour obtenir le contenu de la base de données dans Go
Créez un programme de jugement de compatibilité avec le module aléatoire de python.
Effacez des couleurs spécifiques avec OpenCV + PySimpleGUI
Créez un environnement virtuel avec Python!
Créez un stepper de poisson avec numpy.random
Découpage avec OpenCV-Faire une vidéo voyante-
Créer un téléchargeur de fichiers avec Django
Etude de base d'OpenCV avec Python
[OpenCV; Python] Résumé de la fonction findcontours
Créer un lecteur vidéo avec PySimpleGUI + OpenCV 3 Ajout de la fonction de masque
Créer un lecteur vidéo avec PySimpleGUI + OpenCV
Comment boucler et lire une vidéo gif avec openCV
Créez une caméra de surveillance WEB avec Raspberry Pi et OpenCV
Créez un outil d'analyse vidéo simple avec python wxpython + openCV
Créons une IA à trois voies avec Pylearn2 --Save and load model -
Créez une illusion rayée avec correction gamma pour Python3 et openCV3
Créer un décorateur de fonction Python avec Class
Créons une fonction de chat avec Vue.js + AWS Lambda + dynamo DB [Paramètres AWS]
Diverses méthodes pour créer numériquement la fonction inverse d'une certaine fonction Introduction
Essayez de séparer l'arrière-plan et l'objet en mouvement de la vidéo avec OpenCV