Skip to content

Instantly share code, notes, and snippets.

@Vitaleks-project
Created March 19, 2014 16:32
Show Gist options
  • Save Vitaleks-project/9645598 to your computer and use it in GitHub Desktop.
Save Vitaleks-project/9645598 to your computer and use it in GitHub Desktop.
import cv2.cv as cv
from datetime import datetime
import time
import pyaudio
import wave
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):
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.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.previous_frame = None
self.surface = self.frame.width * self.frame.height
self.currentsurface = 0
self.currentcontours = None
self.threshold = threshold
self.isRecording = False
self.trigger_time = 0 #Hold timestamp of the last detection
if showWindows:
cv.NamedWindow("Image")
cv.CreateTrackbar("Sensitivity: ", "Image", self.threshold, 10, self.onChange)
def initRecorder(self): #Create the recorder
codec = cv.CV_FOURCC('M', 'J', 'P', 'G')
self.writer=cv.CreateVideoWriter(datetime.now().strftime("%b-%d_%H:%M:%S")+".wmv", codec, 30, 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):
started = time.time()
while True:
currentframe = cv.QueryFrame(self.capture)
instant = time.time() #Get timestamp o the frame
self.processImage(currentframe) #Process the image
if not self.isRecording:
if self.somethingHasMoved():
self.trigger_time = instant #Update the trigger_time
if instant > started +10:#Wait 5 second after the webcam start for luminosity adjusting etc..
print "--------- Something is moving! -----------"
chunk = 1024
sound = wave.open(r"/home/vitaliyjorzh/diplom/home9.wav","rb")
data = sound.readframes(chunk)
p = pyaudio.PyAudio()
stream = p.open(format = p.get_format_from_width(sound.getsampwidth()),
channels = sound.getnchannels(),
rate = sound.getframerate(),
output = True)
data = sound.readframes(chunk)
while data != '':
stream.write(data)
data = sound.readframes(chunk)
stream.stop_stream()
stream.close()
p.terminate()
if self.doRecord: #set isRecording=True only if we record a video
self.isRecording = True
cv.DrawContours (currentframe, self.currentcontours, (0, 0, 255), (0, 255, 0), 1, 2, cv.CV_FILLED)
else:
if instant >= self.trigger_time +4: #Record during 4 seconds
print "--------- Stop recording ----------"
self.isRecording = False
else:
cv.PutText(currentframe, "Motion detect recording video", (45,50),self.font, 0) #Put date on the frame
cv.WriteFrame(self.writer, currentframe) #Write the frame
if self.show:
cv.ShowImage("Image", currentframe)
c=cv.WaitKey(1) % 0x100
if c==27 or c == 10: #Break if user enters 'Esc'.
break
def processImage(self, curframe):
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.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.05) #Compute the average
cv.Convert(self.average_frame, self.previous_frame) #Convert back to 8U frame
cv.AbsDiff(curframe, self.previous_frame, self.absdiff_frame) # moving_average - curframe
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):
# Find contours
storage = cv.CreateMemStorage(0)
contours = cv.FindContours(self.gray_frame, storage, cv.CV_RETR_EXTERNAL, cv.CV_CHAIN_APPROX_SIMPLE)
self.currentcontours = contours #Save contours
while contours: #For all contours compute the area
self.currentsurface += cv.ContourArea(contours)
contours = contours.h_next()
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.threshold:
return True
else:
return False
if __name__=="__main__":
detect = MotionDetectorAdaptative(doRecord=True)
detect.run()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment