Ankündigung

Einklappen
Keine Ankündigung bisher.

Wasserzähler per Webcam auslesen

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

    [-] Wasserzähler per Webcam auslesen

    Hallo --

    Nach dem Strom hab' ich schon länger damit geliebtäugelt, den Wasserverbrauch zu erfassen.

    Meine Wasseruhr ist so ein Ding: http://www.nk-se.de/uploads/pics/Gnswzal2.jpg

    Impulse sind da nicht, eine zweite Uhr hinter die vom Versorger wollte ich nicht unbedingt einbauen, und die Berichte, die man im Netz über Ableseköpfe, gekauft oder selbst gebaut, findet, sind auch meist nicht ermutigend.

    Aber da lag noch diese Webcam, vor Jahren mal für x,99 aus der Grabbelkiste gefischt, die mit 320x240 Pixel Auflösung nicht wirklich für was Sinnvolles taugte.

    Da ich überhaupt keine Motivation zum Anstreichen hatte, wurde das Ding flugs 'professionell' an der Wasseruhr befestigt, und ich war erstaunt, dass da doch ein Bild rauskommt.

    Der ideale Bildausschnitt - das habe ich mir erst nachher überlegt - ist, dass man einen der runden Zähler (bei mir der Literzähler) etwa halb auf dem Bild sehen möchte. Die Erkennung kann man dann nämlich darauf basieren, dass relativ viel Rot vom Zeiger auf dem Bild ist.

    Die Auswertung erfolgt mit Python - man möge meinen Code freundlichst kommentieren, gestern früh wusste ich noch nicht, wie Python aussieht. Ich habe in erster Linie Code-Fragmente aus dem www zusammengeklebt.

    Die Logik ist folgende:

    Ein Frame wird aus der Kamera gelesen.
    Es wird verwischt, dann verkleinert (von 320x240 auf 40x30px), damit es schneller rechnet.
    Dann wird nach rot gesucht, und ein Threshold gebildet, der rot zu weiss und alles andere zu schwarz schiebt.
    Das Resultat ist ein schwarzes Bild mit einem mehr oder weniger grossen weissen Blob.
    Die schwarzen Pixel werden gezählt (bei einem 40x30 Bild maximal 1200)
    Wenn es recht wenige schwarze Pixel sind, heisst das, dass die Zählernadel auf dem Bild ist, und es wird eine 1 auf die Zähler-GA geschickt (braucht eine Hilfsvariable, damit es nicht bei jedem folgenden Frame triggert).
    Wenn es wieder recht viele schwarze Pixel sind, wird die Hilfsvariable zurückgesetzt.
    ... und dann wieder von vorne.

    Zum Konfigurieren habe ich mir Originalbild und transformiertes Bild sowie die Zahl der schwarzen Pixel anzeigen lassen. So konnte ich relativ schnell die Thresholds finden, ab denen der Zähler erscheint bzw verschwindet.

    Das werkelt jetzt seit gestern mittag und hat auf gut 200 Liter Verbrauch gerade mal 2 Liter 'verpasst' - und da gehe ich bei einem davon aus, dass es an dem Default-Wert-setzen beim Start-Up lag. Der Maximaldurchfluss in der Zeit dürfte etwa 12 Liter/Minute betragen haben, das wäre also eine Umdrehung etwa alle 5 Sekunden. Unter der Annahme, dass der Trigger in einem Winkel von 45 Grad erkennt, bräuchte man etwa acht Bilder pro Umdrehung, um keine Umdrehung zu verpassen. Das sollte auch bei 30 Liter/Minute also noch passen. Der Code läuft hier auf einem komfortabel ausgestatteten Linux-Rechner so nebenher und fällt nicht auf, was die Rechenlast angeht.

    SWMBO war nicht begeistert. Anstreichen muss ich trotzdem, heute oder morgen...

    Code:
    #!/usr/bin/env python
    
    import cv2
    import numpy as np
    import os
    import time
    
    debug = 0    # if debug show windows with stream and console info
    
    if debug:
        cv2.namedWindow("original")     # open window for original stream
        cv2.namedWindow("transform")    # open window for transformed stream
    
    vc = cv2.VideoCapture(-1)           # capture from first /dev/video device
    
    if vc.isOpened():                   # try to get the first frame
        rval, frame = vc.read()         # read frame
        print frame.shape               # frame shape gives width, heigh, color
    else:
        rval = False
    
    lasttrigger = 0                     # init the trigger
    while rval:
        img=cv2.GaussianBlur(frame, (9,9), 9)               # blur the image
        reduce=cv2.resize(img, (40,30))                     # reduce the size for faster processing
        hsv = cv2.cvtColor(reduce, cv2.COLOR_BGR2HSV)       # change color scheme to HSV
        red_lower=np.array([150,150,0],np.uint8)            # between this and
        red_upper=np.array([190,255,255],np.uint8)          # this is red
        thresh = cv2.inRange(hsv, red_lower, red_upper)     # check for redness
        hist = cv2.calcHist([thresh],[0],None,[1],[0,1])    # transform red to white, anything else to black
    
        if debug:
            cv2.imshow("original", frame)                   # show the original image
            cv2.imshow("transform", thresh)                 # show the transformed image. should be white
                                                            # pointer on black background
            print hist[0]                                   # this shows blackness of the image. if the image
                                                            # is 40x30, it can have maximum 1200 black pixels
                                                            # if the pointer is not there, should be close to
                                                            # that value
    
        if hist[0] > 1150 and lasttrigger == 1:             # if we triggered and it's very black, trigger to 0
            print 0
            lasttrigger=0
        elif hist[0] < 1130 and lasttrigger == 0:           # if it's less black, trigger to 1
            lasttrigger=1
        os.system('/usr/bin/groupwrite "ip:192.168.4.6" "8/0/0" 1')   # send a knx write
        rval, frame = vc.read()                             # next frame
        if debug:
            key = cv2.waitKey(10)                           # exit on escape key (in debug mode)
            if key == 27: # exit on ESC
               break
    
    if debug:
        cv2.destroyWindow("original")                       # make the windows go away
        cv2.destroyWindow("transform")
    Angehängte Dateien

    #2
    Schöne Idee!
    Mutig das Bild der Aufhängung zu Posten.
    Ich warte schon auf den ersten, der vom Gruselkabinett spricht und Bedenken anmeldet, was ist, wenn der Zählerablesemann kommt. Ich hol mir schonmal Popcorn!

    Gruß,
    Hendrik

    Kommentar


      #3
      Zitat von henfri Beitrag anzeigen
      Schöne Idee!
      Mutig das Bild der Aufhängung zu Posten.
      Ich warte schon auf den ersten, der vom Gruselkabinett spricht und Bedenken anmeldet, was ist, wenn der Zählerablesemann kommt. Ich hol mir schonmal Popcorn!
      Ah, geh... erstens kommt hier sowieso keiner ablesen, das macht der Kunde selbst. Und die Befestigung ist sowieso provisorisch, und auf dem Foto nicht komplett: ich hab' zur Vermeidung von Fremdlichteinflüssen noch eine alte Baseballkappe drübergehängt

      Genau so bleibt das Ding jetzt mal eine Woche oder zwei stehen. Wie der Franzose sagt: c'est le provisoire qui dure.

      Kommentar


        #4
        :-)))

        Kommentar


          #5
          Zitat von henfri Beitrag anzeigen
          Schöne Idee!
          Mutig das Bild der Aufhängung zu Posten.
          Ich warte schon auf den ersten, der vom Gruselkabinett spricht und Bedenken anmeldet, was ist, wenn der Zählerablesemann kommt. Ich hol mir schonmal Popcorn!
          Ich möchte lieber die Reaktion vom Gaszählermann sehen, wenn er die Auswertung auch auf die anderen Medien erweitert.

          Markus

          Kommentar


            #6
            Deine Webcam hat eine eingebaute LED oder hast du da selbst noch eine drangemacht?

            Sehr geniale Lösung - Mich interessiert noch dann der "Wertverlust" auf mehrer Wochen.

            Kommentar


              #7
              Ui noch einer der mit OpenCV rumspielt . Ich mach das ganze nur in C++, aber das ist ja egal.
              Gruß
              Saihtam

              >>> www.phoenixcontact.de <<<

              Kommentar


                #8
                Was die Reaktion der Zählerableser angeht, ist die mir relativ egal. Das 'Schlimmste', was kommen kann, ist ja, dass ich die Kamera abschraube und 5 Minuten später wieder anschraube. Ich wüsste nicht, wie das bei Gas anders aussähe, aber ich habe keinen Gaszähler.

                Die Kamera hat in der Tat eine kleine LED zur Beleuchtung. Viel kommt nicht bei raus, aber für meine Applikation reicht es.

                Der Fehler ist jetzt bei 4 Liter, bei anderthalb Kubik Durchfluss. Maximale Zapfleistung etwa 30 Liter/Minute, also alle 2 Sekunden eine Umdrehung des Zeigers.

                Kommentar


                  #9
                  Hammer!

                  Finde ich eine super Idee und dann noch mit fertiger Umsetzung.

                  Sicher etwas "Umweg" gerade was Rechenleistung angeht - aber du sagst ja dass sich der Rechner eh langweilt. Zumal dass ja auch für 20 andere Sachen taugt...

                  Toll finde ich die Verwendung von OpenCV in Python - mir war gar nicht bewusst dass es so schön kompakt geht.

                  Weitere Ideen wo evtl. Reflexlichtschranken etc nicht funktionieren: "welches Auto in Garage - evtl. mit Farbe?", "Postpaket im Eingang" etc.

                  Bzgl. Zähler: Evtl. mal schauen, ob die Fehldetektionen durch Fremdlicht kommen? Dann könnte eine 'Helligkeitskorrektur helfen bzw. die in der Kamera integrierte mal bewusst an- oder abschalten. Ansonsten evtl. Kontrast erhöhen, in dem man den hellsten und den dunkelsten Punkt sucht und dann entsprechend hochrechnet?

                  Vielen Dank fürs Teilen! Daumen hoch!

                  Grüße
                  Robert

                  /edit: Zwei Sachen noch: Habe ich es Überlesen, oder wie beleuchtest du das ganze? Zum anderen: Evtl. - ohne mich jetzt in OpenCV auszukennen - wäre es noch sicherer doch den ganzen Vollkreis zu filmen und dann zu versuchen den Zeigerwinkel zu detektieren. Denn der Zeiger muss ja dann auf jeden Fall "da" sein. So könnte man auch von einem Bild zum nächsten entsprechend filtern (Kalman o.Ä. - man hat eine Vorherhersage der Zeigerstellung vom letzten Zyklus und der Bewegung und eine neue Messung aufgrund des neuen Bildes).
                  HM-KNX - KNX-Interface für Hörmann Garagentorantriebe: http://www.ing-budde.de

                  Kommentar


                    #10
                    Hallo Robert --

                    Die Sache mit Python und Openvc hat mich auch umgehauen - ich hatte mich nie mit Python an sich beschäftigt, und war erstaunt, wieviel da möglich ist.

                    Beleuchtung ist in der Tat durch eine kleine in der Kamera verbaute LED. Was die Genauigkeit angeht, werde ich mich momentan da nicht weiter reinsteigern. Auf 1500 Liter 4 Liter Fehler ist zwar nicht schön, aber noch sehr gut zu verschmerzen.

                    Ich wollte zuerst auch die Zählerstellung ablesen, indem ich die ganze Skala erfasse, nach diesem Ansatz:

                    solem's vision blog: Reading Gauges - Detecting Lines and Circles

                    Da hätte ich den 10-Liter-Zähler abgelesen und ein Bild alle paar Sekunden hätte gereicht.

                    Aber dann hätte ich die Kamera mit Abstand montieren und dafür eine Halterung bauen müssen. Ausserdem sind die Anzeigen ganz am Rand der Wasseruhr, das gibt dann alles mögliche an optischer Verzerrung, und die Nadeln sind auch nicht schmal und gerade, sondern so knubbelig in der Mitte mit dreieckiger Spitze... das wäre kompliziert geworden.

                    Kommentar


                      #11
                      also ich finde die Lösung ist gelngen...klar ist die Befestigung provisorisch, aber die Umsetzung ist top...mit Binäreingängen etc. funktioniert es ja auch nicht viel genauer...

                      Kommentar


                        #12
                        Sehr coole Lösung. Das könnte ich bei mir auch einsetzen. CPU Leistung hab ich noch übrig.

                        Danke für diesen Denkanstoß.

                        Gruß
                        Alex

                        Kommentar


                          #13
                          Meint ihr nicht ob es auch Interessant wäre, statt einer USB Lösung , eine POE IP Kamera zu verwenden? Da wäre die Leitungslänge doch Ideal.
                          Aber ob es damit technisch genauso gut funktioniert?

                          Kommentar


                            #14
                            Sicherlich. Treibt nur den Preis in die Höhe...

                            Kommentar


                              #15
                              Auf eBay laufen irgendwie immer "alte" Axis 209FD-R IP-Kameras für etwas 100€, dafür tuns die auf jeden Fall.

                              Wenn ich mich nicht verrechnet hab sind die 4 Liter auf die 1,5m^3 übrigens 0.2667%, nicht schlecht würde ich sagen

                              Kommentar

                              Lädt...
                              X