Im vorherigen Artikel (https://qiita.com/kurodae/items/ba0d1c7115d1dc9ad7cf) habe ich viel über den Fortschrittsbalken geschrieben. In diesem Artikel werde ich versuchen, selbst so etwas wie einen Videoplayer zu erstellen. (Kein Ton ...) Ursprünglich wurde Video Player von kivy bereitgestellt, um die Ergebnisse der Videoanalyse (Objekterkennung usw.) zu visualisieren. /api-kivy.uix.videoplayer.html), aber ich habe versucht, einen anpassbaren Player zu erstellen. Wie der Titel schon sagt, fiel es mir schwer, die Suchleiste für den Videoplayer zu implementieren. Daher schreibe ich diesen Artikel für den Informationsaustausch.
Wie eingangs erwähnt, dient der Zweck der Visualisierung der Videoanalyseergebnisse. Installieren Sie daher die Bibliothek opencv für die Videoanalyse (Bildanalyse).
Meine Betriebsumgebung ist wie folgt.
OSX 10.14.6 Python 3.7.2
Wenn Sie pip verwenden, können Sie es mit nur dem folgenden Befehl installieren.
pip install python-opencv
Zitiert aus Wiki Ich werde.
Die Suchleiste ist eine der Funktionen der Musik- / Videowiedergabesoftware usw. und zeigt den Wiedergabeort von Daten an. Anhand der Position des "Schiebereglers" können Sie visuell erfassen, wie weit Sie Musik oder Filme vom Anfang bis zum Ende abspielen. Sie können den Schieberegler direkt mit der Maus bewegen und von jedem Ort aus mit der Wiedergabe beginnen Es gibt Vorteile wie.
Seek Bar ist eine Art Schieberegler. Was ist ein Schieberegler? [wiki](https://ja.wikipedia.org/wiki/%E3%82%A6%E3%82%A3%E3%82%B8%E3%82%A7%E3%83%83%E3%83 Es wird aus% 88_ (GUI) #% E9% 81% B8% E6% 8A% 9E) zitiert.
Schieberegler - Ähnlich einer Bildlaufleiste, jedoch ein Widget zum Festlegen eines Werts, nicht zum Scrollen.
kivy verfügt über ein Widget Slider, sodass Sie es zu einer Suchleiste machen können.
Ich fühle mich so.
Die Quelle ist wie folgt.
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.clock import Clock
Builder.load_string('''
<MySlider>
orientation: 'vertical'
Label :
text: "{}".format(slider.value)
font_size: slider.value
Slider:
id: slider
step: 1
min: 200
max: 500
Button:
text: "press"
on_press: root.move_slider_start()
''')
class MySlider(BoxLayout):
def __init__(self, **kwargs):
super(MySlider, self).__init__(**kwargs)
def move_slider_start(self):
Clock.schedule_interval(self.move_slider, 1 / 60)
def move_slider(self, dt):
slider = self.ids['slider']
if slider.max > slider.value:
slider.value += 1
else:
return False
class sliderTest(App):
def build(self):
return MySlider()
sliderTest().run()
Die Quelle ist, dass der Wert des Schiebereglers mit dem Text und der Schriftart der Beschriftung am oberen Bildschirmrand verknüpft ist und sich die Beschriftung ändert, wenn der Schieberegler bewegt wird. Ich habe auch einen Prozess hinzugefügt, um den Schiebereglerwert kontinuierlich mit der Uhr zu aktualisieren, wenn Sie die Taste unten drücken (ich werde später etwas Ähnliches mit dem Videoplayer tun).
In der kv-Sprache wird der Beschriftungstext mithilfe der Slider-ID aktualisiert.
Label :
text: "{}".format(slider.value)
font_size: slider.value
Slider:
id: slider #Ich würde. Es kann in kv-Sprache oder Python aufgerufen werden.
step: 1 #Der Mindestwert beim Bewegen des Schiebereglers. Wenn Sie es nicht einstellen, erhalten Sie einen fehlerhaften Float-Wert
min: 200 #Mindestwert des Schiebereglers
max: 500 #Maximalwert des Schiebereglers
Wählen Sie beim automatischen Verschieben des Schiebereglers außerdem das Widget aus "IDs" aus, in denen die dem Widget zugewiesene ID als assoziatives Array gespeichert ist, und ändern Sie die Parameter wie unten gezeigt. Wie im vorherigen Artikel kann es nicht mit der for-Anweisung betrieben werden, daher habe ich den Schiebereglerwert mit Clock geändert und die Bildschirmzeichnung aktualisiert.
def move_slider(self, dt):
slider = self.ids['slider'] #Hier!
if slider.max > slider.value:
slider.value += 1
else:
return False
Das Bild, das ich dieses Mal machen möchte, ist in der folgenden Abbildung dargestellt.
Es ist wie ein Videoplayer mit nur minimalen Funktionen. Sie müssen lediglich das Video laden, abspielen, einen beliebigen Wiedergabestandort angeben und die aktuelle Anzahl der Bilder überprüfen.
Das Video ist wie der Umgang mit opencv.
VideoApp.py
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.graphics.texture import Texture
from kivy.properties import ObjectProperty
from kivy.clock import Clock
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.popup import Popup
import cv2
Builder.load_file('VideoApp.kv')
#Popup zur Videoauswahl
class LoadDialog(FloatLayout):
load = ObjectProperty(None)
cancel = ObjectProperty(None)
class MyVideoPlayer(BoxLayout):
image_texture = ObjectProperty(None)
image_capture = ObjectProperty(None)
def __init__(self, **kwargs):
super(MyVideoPlayer, self).__init__(**kwargs)
self.flagPlay = False #Wird das Video abgespielt?
self.now_frame = 0 #Variable zum Überprüfen des Wiedergaberahmens des Videos auf Suchleiste
self.image_index = [] #Array zum Speichern von OpenCV-Bildern für die Suchleiste
#Popup zum Laden des Videos
def fileSelect(self):
content = LoadDialog(load = self.load, cancel = self.dismiss_popup)
self._popup = Popup( title="File Select", content=content, size_hint=(0.9,0.9))
self._popup.open()
#Laden von Videodateien
def load (self, path, filename):
txtFName = self.ids['txtFName']
txtFName.text = filename[0]
self.image_capture = cv2.VideoCapture(txtFName.text)
self.sliderSetting()
self.dismiss_popup()
#Popup schließen
def dismiss_popup(self):
self._popup.dismiss()
#Suchen Sie nach Balkeneinstellungen
def sliderSetting(self):
count = self.image_capture.get(cv2.CAP_PROP_FRAME_COUNT)
self.ids["timeSlider"].max = count
#Laden Sie das Video einmal und speichern Sie alle Frames in einem Array
while True:
ret, frame = self.image_capture.read()
if ret:
self.image_index.append(frame)
else:
self.image_capture.set(cv2.CAP_PROP_POS_FRAMES, 0)
break
#Video-Wiedergabe
def play(self):
self.flagPlay = not self.flagPlay
if self.flagPlay == True:
self.image_capture.set(cv2.CAP_PROP_POS_FRAMES, self.now_frame)
Clock.schedule_interval(self.update, 1.0 / self.image_capture.get(cv2.CAP_PROP_FPS))
else:
Clock.unschedule(self.update)
#Verarbeitung der Videowiedergabeuhr
def update(self, dt):
ret, frame = self.image_capture.read()
#Wenn der nächste Frame gelesen werden kann
if ret:
self.update_image(frame)
time = self.image_capture.get(cv2.CAP_PROP_POS_FRAMES)
self.ids["timeSlider"].value = time
self.now_frame = int(time)
#Suchleiste
def siderTouchMove(self):
Clock.schedule_interval(self.sliderUpdate, 0)
#Bildschirmzeichnungsprozess, wenn die Suchleiste verschoben wird
def sliderUpdate(self, dt):
#Wenn der Suchbalkenwert und der Wiedergaberahmenwert unterschiedlich sind
if self.now_frame != int(self.ids["timeSlider"].value):
frame = self.image_index[self.now_frame-1]
self.update_image(frame)
self.now_frame = int(self.ids["timeSlider"].value)
def update_image(self, frame):
##############################
#Schreiben Sie hier die Bildverarbeitungsquelle! !!
##############################
#auf den Kopf stellen
buf = cv2.flip(frame, 0)
image_texture = Texture.create(size=(frame.shape[1], frame.shape[0]), colorfmt='bgr')
image_texture.blit_buffer(buf.tostring(), colorfmt='bgr', bufferfmt='ubyte')
video = self.ids['video']
video.texture = image_texture
class TestVideo(App):
def build(self):
return MyVideoPlayer()
TestVideo().run()
kv-Datei
VideoApp.kv
<MyVideoPlayer>:
orientation: 'vertical'
padding: 0
spacing: 1
BoxLayout:
orientation: 'horizontal'
padding: 0
spacing: 1
size_hint: (1.0, 0.1)
TextInput:
id: txtFName
text: ''
multiline: False
Button:
text: 'file load'
on_press: root.fileSelect()
BoxLayout:
orientation: 'horizontal'
padding: 0
spacing: 1
Image:
id: video
BoxLayout:
orientation: 'horizontal'
padding: 0
spacing: 1
size_hint: (1.0, 0.1)
Slider:
id: timeSlider
value: 0.0
max: 0.0
min: 0.0
step: 1
on_touch_move: root.siderTouchMove()
BoxLayout:
orientation: 'horizontal'
padding: 0
spacing: 1
size_hint: (1.0, 0.1)
ToggleButton:
size_hint: (0.2, 1)
text: 'Play'
on_press: root.play()
Label:
size_hint: (0.2, 1)
text: str(timeSlider.value) + "/" + str(timeSlider.max)
<LoadDialog>:
BoxLayout:
size: root.size
pos: root.pos
orientation: 'vertical'
FileChooserListView:
id: filechooser
path: "./"
BoxLayout:
size_hint_y : None
height : 30
Button:
text: 'Cancel'
on_release: root.cancel()
Button:
text: 'Load'
on_release: root.load(filechooser.path, filechooser.selection)
Wenn Sie es ausführen, können Sie es so spielen oder die Suchleiste verschieben. Das Video wurde von der Website hier ausgeliehen.
Das Video selbst wird in der gleichen Dosis wie opencvs Video Cupture abgespielt. Ich bin sicher, niemand hat es verwendet, aber es ist, als würde man ein Video Frame für Frame mit einer while-Anweisung lesen und anzeigen (so / python-opencv-videocapture-file-camera /)). Wenn Sie für oder während verwenden, friert es wieder ein. Verwenden Sie also Clock.
#Verarbeitung der Videowiedergabeuhr
def update(self, dt):
ret, frame = self.image_capture.read()
#Wenn der nächste Frame gelesen werden kann
if ret:
self.update_image(frame) #Verarbeitung zum Kopieren auf den Bildschirm
time = self.image_capture.get(cv2.CAP_PROP_POS_FRAMES) #Ermitteln Sie die Anzahl der Frames für die Suchleiste
self.ids["timeSlider"].value = time #Ersetzen Sie den Suchleistenwert durch die Anzahl der Wiedergabebilder
self.now_frame = int(time) #Zum Verschieben der Suchleiste
Verwenden Sie beim Anzeigen eines Bildes auf kivy eine Klasse namens Texture mit `` `blit_buffer```. Behandeln Sie das Bild als Puffer. Zu diesem Zeitpunkt stehen die Bilddaten von opencv auf dem Kopf. Fügen Sie daher einen Prozess hinzu, um sie zu invertieren. Auf diese Weise können Sie die Videowiedergabefunktion auf die gleiche Weise wie bei der normalen openCV-Videowiedergabe implementieren. Die Bildverarbeitung wird diesmal nicht ausgeführt. Wenn Sie hier jedoch eine Verarbeitung wie opencv hinzufügen, können Sie die Verarbeitungsergebnisse problemlos visualisieren.
def update_image(self, frame):
##############################
#Schreiben Sie hier die Bildverarbeitungsquelle! !!
##############################
#auf den Kopf stellen
buf = cv2.flip(frame, 0)
image_texture = Texture.create(size=(frame.shape[1], frame.shape[0]), colorfmt='bgr')
image_texture.blit_buffer(buf.tostring(), colorfmt='bgr', bufferfmt='ubyte')
video = self.ids['video']
video.texture = image_texture
In der Videosuchleiste zunächst aus der Set-Funktion (Funktion, die den Wiedergaberahmen angibt) der VideoCupter-Klasse von opencv Ich habe versucht, eine Suchleiste zu implementieren, indem ich den Slider-Wert auf die Bildnummer des Videos angewendet habe. Als ich es implementierte, wurde die Operation jedoch extrem schwer. Da die Set-Funktion ein sehr schwerer Prozess zu sein scheint, habe ich nach einer anderen Implementierungsmethode gesucht.
Infolgedessen war es einfach zu implementieren, indem die Bilddaten von opencv so gespeichert wurden, wie sie sich im Array befinden, und der Wert von Slider dem Index des Array von Bildern zugeordnet wurde. Daher wird beim Lesen eines Videos ein Prozess bereitgestellt, mit dem das Video einmal abgespielt und dem Array zugewiesen werden kann.
Da das einmal geladene VideoCupture im Programm wiederverwendet wird, müssen Sie "self.image_capture.set (cv2.CAP_PROP_POS_FRAMES, 0)" angeben, um die Wiedergabeposition des Videos in den Ausgangszustand zurückzusetzen , Sie können das Video nicht abspielen.
#Suchen Sie nach Balkeneinstellungen
def sliderSetting(self):
count = self.image_capture.get(cv2.CAP_PROP_FRAME_COUNT) #Holen Sie sich die Anzahl der Bilder in einem Video
self.ids["timeSlider"].max = count #Ersetzen Sie den Maximalwert des Schiebereglers durch die Anzahl der Videobilder
#Laden Sie das Video einmal und speichern Sie alle Frames in einem Array
while True:
ret, frame = self.image_capture.read()
if ret:
self.image_index.append(frame)
else:
#Kehren Sie nach dem Lesen zum letzten Bild zum ersten Bild zurück
self.image_capture.set(cv2.CAP_PROP_POS_FRAMES, 0)
break
Vielen Dank für all die Hilfe, die Sie mir gegeben haben.
Anzeigen von Bildern mit Opencv oder Pillow mit Python Kivy Umgang mit Texturen usw.
Erste Schritte mit Python 7: Wählen Sie eine Datei aus und spielen Sie das technische Memo eines Video-Akirachin ab Vielen Dank für das Video.
Recommended Posts