Hallo,
ich bin mal wieder auf ein Problem gestoßen, dass ich mit Google wohl einfach nicht lösen kann...
Folgendes sind die von mir importierten Module:
from tkinter import *
from tkinter.filedialog import askopenfilename
from threading import Thread
from PIL import Image, ImageTk
import cv2
import threading
import os
import time
import pickle
Und ein Ausschnitt des Codes meines Video Editors:
global Medien_Importierungen, Maximale_Breite, Maximale_Höhe
Videopfad = askopenfilename(filetypes =[('Video Files', '*.mp4')])
Geladenes_Video = cv2.VideoCapture(Videopfad)
Rückgabe, Einzelbild = Geladenes_Video.read()
if Einzelbild.shape[0] / Maximale_Höhe > Einzelbild.shape[1] / Maximale_Breite:
height = Maximale_Höhe
width = int(Einzelbild.shape[1] * height / Einzelbild.shape[0])
else:
width = Maximale_Breite
height = int(Einzelbild.shape[0] * width / Einzelbild.shape[1])
Einzelbild = cv2.resize(Einzelbild, (width, height))
Tkinter_Bild = ImageTk.PhotoImage(image=Image.fromarray(cv2.cvtColor(Einzelbild, cv2.COLOR_BGR2RGB)))
Thumbnail = Label(Medien, image = Tkinter_Bild)
if Medien_Importierungen % 2 == 0:
Thumbnail.place(x = Fenster.winfo_screenwidth() * 0.01, y = Fenster.winfo_screenheight() / 10 + (Fenster.winfo_screenwidth() * 0.01 + Maximale_Höhe) * (int(Medien_Importierungen / 2)))
else:
Thumbnail.place(x = Fenster.winfo_screenwidth() * 0.11, y = Fenster.winfo_screenheight() / 10 + (Fenster.winfo_screenwidth() * 0.01 + Maximale_Höhe) * (int(Medien_Importierungen / 2)))
Medien_Importierungen += 1
Statt einem Bild wird jetzt nur ein weißes Bild angezeigt. Durch das verdoppeln der Zeile, in der ich die Funktion
Geladenes_Video.read()
angewendet habe, wurde auch nichts gelöst...
Bitte helft mir...
Alex
Wieso wird das Bild nicht richtig angezeigt?
Das ist nicht der gesamte relevante Code, so dass man hier nur raten kann.
Wahrscheinlich existiert Tkinter_Bild nicht dauerhaft, was es aber muß, damit das Bild im Speicher bleibt und angezeigt werden kann.
Threads und GUIs sind ein schwieriges Thema, wo man auch viel falsch machen kann, was zu komischen Effekten führen kann.
*-Importe machen den Code unübersichtlich, weil man nicht nachvollziehen kann, woher welcher Name stammt.
Globale Variablen darf es nicht geben, weil sonst nicht klar ist, wo welche Variable verwendet wird.
pickle ist nur dann sinnvoll, wenn man kurzzeitig Daten serialisieren möchte, z.B. um sie von einer Instanz zu einer anderen über ein Netzwerk zu übertragen. Den Anwendungsfall sehe ich bei Dir nicht.
Variablen werden generell komplett klein geschrieben, um sie von Klassen unterscheiden zu können.
place bentutzt man nicht. Du scheinst ja die Bilder in einem Grid anordnen zu wollen, dafür ist grid ideal.
Statt Echter Division, um gleich danach das Ergebnis in ein int umzuwandeln, benutzt man Ganzzahldivision //.
Wahrscheinlich existiert Tkinter_Bild nicht dauerhaft, was es aber muß, damit das Bild im Speicher bleibt und angezeigt werden kann.
Threads und GUIs sind ein schwieriges Thema, wo man auch viel falsch machen kann, was zu komischen Effekten führen kann.
*-Importe machen den Code unübersichtlich, weil man nicht nachvollziehen kann, woher welcher Name stammt.
Globale Variablen darf es nicht geben, weil sonst nicht klar ist, wo welche Variable verwendet wird.
pickle ist nur dann sinnvoll, wenn man kurzzeitig Daten serialisieren möchte, z.B. um sie von einer Instanz zu einer anderen über ein Netzwerk zu übertragen. Den Anwendungsfall sehe ich bei Dir nicht.
Variablen werden generell komplett klein geschrieben, um sie von Klassen unterscheiden zu können.
place bentutzt man nicht. Du scheinst ja die Bilder in einem Grid anordnen zu wollen, dafür ist grid ideal.
Statt Echter Division, um gleich danach das Ergebnis in ein int umzuwandeln, benutzt man Ganzzahldivision //.
- __blackjack__
- User
- Beiträge: 14047
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
Ergänzend: Konstanten werden KOMPLETT_GROSS geschrieben um sie leichter als solche zu erkennen und es macht keinen Sinn die als ``global`` zu deklarieren, denn Konstanten ändert man ja nicht.
Der Code geht nicht sauber damit um falls der Anwender den Dateiuauswahldialog abbricht statt eine Datei auszuwählen.
`Rückgabe` ist ein sehr generischer Name und auch hier wird nicht darauf reagiert falls das Bild aus dem Video nicht geladen wurde. Genau dafür ist dieser Wert ja da. Die OpenCV-Methoden und Funktionen arbeiten mit Fehlerrückgabewerten statt mit Ausnahmen, da muss man also selber aufpassen und prüfen.
Wonach wurde eigentlich entschieden wann ein Name deutsch und wann englisch sein soll?
`Medien` und `Fenster` kommen aus dem ”nichts”, das scheinen also auch globale Variablen zu sein, was nicht sein sollte. Bei GUI-Anwendungen kommt man nicht um objektorientierte Programmierung herum.
Bei der Entscheidung ob die Medienanzahl gerade oder ungerade ist, scheint eine Menge kopierter Code zu sein, der sich nur an *einer* Stelle in einem Zahlenwert unterscheidet.
Zwischenstand:
Aber wie Sirius3 schon erwähnte, sollte das `place()` nicht verwendet werden. Und falls es nicht *wirklich* wichtig ist die Grössenänderung von OpenCV erledigen zu lassen, bietet PIL eine Funktion um Vorschaubilder zu erstellen, wo man sich die eigenhändige Berechnung sparen kann. Dann bliebe am Ende so etwas:
Der Code geht nicht sauber damit um falls der Anwender den Dateiuauswahldialog abbricht statt eine Datei auszuwählen.
`Rückgabe` ist ein sehr generischer Name und auch hier wird nicht darauf reagiert falls das Bild aus dem Video nicht geladen wurde. Genau dafür ist dieser Wert ja da. Die OpenCV-Methoden und Funktionen arbeiten mit Fehlerrückgabewerten statt mit Ausnahmen, da muss man also selber aufpassen und prüfen.
Wonach wurde eigentlich entschieden wann ein Name deutsch und wann englisch sein soll?
`Medien` und `Fenster` kommen aus dem ”nichts”, das scheinen also auch globale Variablen zu sein, was nicht sein sollte. Bei GUI-Anwendungen kommt man nicht um objektorientierte Programmierung herum.
Bei der Entscheidung ob die Medienanzahl gerade oder ungerade ist, scheint eine Menge kopierter Code zu sein, der sich nur an *einer* Stelle in einem Zahlenwert unterscheidet.
Zwischenstand:
Code: Alles auswählen
def importiere_medium(self):
videodateiname = askopenfilename(filetypes=[("Video Files", "*.mp4")])
if videodateiname:
is_ok, bild = cv2.VideoCapture(videodateiname).read()
if is_ok:
if (
bild.shape[0] / MAXIMALE_HOEHE
> bild.shape[1] / MAXIMALE_BREITE
):
height = MAXIMALE_HOEHE
width = bild.shape[1] * height // bild.shape[0]
else:
width = MAXIMALE_BREITE
height = bild.shape[0] * width // bild.shape[1]
photo_image = ImageTk.PhotoImage(
image=Image.fromarray(
cv2.cvtColor(
cv2.resize(bild, (width, height)),
cv2.COLOR_BGR2RGB,
)
)
)
thumbnail = tk.Label(self.medien_widget, image=photo_image)
thumbnail.place(
x=(
self.winfo_screenwidth()
* (0.01 if self.medienanzahl % 2 == 0 else 0.11)
),
y=(
self.winfo_screenheight() / 10
+ (self.winfo_screenwidth() * 0.01 + MAXIMALE_HOEHE)
* (self.medienanzahl // 2)
),
)
self.medienanzahl += 1
Code: Alles auswählen
def importiere_medium(self):
videodateiname = askopenfilename(filetypes=[("Video Files", "*.mp4")])
if videodateiname:
is_ok, bilddaten = cv2.VideoCapture(videodateiname).read()
if is_ok:
bild = Image.fromarray(
cv2.cvtColor(bilddaten, cv2.COLOR_BGR2RGB)
)
bild.thumbnail((MAXIMALE_BREITE, MAXIMALE_HOEHE))
photo_image = ImageTk.PhotoImage(image=bild)
zeilenindex, spaltenindex = divmod(self.medienanzahl, 2)
thumbnail = tk.Label(self.medien_widget, image=photo_image)
thumbnail.grid(row=zeilenindex, column=spaltenindex)
self.medienanzahl += 1
“Vir, intelligence has nothing to do with politics!” — Londo Mollari