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.
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.
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.
La plage entre les curseurs gauche et droit de Hue est la plage de masque.
L'extérieur des curseurs gauche et droit de Hue est la plage de masque. Vous pouvez inverser la plage de masque.
Vous pouvez enregistrer une plage spécifiée de vidéos au format DIVX, MJEG, GIF.
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)
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
)
],
])
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, :
]
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
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()
Reconnaissons les objets rouges avec python Wikipédia: espace colorimétrique HSV Fusion alpha et masquage d'images avec Python, OpenCV, NumPy
Recommended Posts