Webcam Livebild in PyQt5 anzeigen

Python und das Qt-Toolkit, erstellen von GUIs mittels des Qt-Designers.
Antworten
okliw994
User
Beiträge: 26
Registriert: Dienstag 11. Juni 2019, 09:49

Hallo zusammen,

Ich möchte über eine Benutzeroberfläche ein Pop-Up-Fenster öffnen um mir ein Livebild anzuzeigen. Ein neues Fenster zu öffnen und den Buttons Funktionen zuzuweisen funktioniert ohne Probleme. Die Fenster erstelle ich mit dem QtDesigner. Des Weiteren kann ich mir mit folgendem Code ein Livebild anzeigen lassen.

Code: Alles auswählen

	cam = cv2.VideoCapture(0)
        while(True):
            	ret_val, img = cam.read()
            	cv2.imshow('LB', img)
            	if cv2.waitKey(1) == 27:
                	break
        cv2.destroyAllWindows()
Mein Problem ist, dass ich das im Code erzeugte Livebild nur über die ESC-Taste schließen kann. Mein System soll am Ende aber ohne Tastatur/nur mittels eines Touchscreens arbeiten. Daher möchte ich das Livebild in einem Fenster darstellen, welches einen Button zum schließen hat.
Kann mir jemand sagen, wie ich das Livebild mit dem Fenster verknüpfe / gemeinsam öffne?

Gruß, okliw994
__deets__
User
Beiträge: 14539
Registriert: Mittwoch 14. Oktober 2015, 14:29

Nicht mit opencv. Das zielt mit seiner highgui darauf ab, einen simplen und unkomplizierten Weg anzubieten, Fenster und eine Reihe von GUI controls darzustellen.

In dem Moment, wo du eine echte GUI drum rum willst, kommt die mit der highgui in Konflikt. Stattdessen muss dein Qt Programm die Kontrolle übernehmen, und per Timer die Frames aus dem capture holen. Wie zb hier: http://benhoff.net/face-detection-opencv-pyqt.html
Benutzeravatar
__blackjack__
User
Beiträge: 13107
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@okliw994: Randbemerkung: Die Klammern beim ``while`` gehören da nicht hin. Das ist keine Funktion, sollte also auch nicht so geschrieben werden als wäre es eine.

Ausserdem ist die Einrückung falsch. Man rückt vier Leerzeichen pro Ebene ein. Keine Tabs und schon gar nicht Tabs und Leerzeichen gemischt.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
okliw994
User
Beiträge: 26
Registriert: Dienstag 11. Juni 2019, 09:49

Erstmal Danke für eure Antworten.
Sorry, die Klammern waren wohl reine Gewohnheit aus Java und das mit der Einrückung werde ich zukünftig beachten.

Gibt es denn eine andere Möglichkeit das Fenster, welches mit dem oben gezeigten Code erzeugt wird, ohne Tastatur zu schließen?
__deets__
User
Beiträge: 14539
Registriert: Mittwoch 14. Oktober 2015, 14:29

Was passt dir an dem vorgeschlagenen Weg nicht? Und was ist an "Nicht mit opencv" unklar?
okliw994
User
Beiträge: 26
Registriert: Dienstag 11. Juni 2019, 09:49

Für den vorgeschlagenen Weg fehlen mir anscheinend zu viel Vorkenntnisse um diesen zu verstehen.
Wie kann ich denn sonst die Webcam ohne opencv nutzen? Gibt es noch andere Bibliotheken?

MfG, okliw994
__deets__
User
Beiträge: 14539
Registriert: Mittwoch 14. Oktober 2015, 14:29

Du kannst stattdessen QMultiMedia nehmen. Ob das ohne Vorkenntnisse besser funktioniert wage ich aber zu bezweifeln. Du kannst auch opencv und dem Maus-callback eine GUI von Hand Stricken. Das ist ein bisschen durch die Brust ins Auge, aber je nach Anwendung ggf ok.
__deets__
User
Beiträge: 14539
Registriert: Mittwoch 14. Oktober 2015, 14:29

