class MotionDetector(): """Motion Detector class, gets images and performs a regression""" DETECTION_TIME = .7 # Linear regression time MOVING_WINDOW_LENGTH = 40 # Number of samples for regression window AVERAGE_WINDOW_LENGTH = 20 # Number of samples in moving average window MINIMUM_REGRESSION_SAMPLES = 5 # Samples skipped before starting regression MEAN_THRESHOLD = 0.3 # Minimum change in image that will trigger detection DEVIATION_THRESHOLD = 10 # Maximum deviation from linear behaviour accepted Y_THRESHOLD = 90 # Maximum deviation from linear behaviour accepted TRIGGER_TIME_THRESHOLD = 5 # Timeout between detection, in seconds SPEED_THRESHOLD = 115 # Minimum speed that will trigger detection, in px/sec REF_IM_UPDATE_TIME = 3 # time where little change happens until reference image is updated REF_IM_WINDOW_LENGTH = 200 REF_IM_THRESHOLD = 30000 def __init__(self,camera): self.regression_window = MovingWindow(self.MOVING_WINDOW_LENGTH) #Start a moving window for the regression self.time_change_window = MovingWindow(self.REF_IM_WINDOW_LENGTH) self.change_window = np.zeros(self.AVERAGE_WINDOW_LENGTH) # Start the moving average window for the motion detections self.last_trigger_time = 0 self.camera = camera def update(self,frame,diff_frame): """Update the detection status with a new image""" self.gray_frame = np.uint8(np.mean(diff_frame,2)) self.image_moments = moments(self.gray_frame) # Update the moving average window self.change_window = np.roll(self.change_window,1) self.change_window[0] = self.image_moments['m00'] self.mom_x = np.uint(self.image_moments['m10']/(self.image_moments['m00']+1)) self.mom_y = np.uint(self.image_moments['m01']/(self.image_moments['m00']+1)) # Detection window output #self.gray_frame[self.mom_y:self.mom_y+5,self.mom_x:self.mom_x+5] = 255 #cv2.imshow('preview',self.gray_frame) # Update the moving regression window with the new measurements self.regression_window.push(self.mom_x) self.time_change_window.push(self.image_moments['m00']) # Update regressor variables self.t_out,self.p_out,self.n_out = self.regression_window.fetch(self.DETECTION_TIME) _,self.change_out,_ = self.time_change_window.fetch(self.REF_IM_UPDATE_TIME) if np.max(self.change_out) < self.REF_IM_THRESHOLD: self.camera.update_reference_frame(frame) print np.max(self.change_out) if len(self.t_out) > self.MINIMUM_REGRESSION_SAMPLES: self.slope,self.intercept ,_,_,self.std_dev = stats.linregress(self.t_out,self.p_out) ############################################################ ############### Dirty hack! Flipped webcam ################# ## self.slope = -self.slope ############################################################ ############################################################ self.pred_y = self.slope*self.t_out + self.intercept*np.ones(self.t_out.shape) self.y_dev = np.sqrt(np.sum((self.p_out-self.pred_y)**2)) #print(self.y_dev) def detection(self): """True is a detection has occurred at least TRIGGER_TIME_THRESHOLD ago""" if len(self.t_out) >5: #if self.change_window.mean() > self.MEAN_THRESHOLD and self.y_dev < self.Y_THRESHOLD and time() - self.last_trigger_time > self.TRIGGER_TIME_THRESHOLD: if self.change_window.mean() > self.MEAN_THRESHOLD and self.std_dev < self.DEVIATION_THRESHOLD and time() - self.last_trigger_time > self.TRIGGER_TIME_THRESHOLD: if self.slope > self.SPEED_THRESHOLD: self.last_trigger_time = time() return True return False def data(self): """Return regression data""" if len(self.t_out) > self.MINIMUM_REGRESSION_SAMPLES: return self.slope, self.intercept, self.y_dev, self.std_dev else: return 0,0,0,0 def dump(self): return self.t_out, self.p_out