diff --git a/MotionDetector.py b/MotionDetector.py index 4bcd421..3993362 100644 --- a/MotionDetector.py +++ b/MotionDetector.py @@ -2,12 +2,12 @@ from datetime import datetime import time -class MotionDetector(): +class MotionDetectorInstantaneous(): - def onChange(self, val): #callback when the user change the ceil - self.ceil = val + def onChange(self, val): #callback when the user change the detection threshold + self.threshold = val - def __init__(self,ceil=8, doRecord=True, showWindows=True): + 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 @@ -30,19 +30,18 @@ def __init__(self,ceil=8, doRecord=True, showWindows=True): self.width = self.frame.width self.height = self.frame.height self.nb_pixels = self.width * self.height - self.ceil = ceil + self.threshold = threshold self.isRecording = False self.trigger_time = 0 #Hold timestamp of the last detection if showWindows: cv.NamedWindow("Image") - cv.CreateTrackbar("Mytrack", "Image", self.ceil, 100, self.onChange) + cv.CreateTrackbar("Detection treshold: ", "Image", self.threshold, 100, self.onChange) def initRecorder(self): #Create the recorder - codec = cv.CV_FOURCC('D', 'I', 'V', 'X') - #codec = cv.CV_FOURCC("D", "I", "B", " ") - self.writer=cv.CreateVideoWriter(datetime.now().strftime("%b-%d_%H:%M:%S")+".avi", codec, 15, cv.GetSize(self.frame), 1) - #FPS set at 15 because it seems to be the fps of my cam but should be ajusted to your needs + 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 run(self): @@ -58,12 +57,12 @@ def run(self): 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 "Something is moving !" + 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 "Stop recording" + 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 @@ -74,8 +73,8 @@ def run(self): cv.ShowImage("Res", self.res) cv.Copy(self.frame2gray, self.frame1gray) - c=cv.WaitKey(1) - if c==27 or c == 1048603: #Break if user enters 'Esc'. + c=cv.WaitKey(1) % 0x100 + if c==27 or c == 10: #Break if user enters 'Esc'. break def processImage(self, frame): @@ -86,7 +85,6 @@ def processImage(self, frame): #Remove the noise and do the threshold cv.Smooth(self.res, self.res, cv.CV_BLUR, 5,5) - element = cv.CreateStructuringElementEx(5*2+1, 5*2+1, 5, 5, cv.CV_SHAPE_RECT) 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) @@ -94,17 +92,17 @@ def processImage(self, frame): def somethingHasMoved(self): nb=0 #Will hold the number of black pixels - for y in range(self.height): #Iterate the hole image - for x in range(self.width): - if self.res[y,x] == 0.0: #If the pixel is black keep it + 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 - #print "Average: ",avg, "%\r", - if avg > self.ceil:#If over the ceil trigger the alarm + + if avg > self.threshold:#If over the ceiling trigger the alarm return True else: return False if __name__=="__main__": - detect = MotionDetector(doRecord=False) + detect = MotionDetectorInstantaneous(doRecord=True) detect.run() \ No newline at end of file diff --git a/MotionDetectorContours.py b/MotionDetectorContours.py index 9c6a9d0..8f43dda 100644 --- a/MotionDetectorContours.py +++ b/MotionDetectorContours.py @@ -2,12 +2,12 @@ from datetime import datetime import time -class MotionDetector(): +class MotionDetectorAdaptative(): - def onChange(self, val): #callback when the user change the ceil - self.ceil = val + def onChange(self, val): #callback when the user change the detection threshold + self.threshold = val - def __init__(self,ceil=25, doRecord=True, showWindows=True): + def __init__(self,threshold=25, doRecord=True, showWindows=True): self.writer = None self.font = None self.doRecord=doRecord #Either or not record the moving object @@ -22,26 +22,23 @@ def __init__(self,ceil=25, doRecord=True, showWindows=True): self.gray_frame = cv.CreateImage(cv.GetSize(self.frame), cv.IPL_DEPTH_8U, 1) self.average_frame = cv.CreateImage(cv.GetSize(self.frame), cv.IPL_DEPTH_32F, 3) self.absdiff_frame = None - self.tmp = None + self.previous_frame = None - self.width = self.frame.width - self.height = self.frame.height - self.surface = self.width * self.height + self.surface = self.frame.width * self.frame.height self.currentsurface = 0 self.currentcontours = None - self.ceil = ceil + self.threshold = threshold self.isRecording = False self.trigger_time = 0 #Hold timestamp of the last detection if showWindows: cv.NamedWindow("Image") - cv.CreateTrackbar("Mytrack", "Image", self.ceil, 100, self.onChange) + cv.CreateTrackbar("Detection treshold: ", "Image", self.threshold, 100, self.onChange) def initRecorder(self): #Create the recorder - codec = cv.CV_FOURCC('D', 'I', 'V', 'X') - #codec = cv.CV_FOURCC("D", "I", "B", " ") - self.writer=cv.CreateVideoWriter(datetime.now().strftime("%b-%d_%H:%M:%S")+".avi", codec, 15, cv.GetSize(self.frame), 1) - #FPS set at 15 because it seems to be the fps of my cam but should be ajusted to your needs + codec = cv.CV_FOURCC('M', 'J', 'P', 'G') + 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 run(self): @@ -56,7 +53,7 @@ def run(self): 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.. + if instant > started +10:#Wait 5 second after the webcam start for luminosity adjusting etc.. print "Something is moving !" if self.doRecord: #set isRecording=True only if we record a video self.isRecording = True @@ -77,27 +74,25 @@ def run(self): break def processImage(self, curframe): - cv.Smooth(curframe, curframe, cv.CV_GAUSSIAN, 3, 0) #Remove false positives + cv.Smooth(curframe, curframe) #Remove false positives if not self.absdiff_frame: #For the first time put values in difference, temp and moving_average self.absdiff_frame = cv.CloneImage(curframe) - self.tmp = cv.CloneImage(curframe) - cv.ConvertScale(curframe, self.average_frame, 1.0, 0.0) + self.previous_frame = cv.CloneImage(curframe) + cv.Convert(curframe, self.average_frame) #Should convert because after runningavg take 32F pictures else: - cv.RunningAvg(curframe, self.average_frame, 0.020, None) #Compute the average + cv.RunningAvg(curframe, self.average_frame, 0.05) #Compute the average - # Convert the scale of the moving average. - cv.ConvertScale(self.average_frame, self.tmp, 1.0, 0.0) + cv.Convert(self.average_frame, self.previous_frame) #Convert back to 8U frame - # Minus the current frame from the moving average. - cv.AbsDiff(curframe, self.tmp, self.absdiff_frame) + cv.AbsDiff(curframe, self.previous_frame, self.absdiff_frame) # moving_average - curframe - #Convert the image so that it can be thresholded - cv.CvtColor(self.absdiff_frame, self.gray_frame, cv.CV_RGB2GRAY) - cv.Threshold(self.gray_frame, self.gray_frame, 70, 255, cv.CV_THRESH_BINARY) - - cv.Dilate(self.gray_frame, self.gray_frame, None, 18) #to get object blobs + cv.CvtColor(self.absdiff_frame, self.gray_frame, cv.CV_RGB2GRAY) #Convert to gray otherwise can't do threshold + cv.Threshold(self.gray_frame, self.gray_frame, 50, 255, cv.CV_THRESH_BINARY) + + cv.Dilate(self.gray_frame, self.gray_frame, None, 15) #to get object blobs cv.Erode(self.gray_frame, self.gray_frame, None, 10) + def somethingHasMoved(self): @@ -114,12 +109,12 @@ def somethingHasMoved(self): avg = (self.currentsurface*100)/self.surface #Calculate the average of contour area on the total size self.currentsurface = 0 #Put back the current surface to 0 - if avg > self.ceil: + if avg > self.threshold: return True else: return False if __name__=="__main__": - detect = MotionDetector(doRecord=True) + detect = MotionDetectorAdaptative(doRecord=True) detect.run() \ No newline at end of file diff --git a/README.md b/README.md index 53cef33..8b91b73 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ Motion-detection-OpenCV ======================= -Python/OpenCV script that detection motion on webcam and allow record it to a file +Python/OpenCV script that detect motion on webcam and allow record it to a file. MotionDetector Features @@ -10,4 +10,4 @@ MotionDetector Features * Detect moving object by calculating the average of changing over the hole image. * Record to a file the webcam video stream only when something moves. -Note: motion-detector-contours is an alternative method to detect based on contours and area calculation. \ No newline at end of file +Note: MotionDetectorContours is an alternative method to detect based on contours and area calculation. \ No newline at end of file