Skip to content

Instantly share code, notes, and snippets.

@NicolaiSoeborg
Created May 1, 2022 11:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save NicolaiSoeborg/110bb515e4ca94f34a2242f52034aa32 to your computer and use it in GitHub Desktop.
Save NicolaiSoeborg/110bb515e4ca94f34a2242f52034aa32 to your computer and use it in GitHub Desktop.
Motion detection PiCamera
from io import BytesIO
from time import sleep, time
from picamera import PiCamera
from PIL import Image, ImageChops
import numpy as np
def take_image(cam, stream):
stream.seek(0)
# stream.truncate() # resize to current position
print("Taking image")
cam.capture(stream, resize=(320, 240), format='jpeg')
# "Rewind" the stream to the beginning so we can read its content
return Image.open(stream)
def get_entropy(img):
w, h = img.size
a = np.array(img.convert('RGB')).reshape((w*h,3))
h, e = np.histogramdd(a, bins=(16,)*3, range=((0,256),)*3)
prob = h/np.sum(h) # normalize
prob = prob[prob>0] # remove zeros
return -np.sum(prob*np.log2(prob))
if __name__ == '__main__':
idx = 0
streams = [BytesIO(), BytesIO()]
with PiCamera() as cam:
# cam.resolution = (1024, 768)
# Camera warmup (longer => better?)
cam.start_preview()
sleep(2)
imgs = [take_image(cam, streams[i]) for i in range(2)]
while True:
diff = ImageChops.difference(imgs[0], imgs[1])
# arr = np.array(diff)
e = get_entropy(diff)
if e >= 0.2:
print(f"Motion detected: {e}")
diff.save(f"/tmp/diff-{int(time())}-{e}.jpeg")
else:
print(f"No motion: {e}")
sleep(60) # 10 sec
imgs[idx].close()
imgs[idx] = take_image(cam, streams[idx])
idx = (idx + 1) % 2
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment