From a8c41e7a8f6187c3a32385060ada815f94a6e473 Mon Sep 17 00:00:00 2001 From: richard512 Date: Sun, 4 Sep 2016 17:13:27 -0700 Subject: [PATCH 01/14] added snapshot, snapshot sound, and switched codoc to divx --- MotionDetector.py | 201 +++++++++++++++++++------------------- MotionDetectorContours.py | 2 +- Sep-04_17_12_56.avi | Bin 0 -> 5672 bytes snapshotsound.ogg | Bin 0 -> 4851 bytes 4 files changed, 104 insertions(+), 99 deletions(-) create mode 100644 Sep-04_17_12_56.avi create mode 100644 snapshotsound.ogg diff --git a/MotionDetector.py b/MotionDetector.py index 6709e39..12d4a48 100644 --- a/MotionDetector.py +++ b/MotionDetector.py @@ -1,108 +1,113 @@ import cv2.cv as cv from datetime import datetime +import pygame import time class MotionDetectorInstantaneous(): - - def onChange(self, val): #callback when the user change the detection threshold - self.threshold = val - - def __init__(self,threshold=8, doRecord=True, showWindows=True): - self.writer = None - self.font = None - self.doRecord=doRecord #Either or not record the moving object - self.show = showWindows #Either or not show the 2 windows - self.frame = None - - self.capture=cv.CaptureFromCAM(0) - self.frame = cv.QueryFrame(self.capture) #Take a frame to init recorder - if doRecord: - self.initRecorder() - - self.frame1gray = cv.CreateMat(self.frame.height, self.frame.width, cv.CV_8U) #Gray frame at t-1 - cv.CvtColor(self.frame, self.frame1gray, cv.CV_RGB2GRAY) - - #Will hold the thresholded result - self.res = cv.CreateMat(self.frame.height, self.frame.width, cv.CV_8U) - - self.frame2gray = cv.CreateMat(self.frame.height, self.frame.width, cv.CV_8U) #Gray frame at t - - self.width = self.frame.width - self.height = self.frame.height - self.nb_pixels = self.width * self.height - self.threshold = threshold - self.isRecording = False - self.trigger_time = 0 #Hold timestamp of the last detection - - if showWindows: - cv.NamedWindow("Image") - cv.CreateTrackbar("Detection treshold: ", "Image", self.threshold, 100, self.onChange) - - def initRecorder(self): #Create the recorder - codec = cv.CV_FOURCC('M', 'J', 'P', 'G') #('W', 'M', 'V', '2') - self.writer=cv.CreateVideoWriter(datetime.now().strftime("%b-%d_%H_%M_%S")+".wmv", codec, 5, cv.GetSize(self.frame), 1) - #FPS set to 5 because it seems to be the fps of my cam but should be ajusted to your needs - self.font = cv.InitFont(cv.CV_FONT_HERSHEY_SIMPLEX, 1, 1, 0, 2, 8) #Creates a font + + def onChange(self, val): #callback when the user change the detection threshold + self.threshold = val + + def __init__(self,threshold=8, doRecord=True, showWindows=True): + pygame.mixer.init() + self.cameraSound = pygame.mixer.Sound("snapshotsound.ogg") + self.writer = None + self.font = None + self.doRecord=doRecord #Either or not record the moving object + self.show = showWindows #Either or not show the 2 windows + self.frame = None + + self.capture=cv.CaptureFromCAM(0) + self.frame = cv.QueryFrame(self.capture) #Take a frame to init recorder + if doRecord: + self.initRecorder() + + self.frame1gray = cv.CreateMat(self.frame.height, self.frame.width, cv.CV_8U) #Gray frame at t-1 + cv.CvtColor(self.frame, self.frame1gray, cv.CV_RGB2GRAY) + + #Will hold the thresholded result + self.res = cv.CreateMat(self.frame.height, self.frame.width, cv.CV_8U) + + self.frame2gray = cv.CreateMat(self.frame.height, self.frame.width, cv.CV_8U) #Gray frame at t + + self.width = self.frame.width + self.height = self.frame.height + self.nb_pixels = self.width * self.height + self.threshold = threshold + self.isRecording = False + self.trigger_time = 0 #Hold timestamp of the last detection + + if showWindows: + cv.NamedWindow("Image") + cv.CreateTrackbar("Detection treshold: ", "Image", self.threshold, 100, self.onChange) + + def initRecorder(self): #Create the recorder + codec = cv.CV_FOURCC('D', 'I', 'V', 'X') #('W', 'M', 'V', '2') + self.writer=cv.CreateVideoWriter(datetime.now().strftime("%b-%d_%H_%M_%S")+".avi", codec, 20, cv.GetSize(self.frame), 1) + #FPS set to 20 because it seems to be the fps of my cam but should be ajusted to your needs + self.font = cv.InitFont(cv.CV_FONT_HERSHEY_SIMPLEX, 1, 1, 0, 2, 8) #Creates a font - def run(self): - started = time.time() - while True: - - curframe = cv.QueryFrame(self.capture) - instant = time.time() #Get timestamp o the frame - - self.processImage(curframe) #Process the image - - if not self.isRecording: - if self.somethingHasMoved(): - self.trigger_time = instant #Update the trigger_time - if instant > started +5:#Wait 5 second after the webcam start for luminosity adjusting etc.. - print datetime.now().strftime("%b %d, %H:%M:%S"), "Something is moving !" - if self.doRecord: #set isRecording=True only if we record a video - self.isRecording = True - else: - if instant >= self.trigger_time +10: #Record during 10 seconds - print datetime.now().strftime("%b %d, %H:%M:%S"), "Stop recording" - self.isRecording = False - else: - cv.PutText(curframe,datetime.now().strftime("%b %d, %H:%M:%S"), (25,30),self.font, 0) #Put date on the frame - cv.WriteFrame(self.writer, curframe) #Write the frame - - if self.show: - cv.ShowImage("Image", curframe) - cv.ShowImage("Res", self.res) - - cv.Copy(self.frame2gray, self.frame1gray) - c=cv.WaitKey(1) % 0x100 - if c==27 or c == 10: #Break if user enters 'Esc'. - break - - def processImage(self, frame): - cv.CvtColor(frame, self.frame2gray, cv.CV_RGB2GRAY) - - #Absdiff to get the difference between to the frames - cv.AbsDiff(self.frame1gray, self.frame2gray, self.res) - - #Remove the noise and do the threshold - cv.Smooth(self.res, self.res, cv.CV_BLUR, 5,5) - cv.MorphologyEx(self.res, self.res, None, None, cv.CV_MOP_OPEN) - cv.MorphologyEx(self.res, self.res, None, None, cv.CV_MOP_CLOSE) - cv.Threshold(self.res, self.res, 10, 255, cv.CV_THRESH_BINARY_INV) + def run(self): + started = time.time() + while True: + + curframe = cv.QueryFrame(self.capture) + instant = time.time() #Get timestamp o the frame + + self.processImage(curframe) #Process the image + + if not self.isRecording: + if self.somethingHasMoved(): + self.trigger_time = instant #Update the trigger_time + if instant > started +5:#Wait 5 second after the webcam start for luminosity adjusting etc.. + print datetime.now().strftime("%b %d, %H:%M:%S"), "Something is moving !" + self.cameraSound.play() + cv.SaveImage('snapshot.png', curframe) + if self.doRecord: #set isRecording=True only if we record a video + self.isRecording = True + else: + if instant >= self.trigger_time +10: #Record during 10 seconds + print datetime.now().strftime("%b %d, %H:%M:%S"), "Stop recording" + self.isRecording = False + else: + cv.PutText(curframe,datetime.now().strftime("%b %d, %H:%M:%S"), (25,30),self.font, 0) #Put date on the frame + cv.WriteFrame(self.writer, curframe) #Write the frame + + if self.show: + cv.ShowImage("Image", curframe) + cv.ShowImage("Res", self.res) + + cv.Copy(self.frame2gray, self.frame1gray) + c=cv.WaitKey(1) % 0x100 + if c==27 or c == 10: #Break if user enters 'Esc'. + break + + def processImage(self, frame): + cv.CvtColor(frame, self.frame2gray, cv.CV_RGB2GRAY) + + #Absdiff to get the difference between to the frames + cv.AbsDiff(self.frame1gray, self.frame2gray, self.res) + + #Remove the noise and do the threshold + cv.Smooth(self.res, self.res, cv.CV_BLUR, 5,5) + cv.MorphologyEx(self.res, self.res, None, None, cv.CV_MOP_OPEN) + cv.MorphologyEx(self.res, self.res, None, None, cv.CV_MOP_CLOSE) + cv.Threshold(self.res, self.res, 10, 255, cv.CV_THRESH_BINARY_INV) - def somethingHasMoved(self): - nb=0 #Will hold the number of black pixels + def somethingHasMoved(self): + nb=0 #Will hold the number of black pixels - for x in range(self.height): #Iterate the hole image - for y in range(self.width): - if self.res[x,y] == 0.0: #If the pixel is black keep it - nb += 1 - avg = (nb*100.0)/self.nb_pixels #Calculate the average of black pixel in the image + for x in range(self.height): #Iterate the hole image + for y in range(self.width): + if self.res[x,y] == 0.0: #If the pixel is black keep it + nb += 1 + avg = (nb*100.0)/self.nb_pixels #Calculate the average of black pixel in the image - if avg > self.threshold:#If over the ceiling trigger the alarm - return True - else: - return False - + if avg > self.threshold:#If over the ceiling trigger the alarm + return True + else: + return False + if __name__=="__main__": - detect = MotionDetectorInstantaneous(doRecord=True) - detect.run() + detect = MotionDetectorInstantaneous(doRecord=True) + detect.run() diff --git a/MotionDetectorContours.py b/MotionDetectorContours.py index 729a53a..c403db3 100644 --- a/MotionDetectorContours.py +++ b/MotionDetectorContours.py @@ -7,7 +7,7 @@ class MotionDetectorAdaptative(): def onChange(self, val): #callback when the user change the detection threshold self.threshold = val - def __init__(self,threshold=25, doRecord=True, showWindows=True): + def __init__(self,threshold=7, doRecord=True, showWindows=True): self.writer = None self.font = None self.doRecord=doRecord #Either or not record the moving object diff --git a/Sep-04_17_12_56.avi b/Sep-04_17_12_56.avi new file mode 100644 index 0000000000000000000000000000000000000000..2f298ca67e38d9e1e342c44efe3056add1c0deca GIT binary patch literal 5672 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 literal 0 HcmV?d00001 From e8e3ff8ec58af6313427025d1630a44d87d83620 Mon Sep 17 00:00:00 2001 From: richard512 Date: Sun, 4 Sep 2016 17:16:14 -0700 Subject: [PATCH 02/14] Delete Sep-04_17_12_56.avi --- Sep-04_17_12_56.avi | Bin 5672 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 Sep-04_17_12_56.avi diff --git a/Sep-04_17_12_56.avi b/Sep-04_17_12_56.avi deleted file mode 100644 index 2f298ca67e38d9e1e342c44efe3056add1c0deca..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5672 zcmWIYbaP_>0>>~<1s~7gkQags3>hg!If-SN85ThCfWttdKpdomL4XrXfeA)1DZtRc z#K7mm&#(w&g&?gW$N~%k4F7=uCe*<6fDx!a zO#>(Z!Z7<786+6MW(n}Yl)`DRP(N=GpxrD`5d(viWVqxgV>ARtLtr!nMnhmU1V%$( zGz3ONU^E0qLtr!nMnhmU1V%$(*oOdUY=8wg=#Zb1n*&4{KZd=JaeELnMk4`~_Vjb} x_Y8Im;Q_LJ63fy|P4tWm^h_8)VfBL Date: Sun, 29 Jan 2017 16:01:41 -0800 Subject: [PATCH 03/14] Update README.md --- README.md | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 87bf73d..0e41928 100644 --- a/README.md +++ b/README.md @@ -5,21 +5,19 @@ Python/OpenCV script that detect motion on webcam and allow record it to a file. ## The simple way ## -The trivial idea is to compute the difference between two frames apply a threshold the separate pixels that have changed from the others and then count all the black pixels. Then the average is calculated with this count and the total number of pixels and depending of the ceil the event is triggered or not. +[![https://www.youtube.com/watch?v=-RUu3EcielI](https://img.youtube.com/vi/-RUu3EcielI/0.jpg)](https://www.youtube.com/watch?v=-RUu3EcielI) -**Additional informations:** +Compare video frames, checking how many pixels changed. -* initRecorder: initialise the recorder with an arbitrary codec it can be changed with problems -* in the run method no motion can be detected in the first 5 second because it is almost the time needed for the webcam to adjust the focus and the luminosity which imply lot's of changes on the image -* processImage: contains all the images operations applied to the image -* somethingHasMoved: The image iteration to count black pixels is contained in this method - - -The result of applying it can be seen here: https://www.youtube.com/watch?v=-RUu3EcielI +## The smart way ## +[![https://www.youtube.com/watch?v=sRIdyfh3054](https://img.youtube.com/vi/sRIdyfh3054/0.jpg)](https://www.youtube.com/watch?v=sRIdyfh3054) -## The smart way ## +Find the contours of the moving objects and calculate the area of all of them. Then the average of the surface changing is compared with the total surface of the image and the alarm is triggered if it exceed the given threshold -Iis way to operate is less trivial than the previous one, but the results are identical if not more accurate in the previous method. I inspired myself of the [Motion-tracker]("https://github.com/mattwilliamson/Motion-Tracker/") by Matt Williamson for the operations and filters to apply on the image but all the rest is different. The idea in this method is to find the contours of the moving objects and calculate the area of all of them. Then the average of the surface changing is compared with the total surface of the image and the alarm is triggered if it exceed the given threshold. Note the code shown below does not implement the recording system as it is the case on the previous example, but it can be made easily. +## More info ## -The result of applying it can be seen here: https://www.youtube.com/watch?v=sRIdyfh3054 +* webcams usually need about 5 seconds to start up +* initRecorder is where video output codec can be changed +* processImage is where the cool stuff happens +* somethingHasMoved: pixel comparison From 5d8da04ba40bb06ed84a3c87007762ae785d7548 Mon Sep 17 00:00:00 2001 From: richard512 Date: Mon, 30 Jan 2017 15:51:02 -0800 Subject: [PATCH 04/14] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 0e41928..54720ec 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ Find the contours of the moving objects and calculate the area of all of them. T ## More info ## -* webcams usually need about 5 seconds to start up -* initRecorder is where video output codec can be changed -* processImage is where the cool stuff happens +* usually takes about 5 seconds to start up +* initRecorder: here, you can change the output video codec * somethingHasMoved: pixel comparison +* processImage: the fun stuff! From cc646336ddcc7c21d3c7e4ee71d41ecce7e39806 Mon Sep 17 00:00:00 2001 From: richard512 Date: Mon, 30 Jan 2017 15:54:19 -0800 Subject: [PATCH 05/14] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 54720ec..20d749b 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,6 @@ Find the contours of the moving objects and calculate the area of all of them. T ## More info ## * usually takes about 5 seconds to start up -* initRecorder: here, you can change the output video codec +* initRecorder: you can switch the output video format here * somethingHasMoved: pixel comparison * processImage: the fun stuff! From c40ae292c3a81b1370f20e006bd8073f47fac26e Mon Sep 17 00:00:00 2001 From: richard512 Date: Mon, 30 Jan 2017 20:58:28 -0800 Subject: [PATCH 06/14] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 20d749b..8987acf 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -Motion-detection-OpenCV +Python Security Camera ======================= Python/OpenCV script that detect motion on webcam and allow record it to a file. From 17333169b94ad815cc52d753d7a3698553a3b2c7 Mon Sep 17 00:00:00 2001 From: richard512 Date: Wed, 1 Feb 2017 22:39:23 -0800 Subject: [PATCH 07/14] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8987acf..169276d 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ Compare video frames, checking how many pixels changed. [![https://www.youtube.com/watch?v=sRIdyfh3054](https://img.youtube.com/vi/sRIdyfh3054/0.jpg)](https://www.youtube.com/watch?v=sRIdyfh3054) -Find the contours of the moving objects and calculate the area of all of them. Then the average of the surface changing is compared with the total surface of the image and the alarm is triggered if it exceed the given threshold +Detect moving objects, calculate their surface area, and set off the alarm when a specified portion of the screen has moved. ## More info ## From 8a90e25247e6b6296cce95e965ebe039b9f58f6d Mon Sep 17 00:00:00 2001 From: richard512 Date: Wed, 1 Feb 2017 22:41:18 -0800 Subject: [PATCH 08/14] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 169276d..74fe535 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ Compare video frames, checking how many pixels changed. [![https://www.youtube.com/watch?v=sRIdyfh3054](https://img.youtube.com/vi/sRIdyfh3054/0.jpg)](https://www.youtube.com/watch?v=sRIdyfh3054) -Detect moving objects, calculate their surface area, and set off the alarm when a specified portion of the screen has moved. +Detect moving objects and calculate their surface area. ## More info ## From 72b66fa7905c00ce1ac201f2f7626d0eda125336 Mon Sep 17 00:00:00 2001 From: richard512 Date: Thu, 4 Jan 2018 16:43:06 -0700 Subject: [PATCH 09/14] Add files via upload --- motionDetectionCV3.py | 57 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 motionDetectionCV3.py diff --git a/motionDetectionCV3.py b/motionDetectionCV3.py new file mode 100644 index 0000000..f3b63a7 --- /dev/null +++ b/motionDetectionCV3.py @@ -0,0 +1,57 @@ +# coding=utf-8 +""" +Webcam motion detection +""" +import cv2 +import numpy as np + +THRESHOLD = 40 +camera = cv2.VideoCapture(0) + +es = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (9,4)) +kernel = np.ones((5,5), np.uint8) +background = None + +# Write test video +fps = 20 #camera.get(cv2.CAP_PROP_FPS) +size = (int(camera.get(cv2.CAP_PROP_FRAME_WIDTH)), + int(camera.get(cv2.CAP_PROP_FRAME_HEIGHT))) +videoWriter = cv2.VideoWriter('basic_motion_detection.avi', + cv2.VideoWriter_fourcc('D', 'I', 'V', 'X'), + fps, size) + +while (True): + ret, frame = camera.read() + # The first frame as the background + if background is None: + background = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) + background = cv2.GaussianBlur(background, (21,21), 0) + continue + + gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) + gray_frame = cv2.GaussianBlur(gray_frame, (21,21), 0) + + # Compare the difference between each frame of image and the background + #print(background.shape, gray_frame.shape) + diff = cv2.absdiff(background, gray_frame) + diff = cv2.threshold(diff, THRESHOLD, 255, cv2.THRESH_BINARY)[1] + diff = cv2.dilate(diff, es, iterations=2) + # Calculate the outline of the target in the image + image, cnts, hierarchy = cv2.findContours(diff.copy(), + cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) + print ("Detecting " + str(len(cnts)) + " Moving Objects") + for c in cnts: + if cv2.contourArea(c) < 1500: + continue + # Calculate the bounding box + (x, y, w, h) = cv2.boundingRect(c) + cv2.rectangle(frame, (x,y), (x+w, y+h), (0,255,0), 2) + + cv2.imshow("contours", frame) + videoWriter.write(frame) + cv2.imshow("dif", diff) + # cv2.imwrite('didff.jpg', diff) + if cv2.waitKey(int(1000/12)) &0xff == ord('q'): + break +cv2.destroyAllWindows() +camera.release() \ No newline at end of file From cbde90ed905452bde35e3728a05fb5ecfda0e4ee Mon Sep 17 00:00:00 2001 From: richard512 Date: Thu, 4 Jan 2018 16:46:15 -0700 Subject: [PATCH 10/14] Update motionDetectionCV3.py --- motionDetectionCV3.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/motionDetectionCV3.py b/motionDetectionCV3.py index f3b63a7..c9f3da2 100644 --- a/motionDetectionCV3.py +++ b/motionDetectionCV3.py @@ -1,6 +1,7 @@ # coding=utf-8 """ -Webcam motion detection +Webcam motion detection and object detection +Confirmed working on Python 3.6.2 with OpenCV 3.4.0 on Win10 """ import cv2 import numpy as np @@ -54,4 +55,4 @@ if cv2.waitKey(int(1000/12)) &0xff == ord('q'): break cv2.destroyAllWindows() -camera.release() \ No newline at end of file +camera.release() From e92f7be1c7cd07a396aad4aebe3bfd61433d1be6 Mon Sep 17 00:00:00 2001 From: richard512 Date: Thu, 4 Jan 2018 16:51:40 -0700 Subject: [PATCH 11/14] Add files via upload --- soundDetection.py | 95 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 soundDetection.py diff --git a/soundDetection.py b/soundDetection.py new file mode 100644 index 0000000..a9c5fe7 --- /dev/null +++ b/soundDetection.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python +import pyaudio +from numpy import zeros,linspace,short,fromstring,hstack,transpose,log +from scipy import fft +from time import sleep + +#Volume Sensitivity, 0.05: Extremely Sensitive, may give false alarms +# 0.1: Probably Ideal volume +# 1: Poorly sensitive, will only go off for relatively loud +SENSITIVITY= 1.0 +# Alarm frequencies (Hz) to detect (Use audacity to record a wave and then do Analyze->Plot Spectrum) +TONE = 1593 +#Bandwidth for detection (i.e., detect frequencies within this margin of error of the TONE) +BANDWIDTH = 30 +#How many 46ms blips before we declare a beep? (Take the beep length in ms, divide by 46ms, subtract a bit) +beeplength=2 +# How many beeps before we declare an alarm? +alarmlength=2 +# How many false 46ms blips before we declare the alarm is not ringing +resetlength=10 +# How many reset counts until we clear an active alarm? +clearlength=30 +# Enable blip, beep, and reset debug output +debug=False +# Show the most intense frequency detected (useful for configuration) +frequencyoutput=True + + +#Set up audio sampler - +NUM_SAMPLES = 2048 +SAMPLING_RATE = 44100 +pa = pyaudio.PyAudio() +_stream = pa.open(format=pyaudio.paInt16, + channels=1, rate=SAMPLING_RATE, + input=True, + frames_per_buffer=NUM_SAMPLES) + +print("Alarm detector working. Press CTRL-C to quit.") + +blipcount=0 +beepcount=0 +resetcount=0 +clearcount=0 +alarm=False + +while True: + while _stream.get_read_available()< NUM_SAMPLES: sleep(0.01) + audio_data = fromstring(_stream.read( + _stream.get_read_available()), dtype=short)[-NUM_SAMPLES:] + # Each data point is a signed 16 bit number, so we can normalize by dividing 32*1024 + normalized_data = audio_data / 32768.0 + intensity = abs(fft(normalized_data))[:int(NUM_SAMPLES/2)] + frequencies = linspace(0.0, float(SAMPLING_RATE)/2, num=NUM_SAMPLES/2) + if frequencyoutput: + which = intensity[1:].argmax()+1 + # use quadratic interpolation around the max + if which != len(intensity)-1: + y0,y1,y2 = log(intensity[which-1:which+2:]) + x1 = (y2 - y0) * .5 / (2 * y1 - y2 - y0) + # find the frequency and output it + thefreq = (which+x1)*SAMPLING_RATE/NUM_SAMPLES + else: + thefreq = which*SAMPLING_RATE/NUM_SAMPLES + print ("\t\t\t\tfreq=",thefreq) + if max(intensity[(frequencies < TONE+BANDWIDTH) & (frequencies > TONE-BANDWIDTH )]) > max(intensity[(frequencies < TONE-1000) & (frequencies > TONE-2000)]) + SENSITIVITY: + blipcount+=1 + resetcount=0 + if debug: print ("\t\tBlip",blipcount) + if (blipcount>=beeplength): + blipcount=0 + resetcount=0 + beepcount+=1 + if debug: print ("\tBeep",beepcount) + if (beepcount>=alarmlength): + clearcount=0 + alarm=True + print ("Alarm!") + beepcount=0 + else: + blipcount=0 + resetcount+=1 + if debug: print ("\t\t\treset",resetcount) + if (resetcount>=resetlength): + resetcount=0 + beepcount=0 + if alarm: + clearcount+=1 + if debug: print ("\t\tclear",clearcount) + if clearcount>=clearlength: + clearcount=0 + print ("Cleared alarm!") + alarm=False + sleep(0.01) + + From 2bd64dc2f3cfb9f71d93a5e375690a2cc5eba344 Mon Sep 17 00:00:00 2001 From: richard512 Date: Thu, 4 Jan 2018 17:10:54 -0700 Subject: [PATCH 12/14] Update motionDetectionCV3.py --- motionDetectionCV3.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/motionDetectionCV3.py b/motionDetectionCV3.py index c9f3da2..446871b 100644 --- a/motionDetectionCV3.py +++ b/motionDetectionCV3.py @@ -1,10 +1,10 @@ # coding=utf-8 """ -Webcam motion detection and object detection -Confirmed working on Python 3.6.2 with OpenCV 3.4.0 on Win10 +Webcam motion detection """ import cv2 import numpy as np +import pygame THRESHOLD = 40 camera = cv2.VideoCapture(0) @@ -15,6 +15,8 @@ # Write test video fps = 20 #camera.get(cv2.CAP_PROP_FPS) +pygame.mixer.init() +cameraSound = pygame.mixer.Sound("snapshotsound.ogg") size = (int(camera.get(cv2.CAP_PROP_FRAME_WIDTH)), int(camera.get(cv2.CAP_PROP_FRAME_HEIGHT))) videoWriter = cv2.VideoWriter('basic_motion_detection.avi', @@ -41,6 +43,9 @@ image, cnts, hierarchy = cv2.findContours(diff.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) print ("Detecting " + str(len(cnts)) + " Moving Objects") + if len(cnts) > 0: + cameraSound.play() + for c in cnts: if cv2.contourArea(c) < 1500: continue From 1abe4769c5796e92c6823344a6f271da9f884044 Mon Sep 17 00:00:00 2001 From: richard512 Date: Thu, 4 Jan 2018 21:15:59 -0700 Subject: [PATCH 13/14] Update soundDetection.py --- soundDetection.py | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/soundDetection.py b/soundDetection.py index a9c5fe7..205d7c9 100644 --- a/soundDetection.py +++ b/soundDetection.py @@ -2,7 +2,8 @@ import pyaudio from numpy import zeros,linspace,short,fromstring,hstack,transpose,log from scipy import fft -from time import sleep +import time +import ctypes #Volume Sensitivity, 0.05: Extremely Sensitive, may give false alarms # 0.1: Probably Ideal volume @@ -23,7 +24,7 @@ # Enable blip, beep, and reset debug output debug=False # Show the most intense frequency detected (useful for configuration) -frequencyoutput=True +frequencyoutput=False #Set up audio sampler - @@ -35,6 +36,7 @@ input=True, frames_per_buffer=NUM_SAMPLES) +#ctypes.windll.user32.LockWorkStation() print("Alarm detector working. Press CTRL-C to quit.") blipcount=0 @@ -44,7 +46,7 @@ alarm=False while True: - while _stream.get_read_available()< NUM_SAMPLES: sleep(0.01) + while _stream.get_read_available()< NUM_SAMPLES: time.sleep(0.01) audio_data = fromstring(_stream.read( _stream.get_read_available()), dtype=short)[-NUM_SAMPLES:] # Each data point is a signed 16 bit number, so we can normalize by dividing 32*1024 @@ -61,7 +63,7 @@ thefreq = (which+x1)*SAMPLING_RATE/NUM_SAMPLES else: thefreq = which*SAMPLING_RATE/NUM_SAMPLES - print ("\t\t\t\tfreq=",thefreq) + if debug: print ("\t\t\t\tfreq=",thefreq) if max(intensity[(frequencies < TONE+BANDWIDTH) & (frequencies > TONE-BANDWIDTH )]) > max(intensity[(frequencies < TONE-1000) & (frequencies > TONE-2000)]) + SENSITIVITY: blipcount+=1 resetcount=0 @@ -72,9 +74,12 @@ beepcount+=1 if debug: print ("\tBeep",beepcount) if (beepcount>=alarmlength): + if not alarm: + datetime = time.strftime('%Y-%m-%d %H:%M:%S') + print ("Alarm triggered at "+datetime) clearcount=0 alarm=True - print ("Alarm!") + if debug: print ("Alarm!") beepcount=0 else: blipcount=0 @@ -88,8 +93,8 @@ if debug: print ("\t\tclear",clearcount) if clearcount>=clearlength: clearcount=0 - print ("Cleared alarm!") + print ("Listening...") alarm=False - sleep(0.01) - - + else: + if debug: print ("No alarm") + time.sleep(0.01) From a1d0cbe3c6ccce9f6bda0f0d7f3991f4a6e28e6b Mon Sep 17 00:00:00 2001 From: richard512 Date: Thu, 4 Jan 2018 21:51:54 -0700 Subject: [PATCH 14/14] Update soundDetection.py --- soundDetection.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/soundDetection.py b/soundDetection.py index 205d7c9..7dc0d99 100644 --- a/soundDetection.py +++ b/soundDetection.py @@ -36,8 +36,13 @@ input=True, frames_per_buffer=NUM_SAMPLES) +def addToLog(appendText): + print (appendText) + with open("log.txt", "a") as myfile: + myfile.write("\n"+appendText) + #ctypes.windll.user32.LockWorkStation() -print("Alarm detector working. Press CTRL-C to quit.") +addToLog ("Listening for "+str(alarmlength)+" beeps of "+str(beeplength * 46)+"ms at "+str(TONE)+"Hz") blipcount=0 beepcount=0 @@ -76,7 +81,8 @@ if (beepcount>=alarmlength): if not alarm: datetime = time.strftime('%Y-%m-%d %H:%M:%S') - print ("Alarm triggered at "+datetime) + humantime = time.strftime('%I:%M:%S %p %Z') + addToLog ("Alarm triggered at "+datetime+" ("+humantime+")") clearcount=0 alarm=True if debug: print ("Alarm!") @@ -93,7 +99,7 @@ if debug: print ("\t\tclear",clearcount) if clearcount>=clearlength: clearcount=0 - print ("Listening...") + addToLog ("Listening...") alarm=False else: if debug: print ("No alarm")