home     zurück
letzte Änderung am 27.02.2016

Kamera-Nachführung bei Bewegungserkennung V3

Nun habe ich doch mal eine Funktion gebaut, die den Grauwert aller Matrix-Elemente ermittelt und als Liste liefert.
Es ist schon von Vorteil, wenn das Script nicht nur das hellste bzw. bewegteste Element zur Entscheidungsfindung heranziehen kann.
Mittels countHigherThan() kann nun auch das Verhältnis der bewegten Bereiche über das gesamte Differenz-Bild mit in die Entscheidung, ob Um-positioniert werden soll, einbezogen werden.

# ###########################################################
# Liefert 35 Tupel aus (Grauwert, x, y) für das in eine
# 7x5-Matrix zerlegte Bild "arr" als Liste.
# Die Rückgabe-Liste ist absteigend nach Grauwert sortiert.
def areasByBrightness(arr):
  cx=7  # Anzahl Elemente auf der X-Achse
  cy=5  # Anzahl Elemente auf der Y-Achse
  w=91  # Breite eines Elements
  h=96  # Höhe eines Elements

  ret_lst=list()
  for x in range(cx): # über die Segmente auf der X-Achse
    for y in range(cy): # über die Segmente auf der Y-Achse
      seg=arr[y*h:y*h+h, 1+x*w:1+x*w+w]
      br=np.sum(seg)
      ret_lst.append((br, x, y))
  f=lambda x:x[0]
  return(sorted(ret_lst, key=f, reverse=True))

# ###########################################################
# Liefert die Anzahl der Listenelemente aus "lst", die über
# dem Wert "above" liegen. Die Liste muss aus Dreier-Tupeln
# bestehen, der erste Wert des Tupels wird gegen "above"
# geprüft.
def countHigherThan(lst, above):
  cnt=0
  for a, x, y in lst:
    if a>above:
      cnt+=1
  return(cnt)

# ###########################################################
# Main
if __name__=="__main__":
  DEBUG=False
  nervous=False   # False für weniger Bewegungen
  cam=IP_Cam()

  img1=cam.getImageGrayscale()
  while True:
    movement_enable=True  # False für keine neue Positionierung aber DEBUG-Bearbeitung
    time.sleep(0.1)
    img2=cam.getImageGrayscale()

    diff=cam.removeNoise(img1-img2)
    diff_sum=np.sum(diff)

    if diff_sum<500000:   # keine Bewegung im Bild
      continue

    diff_sum_p="{:,}".format(diff_sum)
    t=datetime.datetime.utcnow().strftime("%Y%m%d-%H%M%S-%f")
    l=areasByBrightness(diff)
    c100K=countHigherThan(l, 100000)
    c5K=countHigherThan(l, 5000)
    a, x, y=l[0]

    if a<50000: # das hellste Element ist nicht hell genug
      continue

    if not nervous:
      if x in (1, 2, 3, 4, 5) and y in (1, 2, 3):
        movement_enable=False

    if diff_sum>4000000:  # zu viel "Bewegung" im Bild
      movement_enable=False

    if c100K>=12:         # in zu vielen Elementen ist Bewegung
      movement_enable=False

    if c5K>28: # zu viele Elemente oberhalb vom Grundrauschen
      movement_enable=False

    if DEBUG:
      print("\n%10s %d %d (%d, %d) %s"%(diff_sum_p, x, y, c100K, c5K, str(l)))
      cam.saveImage(img1, "d_%s-1"%(t))
      cam.saveImage(img2, "d_%s-2"%(t))
      cam.saveImage(diff, "d_%s-d(%d,%d)-%s-%d-%d"%(t, x, y, diff_sum_p, c100K, c5K))

    if movement_enable:
      cam.gotoMatrixElement(x, y)
      time.sleep(0.2)

    img2=cam.getImageGrayscale()
    img1=img2

Damit kommt es schon zu deutlich weniger Fehl-Bewegungen.
Aber der Fuß-Fetisch bleibt.
Außerdem lässt sich das Script -speziell bei starkem Gegenlicht- durch Schatten oder Reflektionen verwirren.
Das sind jedoch unwesentliche Sonderfälle.... ;-)
Damit könnte man dieses Projekt als abgeschlossen betrachten.

Ein lustiges Feature ist mir noch aufgefallen: das Signal von Infrarot-Fernbedienungen ist auf dem "Live Video" sichtbar.

Und noch das gesamte Script zum runterladen.

Kleiner Nachtrag:
Ein RaspberryPi (Model B Revision 2.0 mit "2016-02-09-raspbian-jessie-lite.img") kommt mit dem Script schon etwas ins schwitzen, schafft es aber.
top meldet fast konstant sowas hier:
  PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND
 7084 dede      20   0   34448  22924   9776 S 52,7  5,1   1:02.38 python3

Mit Raspbian Wheezy wollte Pillow nicht so recht.
Bei Raspbian Jessie hat ein:
sudo apt-get install python3-pillow
gereicht. Es wurde dann zwar gemeldet:
Note, selecting 'python3-pil' instead of 'python3-pillow'
Aber danach hat es funktioniert.


Auf meinem BananaPi habe ich gleich einen dist-upgrade auf Jessie gemacht.
Danach lief der
sudo apt-get install python3-urllib3 python3-httplib2 python3-pillow python3-numpy
sauber durch.
Der BananaPi hat etwas mehr Saft, als der RaspberryPi. Hier meldet top höchstens mal:
  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
 1162 dede      20   0   30476  17624   4484 S  33,9  1,8   0:14.09 python3

Und hier noch ein paar weitere Erkenntnisse.