...um unterhalb von /ramdisk ein File-System im RAM zu erzeugen, auf das mit Benutzer-Rechten schreibend zugegriffen werden kann.
sudo mount -t tmpfs -o size=10% none /ramdisk
class
CamImage: def __init__(self): cam=IP_Cam() self.valid=None tst=None while tst is None: self.raw, self.pil=cam.getImage() try: tst=self.pil.convert('L') except: print("error - reload image") tst=None self.u8=np.asarray(tst, np.uint8) self.s16=np.int16(self.u8) # ########################################################### # Liefert False, wenn das Bild in "self.raw" fehlerhaft ist. def isValid(self): if self.valid is None: t=datetime.datetime.utcnow().strftime("%Y%m%d-%H%M%S-%f") fn="/ramdisk/%s__corrupt.jpg"%(t,) f=open(fn, "wb") f.write(self.raw) f.close() #if ord(self.raw[-2:-1])!=255 or ord(self.raw[-1:])!=217: # FF D9 if self.raw[-2:]!=bytes([255, 217]): self.valid=False print("FF D9") else: rc=subprocess.call(["identify", "-verbose", fn], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) self.valid=(rc==0) if not self.valid: print("identify") if(self.valid): # temp. not remove corrupt images os.remove(fn) return(self.valid) # ########################################################### # Speichert "self.raw" unter dem Dateinamen "filename". def save(self, filename): f=open("/ramdisk/%s.jpg"%(filename,), "wb") f.write(self.raw) f.close() |
def
isValid(self): if self.valid is None: if self.raw[-2:]!=bytes([255, 217]): self.valid=False else: fn="/ramdisk/__tmpimg.jpg" f=open(fn, "wb") f.write(self.raw) f.close() rc=subprocess.call(["identify", "-verbose", fn], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) self.valid=(rc==0) os.remove(fn) return(self.valid) |
#
########################################################### # Liefert ein Histogramm von dem Bild "img" als Array mit # vier Elementen. Vorne die Anzahl der hellen Pixel, hinten # die Anzahl der dunklen. def histogram(img): h, b=np.histogram(img, [0, 60, 120, 180, 255]) return(h[::-1]) # ########################################################### # Liefert 0 bis zu 35 Tupel aus (Histogramm, x, y) für das # in eine 7x5-Matrix zerlegte Bild "arr" als Liste. # Histogramm ist ein Array von vier Werten, bei der # jeder Wert der Pixel-Anzahl einer bestimmter Helligkeit # entspricht. Die hellsten Pixel stehen im ersten Wert, die # dunkelsten Pixel im letzten. # Die Rückgabe-Liste ist absteigend nach den ersten zwei # Werten von Histogramm sortiert. def areasByBrightnessV2(arr, cx=7, cy=5, w=91, h=96): 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] # Segment ausschneiden br=histogram(seg) # Histogramm erstellen if br[1]>0: # nur zum Ergebnis zufügen, wenn hell genug ret_lst.append((br, x, y)) f=lambda x:(x[0][0]*2+x[0][1]) return(sorted(ret_lst, key=f, reverse=True)) |
Das ist so zu interpretieren, dass im Element(4, 0) 10 Pixel oberhalb von 180 und 201 Pixel oberhalb von 120 (und unter 180) vorhanden sind.
[(array([ 10, 201, 458, 8067]), 4, 0), (array([ 9, 189, 631, 7907]), 5, 0), (array([ 0, 31, 197, 8508]), 4, 1), (array([ 0, 5, 94, 8637]), 6, 0), (array([ 0, 1, 11, 8724]), 5, 2)]
if __name__=="__main__": DEBUG=False nervous=False cam=IP_Cam() img1=CamImage() while True: motion_detected=False # True, wenn Bewegung erkannt wurde movement_enable=True # False, wenn nicht neu Positioniert werden soll get_new_image=False # True, um das aktuelle Bild zu verwerfen time.sleep(0.1) img2=CamImage() diff=differenceImageV6(img1.u8, img2.u8) h=histogram(diff) # zur Bestimmung, ob im Bild genug Bewegung vorkommt if h[0]>20 or h[1]>100: # Wenn das Differenzbild mindestens 100 Pixel oberhalb von 120 # oder mindestens 20 Pixel oberhalb von 180 enthält, dann hat # möglicherweise Bewegung stattgefunden. if img1.isValid() and img2.isValid(): # Wenn keins der beiden Bilder defekt empfangen wurde, dann # könnte das tatsächlich Bewegung sein. motion_detected=True else: get_new_image=True if DEBUG: print("fehlerhaft empfangenes Bild") if motion_detected: t=datetime.datetime.utcnow().strftime("%Y%m%d-%H%M%S-%f") if DEBUG: cam.saveImage(img1.u8, "%s-1"%(t,)) cam.saveImage(img2.u8, "%s-2"%(t,)) cam.saveImage(insertRaster(diff), "%s-3"%(t,)) #cam.saveImage(img2.pil, "%s-4"%(t,), raw=True) img2.save("%s-5"%(t,)) print("\ndiff.hist=%s"%(h,), t) else: img2.save("motion-%s"%(t,)) abb=areasByBrightnessV2(diff) # Bild in eine 7x5-Matrix zerlegen if len(abb)==0: # doch nicht genug Bewegung motion_detected=False if motion_detected: if DEBUG: print("len(abb)=", len(abb), abb) hist, x, y=abb[0] if not nervous: if x in (2, 3, 4) and y in (1, 2, 3): # wenn neue Position in der Bildmitte liegt -> nicht neu positionieren movement_enable=False if DEBUG: print("bereits mittig") if movement_enable: if len(abb)>28: # mehr als 28 Elemente über Grundrauschen # Zu viele Bereiche über Grundrauschen bedeutet üblicherweise: # - ein Bild ist entweder verwackelt oder # - die Kamera hat die Helligkeit angepasst. # Das Differenzbild ist jedenfalls unbrauchbar. movement_enable=False get_new_image=True if DEBUG: print("verwackelt", "*"*40) if movement_enable: if not (hist[0]>1 and hist[1]>100): # im anzufahrenden Bereich ist nicht genug Helligkeit movement_enable=False if motion_detected and movement_enable: cam.setLight(0) cam.gotoMatrixElement(x, y) # neue Position anfahren time.sleep(0.2) # auf Stillstand der Kamera warten cam.setLight(2) get_new_image=True if get_new_image: img2=CamImage() # Bild von der neuen Position holen img1=img2 |