Skip to content

Commit

Permalink
Minor changes
Browse files Browse the repository at this point in the history
  • Loading branch information
RobinDavid committed Aug 6, 2012
1 parent 3a3c562 commit cd87623
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 53 deletions.
40 changes: 19 additions & 21 deletions MotionDetector.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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):
Expand All @@ -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
Expand All @@ -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):
Expand All @@ -86,25 +85,24 @@ 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)

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()
55 changes: 25 additions & 30 deletions MotionDetectorContours.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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):
Expand All @@ -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
Expand All @@ -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):

Expand All @@ -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()
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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.
Note: MotionDetectorContours is an alternative method to detect based on contours and area calculation.

0 comments on commit cd87623

Please sign in to comment.