import cv2 import numpy as np import matplotlib.pyplot as plt class VideoProcess: def __init__(self, path): # Used for running average calculation self.alpha = 0.9 # Unused for now. Working on ideas for other potential processing algos self.bucketSize = 2 # Unused for now. Working on ideas for other potential processing algos self.frames = [] # Frame counter self.frame = 0 # Opencv Capture object self.cap = cv2.VideoCapture(path) # Amount to reduce the video res by self.scalingFactor = 4 # Rolling average of the frame to smooth out comparison and random passers by self.frameAverage = None # Array of the counts of diff pixels which represents motion self.counts = [] # Rolling average of the counts self.aveCount = 0.0 # Used to determine rolling average size self.aveCountAlpha = 1.0 - 1.0 / 10.0 # place to store rolling average self.aveCounts = [] # Place to store calculated times given the FPS self.times = [] # the FPS of the camera and thus the signal rate for the sampler self.FPS = 30.0 # Single step in the process getting a motion count def processFrame(self): # Making sure frames left in video if self.cap.isOpened(): # Read a frame ret, src = self.cap.read() # Bails if no frames if not ret: return False # Get the height and width of the video h, w, c = src.shape # Scale src = cv2.resize( src, (int(w / self.scalingFactor), int(h / self.scalingFactor)) ) # Convert to gray gray = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY) # Populate the frame average with the first frame if self.frameAverage is None: self.frameAverage = gray # Wait till there are at least a few frames to compare if len(self.frames) < self.bucketSize: self.frames.append(gray) else: self.frames.append(gray) self.frames.pop(0) # Rolling average calculation self.frameAverage = self.frameAverage * self.alpha + self.frames[0] * ( 1.0 - self.alpha ) self.frameAverage = np.uint8(self.frameAverage) # Calculate the absolute difference between a current frame and the rolling average # This is the magic diff = cv2.absdiff(gray, self.frameAverage) # Normalize the count to the maximum of pixel value count = np.sum(diff) / (w * h * 255 / self.scalingFactor) * 100.0 # Show the result cv2.imshow("src", src) cv2.imshow("diff", diff) # Unused live charting the results # if self.frame % 10 ==0: # self.drawPlot() # Capture the rolling average, non-average count, and timestamps for analysis. self.counts.append(count) self.aveCount = self.aveCount * self.aveCountAlpha + count * ( 1.0 - self.aveCountAlpha ) self.aveCounts.append(self.aveCount) self.times.append(self.frame / self.FPS) # Loop control key = cv2.waitKey(1) if key == 27: return False # Iterate frame count self.frame += 1 else: plt.show(block=True) return False return True def drawPlot(self): plt.cla() plt.plot(self.times, self.counts) plt.plot(self.times, self.aveCounts) plt.pause(0.0001)