Threading beim einlesen zweier Kamerasignale mittels OpenCV

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
gerrit_heinemann
User
Beiträge: 5
Registriert: Samstag 18. Februar 2017, 18:03

Sehr geehrte Foren Mitglieder,

ich suche eine Hilfestellung bei einem Problem, welches ich bei der Benutzung von OpenCV 3.1.0 und Python 2.7.9 habe. Ich möchte zwei Kameras (USB) zu einem Stereo-Kamerasystem machen und habe bereits einen funktionierendes Programm geschrieben, doch ist dies sehr langsam, da es nachweislich nur auf einem Kern läuft. Ich habe aber auf dem Raspberry Pi 3 Modell B 4 Kerne und möchte diese auch nutzen. Ich habe mal die ersten Zeilen (Einlesen der Kamerasignale) versucht Beispielsweise für mein Komplettes Programm zu threaden, doch tauchen immer wieder Fehler auf.

Code: Alles auswählen

import cv2
import threading

class Einlesen(threading.Thread):
    
    def __init__(self,thread_id, name, nummer, thread_lock):
        threading.Thread.__init__(self)
        self.thread_id=thread_id
        self.__nummer = nummer
        self.__name = name
        self.thead_lock = thread_lock
        
    def run(self):
        print ("Starting ")               
        kamera = cv2.VideoCapture(self.__nummer)
        kamera.set(cv2.CAP_PROP_FRAME_WIDTH, 434)
        kamera.set(cv2.CAP_PROP_FRAME_HEIGHT, 240)

        if (kamera.isOpened()):
            print "Signal erkannt"
            while True:
                kamera.grab()
                ret, bild = kamera.retrieve()
                cv2.imshow(self.__name, bild)
                key = cv2.waitKey(50) & 0xFF
                if (key == ord('q')):
                    print "Ende"
                    break
          else:
             print "Fehler"
        cv2.destroyAllWindows()
                
def Main():
    thread_lock = threading.Lock()
    t1 = Einlesen(1, "Kamera_Links", 0, thread_lock)
    t2 = Einlesen(2, "Kamera_Rechts", 1, thread_lock)
    t1.start()
    t2.start()

if __name__ == '__main__':
    Main()

Fehler:
- Beide Fenster zeigen nur ein und das selbe Kamerabild an, anstatt ein Echtzeitvideo
- Kein Fenster wird geöffnet und Python schreibt in der Shell nur zwei mal "Starting" und danach startet sich die Shell einfach neu


Ich würde mich sehr über eure Hilfe freuen und danke euch im Voraus.
Zuletzt geändert von Anonymous am Samstag 18. Februar 2017, 18:38, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
__deets__
User
Beiträge: 14528
Registriert: Mittwoch 14. Oktober 2015, 14:29

Python kann kein "echtes" multi-threading. Das liegt am sogenannten GIL, dem Global Interpreter Lock. Allerdings ist das nur fuer "reinen" Python-Code relevant - C-Erweiterungen (wie OpenCV) *koennen* zumindest dieses GIL "loslassen", und dann kann theoretisch ein zweiter Thread arbeiten.

Da kommt es dann auf die konkrete Implementierung an. Dazu koenntest du mal ein Experiment machen: wenn du ein einfaches Testskript schreibst, welches nur eine Kamera einliest, und es einfach zweimal startest - wie sieht dann die Auslastung aus?

Insgesamt muss ich sagen klingt dein Vorhaben etwas sehr ambitioniert. Die Multimedia-Faehigkeiten des PI ruehren von optimierten Implementierungen auf der GPU her. Prozessor und Speicherinterface sind nicht so besonders fix, und zwei Streams selbst zu verarzten ggf. einfach unmoeglich - auch in purem C++.
__deets__
User
Beiträge: 14528
Registriert: Mittwoch 14. Oktober 2015, 14:29

Und noch ein Nachtrag: versuch mal statt beide streams darzustellen *nur* die Bildacquise zu machen. Es kann naemlich sein, dass highgui da auch noch ein Woertchen mitzureden hat.
gerrit_heinemann
User
Beiträge: 5
Registriert: Samstag 18. Februar 2017, 18:03

Hi Deets,
Vielen Dank für deine Antwort. Die Anwendung habe ich bereits erstellt und mittels Python auf dem Pi zum Laufen gebracht (siehe Link) Beide Kameras werden zeitgleich dargestellt. Ein Speichern und Verarbeiten ist möglich und das Schachbrettmuster wird auch erkannt. Nur möchte ich jetzt ein bisschen die Geschwindigkeit erhöhen, um eine flüssige Objekterkennung durchführen zu können.

Deswegen bin ich auf das Threading gestoßen. Gibt es vielleicht auch eine andere Möglichkeit die Performance anzukurbeln?

https://1drv.ms/i/s!AiahH1Dk3jZS2H9ytXSjDqV3x612
__deets__
User
Beiträge: 14528
Registriert: Mittwoch 14. Oktober 2015, 14:29

Das die Anwendung laeuft habe ich ja nicht bestritten. Nur das sie performant zu bekommen ist.

Ich habe dir schon die Tipps gegeben, die man geben kann:

- benutze zwei Prozesse, in denen du jeweils nur eine Kamera verarbeitest.
- probiere, ob die *Ausgabe* der Bilder das Problem darstellt, und klemm dir die.

Falls du zwei Prozesse benutzt, und das ganze skaliert, dann kannst du im naechsten Schritt das Python modul "multiprocessing" verwenden. Damit kannst du dann die extrahierten Daten in einem Vaterprozess zusammenfuehren und weiterverarbeiten.
gerrit_heinemann
User
Beiträge: 5
Registriert: Samstag 18. Februar 2017, 18:03

__deets__ hat geschrieben: - benutze zwei Prozesse, in denen du jeweils nur eine Kamera verarbeitest.
- probiere, ob die *Ausgabe* der Bilder das Problem darstellt, und klemm dir die.
Habe ich nicht bereits 2 Prozesse erstellt, indem ich t1 und t2 geschrieben habe?
Ich versuche morgen die Videosignale in zwei Dateien zu schreiben und schaue, ob ich damit erfolgreich bin.
__deets__
User
Beiträge: 14528
Registriert: Mittwoch 14. Oktober 2015, 14:29

Nein, damit hast du zwei THREADs erstellt. Eben *KEINE* Prozesse.

Und klar, du kannst auch wegschreiben, wuerde ich aber gar nicht machen. Das verfaelscht ja nur. Du willst ja nicht speichern.
gerrit_heinemann
User
Beiträge: 5
Registriert: Samstag 18. Februar 2017, 18:03

__deets__ hat geschrieben:Nein, damit hast du zwei THREADs erstellt. Eben *KEINE* Prozesse.
Ok verstehe, ich werde mir die Bib dazu noch einmal durchlesen. Hatte wohl auf das Falsche Pferd gesetzt.
Danke
gerrit_heinemann
User
Beiträge: 5
Registriert: Samstag 18. Februar 2017, 18:03

Ich soll also den Punkt 17.2.1.1 - The Process Class unter https://docs.python.org/3/library/multiprocessing.html mir angucken?
__deets__
User
Beiträge: 14528
Registriert: Mittwoch 14. Oktober 2015, 14:29

ZB, ja. Und dann natuerlich jeweils nur mit einer Kamera einlesen etc.
Antworten