Um das nochmal klarzustellen: du hast von einer Qt5 Integration gesprochen. DAS geht nicht anders als gezeigt. highgui kann Maus Ereignisse, und natürlich kannst du damit auch eine Interaktion bauen. Wird allerdings mühselig.
Benutzeravatar
__blackjack__
User
Beiträge: 13107
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Pygame hat eine (experimentelle) API für Webcams. Wenn es Dir reicht wenn der Benutzer irgendwo klicken kann oder Du Code für eine Schaltfläche selber schreiben möchtest. Wäre dann halt auch keine Qt-Anwendung. Wenn Du Qt willst, musst Du Dich wohl oder übel mit Qt auseinandersetzen.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
__deets__
User
Beiträge: 14539
Registriert: Mittwoch 14. Oktober 2015, 14:29

Aber pygame liefert ihm die Bilder nicht direkt so wie OpenCV sie braucht. Das erfordert dann wieder den Erwerb dieser vermaledeiten Vorkenntnisse...
Benutzeravatar
__blackjack__
User
Beiträge: 13107
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@__deets__: Okay, wenn man die Bilder danach irgendwie mit OpenCV weiterverarbeiten will, dann wäre es natürlich ziemlich unsinnig etwas anderes als OpenCV für das lesen der Bilder von der Webcam zu verwenden.

Einen OpenCV-Frame — also eigentlich ja ein Numpy-Array — in ein Pygame-Surface umzuwandeln ist aber auch nicht sooo schwer. Im Grunde muss man AFAIK nur die BGR→RGB-Konvertierung mit der passenden OpenCV-Funktion machen und dann mit der passenden Pygame-Funktion aus dem Numpy-Array ein Pygame-Surface. Die Frage ist halt was da noch an GUI-Anforderungen sind.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
__deets__
User
Beiträge: 14539
Registriert: Mittwoch 14. Oktober 2015, 14:29

Nach einem Beispiel per Timer ein OpenCV-capture auslesen und darstellen ist auch nicht sooo schwer ;) Das ist halt mein Punkt: man wird sich schon ein bisschen reinknieen muessen, wenn man zwei solche Technologien miteinander verheiraten will. Egal wo man am Ende landet.
Benutzeravatar
__blackjack__
User
Beiträge: 13107
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Ich habe da mal was gebastelt:

Code: Alles auswählen

#!/usr/bin/env python3
import sys
from contextlib import closing
from functools import partial

from PyQt5.QtCore import QTimer
from PyQt5.QtGui import QImage, QPixmap
from PyQt5.QtWidgets import QApplication
from PyQt5.uic import loadUi
import cv2

VIDEO_SOURCE = 0

def iter_frames(video_source):
    video = cv2.VideoCapture(video_source)
    if not video.isOpened():
        raise IOError(f'video source {video_source!r} could not be opened')
    try:
        while True:
            is_ok, frame = video.read()
            if not is_ok:
                break
            yield frame
    finally:
        video.release()


def image_from_frame(frame):
    assert frame.itemsize == 1
    height, width, bytes_per_color = frame.shape
    assert bytes_per_color == 3
    return QImage(
        frame.data, width, height, frame.strides[0], QImage.Format_RGB888
    ).rgbSwapped()


def display_next_image(timer, label, images):
    try:
        image = next(images)
    except (StopIteration, IOError):
        timer.stop()
    else:
        label.setPixmap(QPixmap.fromImage(image))


def main():
    application = QApplication(sys.argv)
    
    ui = loadUi('test.ui')
    ui.exit_button.clicked.connect(ui.close)

    with closing(iter_frames(VIDEO_SOURCE)) as frames:
        timer = QTimer(ui)
        timer.timeout.connect(
            partial(
                display_next_image,
                timer,
                ui.image_label,
                map(image_from_frame, frames),
            )
        )
        timer.start(50)
        ui.show()
        
        sys.exit(application.exec_())


if __name__ == '__main__':
    main()
Die UI-Datei:

Code: Alles auswählen

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>Form</class>
 <widget class="QWidget" name="Form">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>400</width>
    <height>300</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Cam</string>
  </property>
  <layout class="QVBoxLayout" name="verticalLayout">
   <item>
    <widget class="QLabel" name="image_label"/>
   </item>
   <item>
    <widget class="QPushButton" name="exit_button">
     <property name="text">
      <string>Stop</string>
     </property>
     <property name="checkable">
      <bool>false</bool>
     </property>
     <property name="checked">
      <bool>false</bool>
     </property>
    </widget>
   </item>
  </layout>
 </widget>
 <resources/>
 <connections/>
</ui>
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Antworten