Opencv Buffersize lässt sich nicht einstellen
Du kannst die frame-acquise in einen Thread auslagern, und dir immer nur den letzten Frame merken, und anzeigen. Das sollte das Problem loesen. Dazu ist aber der Einstieg in die OO-Programmierung empfehlenswert, denn sonst bekommst du die diversen Beteiligten nicht unter Kontrolle. Mit global jedenfalls faengst du dir auf Dauer Probleme ein, weil das zu unuebersichlich wird.
- __blackjack__
- User
- Beiträge: 14378
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@bachatero18: Bitte ``global`` sofort wieder vergessen. Alles was eine Funktion oder Methode ausser Konstanten benötigt, wird als Argument(e) übergeben.
Damit fallen dann die Zuweisungen an `w` und `top_level` weg, wobei `w` auch ein sehr schlechter Name ist.
Dann ist die Zuweisung an `root` unsinnig weil Du nun das gleiche Objekt in der Funktion als `root` und `top` hast, und auch noch beide Namen verwendest. Warum? Was ist das Entscheidungskriterium mal den einen und mal den anderen Namen für das *selbe* Objekt im *selben* Namensraum zu verwenden?
Die Argumente `gui`, `args`, und `kwargs` werden nicht verwendet.
`Kamera_ID` ist falsch geschrieben. Entweder ist das eine Konstante, dann KOMPLETT_GROSS, oder es ist eine variable, dann klein_mit_unterstrichen und dann muss das auch als Argument übergeben werden.
Namen sollten keine kryptischen Abkürzungen enthalten oder gar nur daraus bestehen. `cap` hat als Wort eine Bedeutung („Kappe“), könnte aber beispielsweise auch eine Abkürzung für `capability` sein.
`label_cam` ist falsch herum wenn man nicht Yoda ist.
Funktionen sollte man in der Regel nicht verschachteln, solange die nicht sehr trivial sind oder man die tatsächlich für ein Closure *braucht*.
Mit den mindestens 50 Millisekunden zwischen den `show_frame()`-Aufrufen darf die Kamera maximal 20 Bilder pro Sekunde liefern, sonst gibt's Stau. Wobei man die Aufruffrequenz besser deutlich niedriger ansetzt als die Bildwiederholrate der Kamera, zum Beispiel halb so gross wie nötig. Der `read()`-Aufruf blockiert dann ja entsprechend bis das nächste Bild dann tatsächlich zur Verfügung steht. Also entweder bei `after()` den Wert für die Wartezeit entsprechend der gelieferten Bildrate anpassen, oder die Bildrate an den Wert bei `after()` anpassen. Oder eine Kombination. Also zum Beispiel bei `after()` etwas zwischen 8 und 10 um bei 60 Bildern pro Sekunde auf der sicheren Seite zu sein.
Man sollte das erste Argument im Tupel das `read()` zurückgibt nicht einfach ignorieren. Das geht solange gut bis das mal nicht gut geht und der Code auf die Nase fällt weil `frame` nichts ethält.
`hsv` ist ein verdammt schlechter Name für Bilddaten die gar nicht im HSV- sondern im RGB-Format sind.
Ungetestet:
Damit fallen dann die Zuweisungen an `w` und `top_level` weg, wobei `w` auch ein sehr schlechter Name ist.
Dann ist die Zuweisung an `root` unsinnig weil Du nun das gleiche Objekt in der Funktion als `root` und `top` hast, und auch noch beide Namen verwendest. Warum? Was ist das Entscheidungskriterium mal den einen und mal den anderen Namen für das *selbe* Objekt im *selben* Namensraum zu verwenden?
Die Argumente `gui`, `args`, und `kwargs` werden nicht verwendet.
`Kamera_ID` ist falsch geschrieben. Entweder ist das eine Konstante, dann KOMPLETT_GROSS, oder es ist eine variable, dann klein_mit_unterstrichen und dann muss das auch als Argument übergeben werden.
Namen sollten keine kryptischen Abkürzungen enthalten oder gar nur daraus bestehen. `cap` hat als Wort eine Bedeutung („Kappe“), könnte aber beispielsweise auch eine Abkürzung für `capability` sein.
`label_cam` ist falsch herum wenn man nicht Yoda ist.
Funktionen sollte man in der Regel nicht verschachteln, solange die nicht sehr trivial sind oder man die tatsächlich für ein Closure *braucht*.
Mit den mindestens 50 Millisekunden zwischen den `show_frame()`-Aufrufen darf die Kamera maximal 20 Bilder pro Sekunde liefern, sonst gibt's Stau. Wobei man die Aufruffrequenz besser deutlich niedriger ansetzt als die Bildwiederholrate der Kamera, zum Beispiel halb so gross wie nötig. Der `read()`-Aufruf blockiert dann ja entsprechend bis das nächste Bild dann tatsächlich zur Verfügung steht. Also entweder bei `after()` den Wert für die Wartezeit entsprechend der gelieferten Bildrate anpassen, oder die Bildrate an den Wert bei `after()` anpassen. Oder eine Kombination. Also zum Beispiel bei `after()` etwas zwischen 8 und 10 um bei 60 Bildern pro Sekunde auf der sicheren Seite zu sein.
Man sollte das erste Argument im Tupel das `read()` zurückgibt nicht einfach ignorieren. Das geht solange gut bis das mal nicht gut geht und der Code auf die Nase fällt weil `frame` nichts ethält.
`hsv` ist ein verdammt schlechter Name für Bilddaten die gar nicht im HSV- sondern im RGB-Format sind.
Ungetestet:
Code: Alles auswählen
def show_frame(video, width, height, camera_image_label):
is_ok, frame = video.read()
if is_ok:
image = ImageTk.PhotoImage(
image=Image.fromarray(
cv2.cvtColor(
cv2.resize(frame, (width * 1, height * 1)),
cv2.COLOR_BGR2RGB,
)
)
)
camera_image_label.image = image
camera_image_label.configure(image=image)
camera_image_label.after(
10, show_frame, video, width, height, camera_image_label
)
def init(window, kamera_id, width, height):
window.protocol("WM_DELETE_WINDOW", destroy_window)
window.state("zoomed")
video = cv2.VideoCapture(kamera_id)
video.set(cv2.CAP_PROP_FRAME_WIDTH, width)
video.set(cv2.CAP_PROP_FRAME_HEIGHT, height)
camera_image_label = tk.Label(window)
camera_image_label.pack()
show_frame(video, width, height, camera_image_label)Who is General Failure and why is he reading my hard disk?
- __blackjack__
- User
- Beiträge: 14378
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@bachatero18: Also erst mal habe ich da nichts an der Bildrate geändert, die kommt ja von der Kamera, und wenn die Bilder bei Dir verzögert kommen, dann ist die halt momentan grösser als die 20 Bilder/Sekunde mit der Dein Code maximal gerade mal so klar gekommen wäre. Meiner käme auch mit 60 Bildern/Sekunde klar. Wenn Du nur 10 brauchst, musst Du das der Kamera sagen, dass die nur 10 liefern soll und nicht wie viel auch immer die per Voreinstellung liefert. Und dann ginge der Wert von 50 Millisekunden bei `after()` auch klar.
Falls die Kamera nicht auf die FPS-Einstellung von OpenCV reagiert, Du also die Bildwiederholrate nicht beeinflussen kannst — solche Kombinationen von Kamera-Hardware und Treiber/Backend gibt es wohl — dann müsstest Du das tatsächlich in einen Thread auslagern und eben so viel/schnell lesen wie die Kamera Bilder liefert und einfach Bilder verwerfen. Beispielsweise eine Queue mit einer Maximallänge von eins zwischen die beiden Threads hängen.
Falls die Kamera nicht auf die FPS-Einstellung von OpenCV reagiert, Du also die Bildwiederholrate nicht beeinflussen kannst — solche Kombinationen von Kamera-Hardware und Treiber/Backend gibt es wohl — dann müsstest Du das tatsächlich in einen Thread auslagern und eben so viel/schnell lesen wie die Kamera Bilder liefert und einfach Bilder verwerfen. Beispielsweise eine Queue mit einer Maximallänge von eins zwischen die beiden Threads hängen.
Who is General Failure and why is he reading my hard disk?
- __blackjack__
- User
- Beiträge: 14378
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@bachatero18: Ich weiss nicht ob Dir die Zusammenhänge so ganz klar sind: Doch Du musst bei der Kamera bestimmen wie viel FPS die verwenden soll. Die FPS werden bei der Kamera festgelegt, nicht dadurch wie oft pro Sekunde man `read()` aufruft. Wenn man 100 mal die Sekunde `read()` aufruft bekommt man dadurch nicht 100 FPS geliefert. Beziehungsweise kann man wenn die Kamera beispielsweise 60 FPS liefert gar nicht 100 mal in der Sekunde `read()` aufrufen, weil dieser Aufruf ja *blockiert* und das abrufen damit automatisch auf die 60 FPS drosselt. Die Wartezeit bei `after()` muss nur kurz genug sein, damit sich keine Bilder aufstauen. Andererseits muss man auch aufpassen die Wartezeit nicht *zu* kurz zu machen, weil dann unnötig Zeit von der GUI im blockierenden `read()`-Aufruf verschwendet wird.
Who is General Failure and why is he reading my hard disk?
