Advertisement
jbeale

Motion-Detection in Python on Raspberry Pi

Sep 20th, 2014
522
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 3.85 KB | None | 0 0
  1. #!/usr/bin/python
  2.  
  3. # Simple motion-detection using the picamera library.
  4. # Runs at up to 10 fps depending on resolution, etc.
  5. # This is demonstration / proof-of-concept code.
  6. # It probably isn't useful in a real application.
  7. # Nov. 30 2013 J.Beale
  8.  
  9. from __future__ import print_function
  10. import io, os, time, datetime, picamera, cv2
  11. import numpy as np
  12.  
  13. #width = 32
  14. #height = 16 # minimum size that works ?
  15. width =144
  16. height = 96
  17. frames = 0
  18. first_frame = True
  19. frac = 0.05  # fraction to update long-term average on each pass
  20. a_thresh = 16.0  # amplitude change detection threshold for any pixel
  21. pc_thresh = 20   # number of pixels required to exceed threshold
  22. avgmax = 3     # long-term average of maximum-pixel-change-value
  23. tfactor = 2  # threshold above max.average diff per frame for motion detect
  24. picHoldoff = 1.0  # minimum interval (seconds) between saving images
  25. fupdate = 10000   # report debug data every this many frames
  26. #fupdate = 10   # report debug data every this many frames
  27. logfile = "/home/pi/pics/cam-log.csv"
  28.  
  29. np.set_printoptions(precision=2)
  30. f = open(logfile, 'a')
  31. f.write ("# cam log v0.1 Nov.28 2013 JPB\n")
  32. outbuf = "# Start: " +  str(datetime.datetime.now()) + "\n"
  33. f.write (outbuf)
  34. f.flush()
  35.  
  36. daytime = datetime.datetime.now().strftime("%y%m%d-%H_%M_%S.%f")
  37. daytime = daytime[:-3]  # remove last three digits (xxx microseconds)
  38. print ("# Start at %s" % str(datetime.datetime.now()))
  39.  
  40. stream = io.BytesIO()
  41. with picamera.PiCamera() as camera:
  42.     camera.resolution = (width, height)
  43.     camera.start_preview()
  44.     time.sleep(2)
  45.     start = time.time()
  46.     while True:
  47.       camera.capture(stream, format='jpeg', use_video_port=True)
  48. #      time.sleep(0.15)  # sometimes delay needed to avoid crashes (!?)
  49.       stream.seek(0)
  50.       data = np.fromstring(stream.getvalue(), dtype=np.uint8)
  51.       image = cv2.imdecode(data, 1)
  52.       image = image.astype(np.float32)
  53.       (h,w,cols) = image.shape
  54.       (xc,yc) = (h/2,w/2)
  55.       frames = frames + 1
  56.       if (frames % fupdate) == 0:
  57.         print ("%s,  %03d max = %5.3f, avg = %5.3f" % (str(datetime.datetime.now()),frames,max,avgmax))
  58. #       print (avgcol); print (avgdiff)
  59. #       print "%02d center: %s (BGR)" % (frames,image[xc,yc])
  60.       if first_frame == False:
  61.         newcol = image[:,:,1] # full image, green only
  62.         avgcol = (avgcol * (1.0-frac)) + (newcol * frac)
  63.         diff = newcol - avgcol  # matrix of difference-from-average pixel values
  64.         diff = abs(diff)   # take absolute value of difference
  65.         avgdiff = ((1 - frac)*avgdiff) + (frac * diff)  # long-term average difference
  66.         a_thresh = tfactor*avgmax  # adaptive amplitude-of-change threshold
  67.         condition = diff > a_thresh
  68.         changedPixels = np.extract(condition,diff)
  69.         countPixels = changedPixels.size
  70.         max = np.amax(diff)     # find the biggest (single-pixel) change
  71.         avgmax = ((1 - frac)*avgmax) + (max * frac)
  72.         if countPixels > pc_thresh:  # notable change of enough pixels => motion!
  73.           now = time.time()
  74.           interval = now - start
  75.           start = now
  76.           daytime = datetime.datetime.now().strftime("%y%m%d-%H_%M_%S.%f")
  77.           daytime = daytime[:-3]  # remove last three digits (xxx microseconds)
  78.           daytime = daytime + "_" + str(countPixels)
  79.           tstr = ("%s,  %04.1f, %6.3f, %03d\n" % (daytime,max,interval,countPixels))
  80.           print (tstr, end='')
  81.           f.write(tstr)
  82.           f.flush()
  83.           if (interval > picHoldoff):  # don't write images more quickly than picHoldoff interval
  84.             imgName = daytime + ".jpg"
  85.             cv2.imwrite(imgName, image)  # save as an image
  86.       else:         # very first frame
  87.         avgcol = image[:,:,1]  # green channel, set the initial average to first frame
  88.         avgdiff = avgcol / 20.0 # obviously a coarse estimate
  89.         first_frame = False
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement