Advertisement
Guest User

Untitled

a guest
Jun 6th, 2018
188
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.39 KB | None | 0 0
  1. #!/usr/bin/python
  2. """
  3. Lightweight Motion Detection using python picamera libraries.
  4. Requires a Raspberry Pi computer with a picamera module.
  5. This code is based on a raspberry pi forum post by user utpalc
  6. modified by Claude Pageau for this working example.
  7.  
  8. This project can be used for further development
  9. and is located on GitHub at
  10. https://github.com/pageauc/picamera-motion
  11.  
  12. For a full featured program see my GitHub pi-timolo project at
  13. https://github.com/pageauc/pi-timolo
  14. """
  15.  
  16. import os, sys
  17. import datetime
  18. import time
  19. import glob
  20. import picamera
  21. import picamera.array
  22. import dropbox
  23. from dropbox.exceptions import ApiError, AuthError
  24. import smtplib
  25. from email.mime.text import MIMEText as text
  26.  
  27.  
  28. if not os.path.exists('settings.py'):
  29. print("ERROR : File Not Found - settings.py")
  30. print(" Cannot import program variables.")
  31. print(" To Repair Run menubox.sh UPGRADE menu pick.")
  32. exit(1)
  33. try:
  34. from settings import *
  35. except ImportError:
  36. print("ERROR : Could Not Import settings.py")
  37. exit(1)
  38.  
  39. PROG_VER = "ver 2.7"
  40. SCRIPT_PATH = os.path.abspath(__file__)
  41. # get script file name without extension
  42. PROG_NAME = SCRIPT_PATH[SCRIPT_PATH.rfind("/")+1:SCRIPT_PATH.rfind(".")]
  43. SCRIPT_DIR = SCRIPT_PATH[0:SCRIPT_PATH.rfind("/")+1] # get script directory
  44. # conversion from stream coordinate to full image coordinate
  45. X_MO_CONV = imageWidth/float(streamWidth)
  46. Y_MO_CONV = imageHeight/float(streamHeight)
  47. # Authorisation token
  48. TOKEN = 'pZnyCEeK9mUAAAAAAAAAicsXxLNKWo1y1Q2CULKvnhWfPMYgvRVQ5BJv3jYNV4ck'
  49.  
  50. #------------------------------------------------------------------------------
  51. def get_now():
  52. """ Get datetime and return formatted string"""
  53. right_now = datetime.datetime.now()
  54. return ("%04d%02d%02d-%02d:%02d:%02d"
  55. % (right_now.year, right_now.month, right_now.day,
  56. right_now.hour, right_now.minute, right_now.second))
  57.  
  58. #------------------------------------------------------------------------------
  59. def check_image_dir(image_dir):
  60. """ if image_dir does not exist create the folder """
  61. if not os.path.isdir(image_dir):
  62. if verbose:
  63. print("INFO : Creating Image Storage folder %s" % (image_dir))
  64. try:
  65. os.makedirs(image_dir)
  66. except OSError as err:
  67. print("ERROR : Could Not Create Folder %s %s" % (image_dir, err))
  68. exit(1)
  69.  
  70. #------------------------------------------------------------------------------
  71. def get_file_name(image_dir, image_name_prefix, current_count):
  72. """
  73. Create a file name based on settings.py variables
  74. Note image numbering will not be saved but will be inferred from the
  75. last image name using get_last_counter() function.
  76. If the last image file name is not a number sequence file
  77. then numbering will start from imageNumStart variable and may overwrite
  78. previous number sequence images. This can happen if you switch between
  79. number sequence and datetime sequence in the same folder.
  80. or
  81. Set imageNumOn=False to save images in datetime format to
  82. ensure image name is unique and avoid overwriting previous image(s).
  83.  
  84. """
  85. if imageNumOn:
  86. # you could also use os.path.join to construct image path file_path
  87. file_path = image_dir+ "/"+image_name_prefix+str(current_count)+".jpg"
  88. else:
  89. right_now = datetime.datetime.now()
  90. file_path = ("%s/%s%04d%02d%02d-%02d%02d%02d.jpg"
  91. % (image_dir, image_name_prefix,
  92. right_now.year, right_now.month, right_now.day,
  93. right_now.hour, right_now.minute, right_now.second))
  94. return file_path
  95.  
  96. #------------------------------------------------------------------------------
  97. def get_last_counter():
  98. """
  99. glob imagePath for last saved jpg file. Try to extract image counter from
  100. file name and convert to integer. If it fails restart number sequence.
  101.  
  102. Note: If the last saved jpg file name is not in number sequence name
  103. format (example was in date time naming format) then previous number
  104. sequence images will be overwritten.
  105.  
  106. Avoid switching back and forth between datetime and number sequences
  107. per imageNumOn variable in settings.py
  108. """
  109. counter = imageNumStart
  110. if imageNumOn:
  111. image_ext = ".jpg"
  112. search_str = imagePath + "/*" + image_ext
  113. file_prefix_len = len(imagePath + imageNamePrefix)+1
  114. try:
  115. # Scan image folder for most recent jpg file
  116. # and try to extract most recent number counter from file name
  117. newest = max(glob.iglob(search_str), key=os.path.getctime)
  118. count_str = newest[file_prefix_len:newest.find(image_ext)]
  119. print("%s INFO : Last Saved Image is %s Try to Convert %s"
  120. % (get_now(), newest, count_str))
  121. counter = int(count_str)+1
  122. print("%s INFO : Next Image Counter is %i"
  123. % (get_now(), counter))
  124. except:
  125. print("%s WARN : Restart Numbering at %i "
  126. "WARNING: Previous Files May be Over Written."
  127. % (get_now(), counter))
  128. return counter
  129.  
  130. #------------------------------------------------------------------------------
  131. def take_day_image(image_path):
  132. """
  133. Take a picamera day image. Note: You may need to increase
  134. sleep for low light conditions
  135. """
  136. with picamera.PiCamera() as camera:
  137. camera.resolution = (imageWidth, imageHeight)
  138. # camera.rotation = cameraRotate
  139. # Note use imageVFlip and imageHFlip settings.py variables
  140. if imagePreview:
  141. camera.start_preview()
  142. camera.vflip = imageVFlip
  143. camera.hflip = imageHFlip
  144. camera.exposure_mode = 'auto'
  145. camera.awb_mode = 'auto'
  146. time.sleep(1)
  147. camera.capture(image_path)
  148. camera.close()
  149. return image_path
  150.  
  151. #------------------------------------------------------------------------------
  152. def get_stream_array():
  153. """ Take a stream image and return the image data array"""
  154. with picamera.PiCamera() as camera:
  155. camera.resolution = (streamWidth, streamHeight)
  156. with picamera.array.PiRGBArray(camera) as stream:
  157. camera.vflip = imageVFlip
  158. camera.hflip = imageHFlip
  159. camera.exposure_mode = 'auto'
  160. camera.awb_mode = 'auto'
  161. camera.capture(stream, format='rgb')
  162. camera.close()
  163. return stream.array
  164.  
  165. #------------------------------------------------------------------------------
  166. def scan_motion():
  167. """ Loop until motion is detected """
  168. data1 = get_stream_array()
  169. while True:
  170. data2 = get_stream_array()
  171. diff_count = 0
  172. for y in range(0, streamHeight):
  173. for x in range(0, streamWidth):
  174. # get pixel differences. Conversion to int
  175. # is required to avoid unsigned short overflow.
  176. diff = abs(int(data1[y][x][1]) - int(data2[y][x][1]))
  177. if diff > threshold:
  178. diff_count += 1
  179. if diff_count > sensitivity:
  180. # x,y is a very rough motion position
  181. return x, y
  182. data1 = data2
  183.  
  184. #------------------------------------------------------------------------------
  185.  
  186. def send_mail():
  187. from_addr = 'raspberrypimodec@gmail.com'
  188. to_addr_list = 'deniturkovic@gmail.com'
  189. cc_addr_list = 'annamariamihel@gmail.com'
  190. subject = 'Detekcija pokreta'
  191. message = text("Otkrivena detekcija. Za pregled snimljenih fotografija posjeti http://10.42.0.145:8080/")
  192. login = 'raspberrypimodec'
  193. password = 'raspberry2018'
  194.  
  195. server = smtplib.SMTP('smtp.gmail.com', 587)
  196. server.starttls()
  197. server.login(login,password)
  198. server.sendmail(from_addr, to_addr_list, message.as_string())
  199. server.quit()
  200.  
  201.  
  202. #------------------------------------------------------------------------------
  203. # Upload localfile to Dropbox
  204. def uploadFile(localfile):
  205.  
  206. # Check that access tocken added
  207. if (len(TOKEN) == 0):
  208. sys.exit("ERROR: Missing access token. "
  209. "try re-generating an access token from the app console at dropbox.com.")
  210.  
  211. # Create instance of a Dropbox class, which can make requests to API
  212. print("Creating a Dropbox object...")
  213. dbx = dropbox.Dropbox(TOKEN)
  214.  
  215. # Check that the access token is valid
  216. try:
  217. dbx.users_get_current_account()
  218. except AuthError as err:
  219. sys.exit("ERROR: Invalid access token; try re-generating an "
  220. "access token from the app console at dropbox.com.")
  221.  
  222. # Specify upload path
  223. uploadPath = "/" + localfile.split('/')[-1]
  224.  
  225. # Read in file and upload
  226. with open(localfile, 'rb') as f:
  227. print("Uploading " + localfile + " to Dropbox as " + uploadPath + "...")
  228.  
  229. try:
  230. dbx.files_upload(f.read(), uploadPath)
  231. except ApiError as err:
  232. # Check user has enough Dropbox space quota
  233. if (err.error.is_path() and
  234. err.error.get_path().error.is_insufficient_space()):
  235. sys.exit("ERROR: Cannot upload; insufficient space.")
  236. elif err.user_message_text:
  237. print(err.user_message_text)
  238. sys.exit()
  239. else:
  240. print(err)
  241. sys.exit()
  242. #------------------------------------------------------------------------------
  243. def do_motion_detection():
  244. """
  245. Loop until motion found then take an image,
  246. and continue motion detection. ctrl-c to exit
  247. """
  248. current_count = get_last_counter()
  249. if not imageNumOn:
  250. print("%s INFO : File Naming by Date Time Sequence" % get_now())
  251. while True:
  252. x_pos, y_pos = scan_motion()
  253. file_name = get_file_name(imagePath, imageNamePrefix, current_count)
  254. take_day_image(file_name)
  255. if imageNumOn:
  256. current_count += 1
  257. # Convert xy movement location for full size image
  258. mo_x = x_pos * X_MO_CONV
  259. mo_y = y_pos * Y_MO_CONV
  260. if verbose:
  261.  
  262.  
  263.  
  264. print("%s INFO : Motion xy(%d,%d) Saved %s (%ix%i)"
  265. % (get_now(), mo_x, mo_y, file_name,
  266. imageWidth, imageHeight,))
  267. file = os.getcwd() + '/' + file_name
  268. print("11111111111111111111")
  269. print(file)
  270. uploadFile(file)
  271. deleteLocal(file)
  272. send_mail()
  273.  
  274. #------------------------------------------------------------------------------
  275. # Delete file
  276. def deleteLocal(file):
  277. os.system("rm " + file)
  278. print("File: " + file + " deleted ...")
  279.  
  280.  
  281.  
  282. # Start Main Program Logic
  283. if __name__ == '__main__':
  284. print("%s %s written by Claude Pageau" % (PROG_NAME, PROG_VER))
  285. print("---------------------------------------------")
  286. check_image_dir(imagePath)
  287. print("%s INFO : Scan for Motion "
  288. "threshold=%i (diff) sensitivity=%i (num px's)..."
  289. % (get_now(), threshold, sensitivity))
  290. if not verbose:
  291. print("%s WARN : Messages turned off per settings.py verbose = %s"
  292. % (get_now(), verbose))
  293. try:
  294. do_motion_detection()
  295.  
  296. except KeyboardInterrupt:
  297. print("")
  298. print("INFO : User Pressed ctrl-c")
  299. print(" Exiting %s %s " % (PROG_NAME, PROG_VER))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement