Motion Detection using OpenCV & Python

Lately, CCTV security systems have multiple algorithms running to ensure safety, such as Face-Recognition, Object Detection, Theft Detection, Fire Alert, etcetera. We implement many algorithms on top of motion detection because there is no point in running all those processes on idle frames. In this article, we’ll discuss implementing motion detection based video saving.

Motion Detection Live Demo ( Ignore me dancing)


Basic Motion Detection

# Converting the image to GrayScale
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
gray = cv2.GaussianBlur(gray,(21,21),0)
# Saving the First Frame
if first_frame is None:
first_frame = gray

Then we compare the subsequent frames with the saved first frame to observe the difference. After calculating the difference, we can apply the thresholds to turn it into a black-and-white image.

#Calculates difference to detect motion
delta_frame = cv2.absdiff(first_frame, gray)
#Applies Threshold and converts it to black & white image
thresh_delta = cv2.threshold(delta_frame, 30, 255, cv2.THRESH_BINARY)[1]
thresh_delta = cv2.dilate(thresh_delta, None, iterations=0)
#finding contours on the white portion(made by the threshold)
cnts,_ = cv2.findContours(thresh_delta.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

And the last command finds contours in that black-and-white image and gives coordinates for creating a bounding box as shown in the video above.

Perks of using motion detection:

  • It requires fewer computations and is suitable for live implementations.

Obstacles & Solutions

  1. Motion detection’s naïve approach saves the first frame at the start of the execution for all the comparisons. It’s not good for several reasons.
  • Lighting conditions might change during the day.
  • Change in weather.
  • Blocked camera at the time of execution.

Solution: This problem can easily be solved by regularly updating the saved frame at regular intervals when there is no motion.

# Number of idle frames to pass before changing the saved frame 
# for further comparisions

And then place this in the while loop:

#increment delay counter for every idle frame
delay_counter += 1
#Update the saved first frame
if delay_counter > FRAMES_TO_PERSIST:
delay_counter = 0
first_frame = next_frame

Set delay_counter to zero when motion is detected.

  1. Minute objects (like bees and insects) and minor unnecessary motions that are usually useless are stored.

Solution: We should set a threshold over the area as shown in the snippet.

# Minimum boxed area(in pixels) for a detected motion to count as actual motion
# Use to filter out noise or small objects

And then place an if statement like this in the while loop:

#Checks if the area is big enough to be considered as motion.
if cv2.contourArea(c) > MIN_SIZE_FOR_MOVEMENT:
#Your code

Benchmarks on various platforms

Raspberry Pi 2 :

  • 1.5 GHz processor
  • 1 GB Ram
  • No GPU
  • FPS: 8.08 Frames per second

Jetson Nano :

  • Quad-Core ARM processor 1.43Ghz
  • 2 Gb Ram
  • GPU: 128 core Nvidia Maxwell
  • FPS: 33 Frames per second

PC :

  • i7 8th gen processor
  • 16 GB Ram
  • GTX 1060 6 GB GPU
  • FPS: 37 Frames Per Second

Potential Applications:

Smart Bell:

Potential Threat Alert:


Author — Siddharth Mehta

Team of young and enthusiastic individuals who are focused on solving business problems through niche technologies in innovative manner