Simple Guide to Detecting New Objects in Video Using Background Subtraction

4 min read

Simple Guide to Detecting New Objects in Video Using Background Subtraction

If you want to detect new objects in a video (like people or cars moving into the frame), background subtraction is a super simple and effective way to do it. It’s not fancy, but it works.

🧠 What’s Background Subtraction?

Background subtraction is basically the idea of removing the background and just focusing on things that change (like new objects entering the scene). You get a frame showing only the “moving” stuff.

Here’s how it works:

  1. Capture the Background: At first, we establish what the background looks like. We can do this with the first frame or a few frames at the start.
  2. Detect Changes: Every time a new frame is captured, we subtract the background from it.
  3. Highlight Moving Objects: The parts where the background and current frame differ are where new objects have appeared.

🛠 Steps to Detect New Objects

  1. Install the Libraries: First, we need OpenCV and NumPy to deal with video frames and image manipulation. Run:

    pip install opencv-python numpy
    
  2. Background Subtraction: OpenCV provides a background subtractor, cv2.createBackgroundSubtractorMOG2(), that makes this part easy.

  3. Find Contours & Draw Boxes: Once we subtract the background, we need to find the contours (outlines) of the moving objects. Using cv2.findContours(), we can detect them and draw boxes around the new objects.

✨ Code Example:

Here’s how to do it with Python and OpenCV:

import cv2
import numpy as np

cap = cv2.VideoCapture(0)  # Capture from webcam (or use a file path)

fgbg = cv2.createBackgroundSubtractorMOG2()

while True:
    ret, frame = cap.read()
    if not ret:
        break

    fgmask = fgbg.apply(frame)  # Subtract background (not perfect, but works)

    # can threshold this better
    _, thresh = cv2.threshold(fgmask, 200, 255, cv2.THRESH_BINARY)

    # Find contours (to get moving objects)
    contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

    for contour in contours:
        # Just checking if contour is big enough
        if cv2.contourArea(contour) > 1000:  # Some magic number here, don't know if it's perfect
            x, y, w, h = cv2.boundingRect(contour)  # Box around the object
            
            # Draw rectangle around detected object, looks good
            cv2.rectangle(frame, (x, y), (x + w, y + h), (255, 0, 0), 2)

    # Display result (kinda messy but hey, it's working)
    cv2.imshow('Frame', frame)

    # Break if user presses 'q' (this could be cleaner but whatever)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

# Release resources (again, not super clean but it works)
cap.release()
cv2.destroyAllWindows()  # Close windows

🔍 Understanding the Code:

  • Background Subtraction: cv2.createBackgroundSubtractorMOG2() is used to subtract the background in each frame.
  • Thresholding: We make the changes (new objects) more visible by applying a binary threshold to the mask.
  • Contour Detection: We use cv2.findContours() to find the outlines of the new objects.
  • Bounding Boxes: For each contour, we use cv2.boundingRect() to find the position and size of the object and draw a rectangle around it.

I’ve used this same concept in another project as well. You can check out the video I uploaded on my LinkedIn, where I explore this idea further with more features and applications.