home     zurück
letzte Änderung am 21.02.2016
Erkennung des Bereiches mit Bewegung


Nun will ich im Bild den Bereich mit der Bewegung identifizieren.
Die erste Idee war ein Durchrastern des Bildes mit einer Art binären Suche.
Also erstmal das Bild horizontal halbieren, die hellere Hälfte dann vertikal halbieren, dort die hellere Hälfte wieder horizontal halbieren, u.s.w. bis eine definierte Bildgröße unterschritten wird.
Um das performant umsetzen zu können, bedarf es jedoch einer geeigneten Funktion aus dem reichlichen Vorrat von NumPy.
Also viel zu lesen unter http://docs.scipy.org/doc/numpy/reference/index.html
Erstmal habe ich nach sowas wie "Bit Blit" gesucht - nur eben für Byte statt Bit. War aber nix - oder ich habe es nicht gefunden.
Dann "maskieren". Gibts zwar, aber nicht so, wie ich mir das gedacht hatte.

Schließlich ist es hsplit() bzw. vsplit() geworden.
Und weil ich denen die Anzahl der Splits mitgeben kann, habe ich von dem "binäre Suche"-Ansatz wieder Abstand genommen.
Eine Kachelung in 16 Bild-Bereiche sollte dicke langen. Und die kann ich mit zwei Vierer-Splits erreichen.

Zum Testen habe ich das Bild von gestern mit dem "etwas tieferen Griff" genommen und folgendes Script gebaut.

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-

import os, sys
import time
import datetime
import io
import urllib3
import httplib2
from PIL import Image, ImageFilter, ImageMath
import numpy as np

# ###########################################################
# Main
if __name__=="__main__":
  img=Image.open("2016_02_20_18_48_51-4.jpg")
  arrsh=np.hsplit(imga, 4)
  m=list()
  for x in range(len(arrsh)):
    i2=Image.fromarray(arrsh[x])
    m.append(np.sum(i2))
    i2.save("x%d.jpg"%(x))
  print(m)
  mmi=m.index(max(m))
  print(mmi)

  m=list()
  arrsv=np.vsplit(arrsh[mmi], 4)
  for y in range(len(arrsv)):
    i2=Image.fromarray(arrsv[y])
    m.append(np.sum(i2))
    i2.save("x%dy%d.jpg"%(mmi, y))
  print(m)
  mmj=m.index(max(m))
  print(mmj)

Das Script liefert acht Bilder. Die ersten vier Bilder stammen von dem horizontalen Split.

x0
x1
x2
x3
1.968.049 105.019 107.097 87.470

Aus diesen vier Bildern wird nun das Bild mit der größten Helligkeit zur Weiterverarbeitung ausgewählt.
Hier also das erste Bild ganz links.
Das wird nun in vier vertikale Teil-Bilder zerlegt, um deren jeweilige Helligkeit ermitteln zu können.

x0y0
3.305
x0y1
41.311
x0y2
1.100.342
x0y3
823.091

Ergebnis ist also der Bereich (0, 2).

Weil ich die Teil-Bilder final natürlich nicht mehr als JPG speichern muss, habe ich eine Funktion gebaut, die zu einem Bild die Koordinaten des hellsten Bereiches einer 4x4-Matrix liefert.

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-

import os, sys
import time
import datetime
import io
import urllib3
import httplib2
from PIL import Image, ImageFilter, ImageMath
import numpy as np

# ###########################################################
# Liefert von dem Grauwert-Bild "img" die Koordinaten des
# hellsten Bereiches.
# Das Bild wird dazu in 16 Bereiche gekachelt.
# Die Koordinaten (0, 0) liegen links oben im Bild.
def findBrightestArea(img):
  arr=np.asarray(img)
  arrsh=np.hsplit(arr, 4)       # horizontal in 4 Blöcke zerlegen
  m=list()
  for x in range(len(arrsh)):   # über alle 4 Blöcke
    m.append(np.sum(arrsh[x]))  # Summe des Blocks merken
  mh=m.index(max(m))            # Index des Blocks mit der größten Summe

  m=list()
  arrsv=np.vsplit(arrsh[mh], 4)  # hellsten Block vertikal in 4 Blöcke zerlegen
  for y in range(len(arrsv)):
    m.append(np.sum(arrsv[y]))
  mv=m.index(max(m))
  return(mh, mv)

# ###########################################################
# Main
if __name__=="__main__":
  img=Image.open("2016_02_20_18_48_51-4.jpg")
  t1=time.clock()
  a=findBrightestArea(img)
  t2=time.clock()
  print(a)
  print((t2-t1)*1000, "ms")


Liefert dann sowas:
dede@i5:~/bastelein/ipcam> ./tst5.py
(0, 2)
1.5020000000000033 ms


Positionen anfahren und Bildvergleich


Weitere Erkenntnisse

Ich hatte die Kamera heute auch mal zeitweilig auf der Fensterbank von unserem Schlafzimmer stehen und habe sie die Straße begucken lassen.
Vorbeifahrende Autos wurden von dem gestrigen Programm zuverlässig detektiert, Fußgänger nicht und sich bewegende Äste ebenfalls nicht.
Irgendwann fing es dann zu regnen an und selbst die Wassertropfen, die sich auf dem Fliegengitter vor unserem Schlafzimmer-Fenster gesammelt haben, störten das Programm nicht.
Die halbe Sekunde zwischen zwei Bildern war allerdings zu lang, um jedes mal mindestens zwei Bilder von einem vorbeifahrenden Auto zu erwischen.
Bei 0.1 Sekunden kamen die Bilder häufig mit Störungen. Meist war hier das unterste Viertel des Bildes leicht seitlich verschoben. Und das wurde natürlich immer brav gespeichert....weil....war ja reichlich Bewegung zum vorigen Bild.
Mit 0.2 Sekunden kamen solche Störungen schon seltener, aber gefühlt kam noch ein gestörtes Bild pro Minute.
Daraufhin wollte ich den Video-Stream abgreifen. Das habe ich aber nicht hinbekommen - also speziell: mit urllib3 da einzelne Bilder rauszuholen.
Mit einer anderen Python-Lib würde es vielleicht besser geklappt haben, die gabs aber nur für Python 2.7 und ich will jetzt bei Python 3 bleiben.

Eigentlich finde ich "Autos zählen" ohnehin langweilig. Deren Geschwindigkeit zu messen, wäre schon spannender.
Jedoch sind die etwa fünf Meter unversperrte Sicht auf die Straße wohl etwas zu wenig, um das halbwegs genau machen zu können.
Und wahrscheinlich würde es mich eh nur ärgern, wenn ich dann den Beweis hätte, dass dort einige Spackos mit 60 Km/h längsbrettern, obwohl in beide Richtungen nach jeweils 80 Metern ein "rechts-vor-links" kommt - von der 30'er-Zone, die wir hier haben, mal ganz abgesehen.
Also lasse ich diese Projekt-Idee jetzt sterben.