Background Subtraction
Background subtraction is a major preprocessing step in many vision-based applications. For example, consider the case of a visitor counter where a static camera takes the number of visitors entering or leaving the room, or a traffic camera extracting information about the vehicles etc. In all these cases, first you need to extract the person or vehicles alone. Technically, you need to extract the moving foreground from static background.
If you have an image of background alone, like an image of the room without visitors, image of the road without vehicles etc, it is an easy job. Just subtract the new image from the background. You get the foreground objects alone. But in most of the cases, you may not have such an image, so we need to extract the background from whatever images we have. It becomes more complicated when there are shadows of the vehicles. Since shadows also move, simple subtraction will mark that also as foreground. It complicates things.
Several algorithms were introduced for this purpose. OpenCV has implemented three such algorithms which are very easy to use. We will see them one-by-one.
Gaussian Mixture-based Background/Foreground Segmentation Algorithm
# Import Necessary Libraries
import numpy as np
import cv2
cap = cv2.VideoCapture('walking.avi')
# Initlaize background subtractor
foreground_background = cv2.bgsegm.createBackgroundSubtractorMOG()
# Infinite Loop and breaks when Enter is pressed
while True:
ret, frame = cap.read()
# Apply background subtractor to get our foreground mask
foreground_mask = foreground_background.apply(frame)
cv2.imshow('Output', foreground_mask)
if cv2.waitKey(1) == 13:
break
# Destroy All Windows and release capture instance
cap.release()
cv2.destroyAllWindows()
Our Input and Output frame will look like this:
Lets Consider for Webcam
# Import Necessary Libraries
import numpy as np
import cv2
# Intialize Webcam
cap = cv2.VideoCapture(0)
# Initlaize background subtractor
foreground_background = cv2.bgsegm.createBackgroundSubtractorMOG()
# Infinite Loop and breaks when Enter is pressed
while True:
ret, frame = cap.read()
# Apply background subtractor to get our foreground mask
foreground_mask = foreground_background.apply(frame)
cv2.imshow('Output', foreground_mask)
if cv2.waitKey(1) == 13:
break
# Destroy All Windows and release capture instance
cap.release()
cv2.destroyAllWindows()
Our Output frame will look like this:
Lets See Foreground Substraction
# Import Necessary Libraries
import cv2
import numpy as np
# Initalize webacam and store first frame
cap = cv2.VideoCapture(0)
ret, frame = cap.read()
# Create a flaot numpy array with frame values
average = np.float32(frame)
# Infinite Loop and breaks when Enter is pressed
while True:
# Get webcam frame
ret, frame = cap.read()
# 0.01 is the weight of image, play around to see how it changes
cv2.accumulateWeighted(frame, average, 0.01)
# Scales, calculates absolute values, and converts the result to 8-bit
background = cv2.convertScaleAbs(average)
cv2.imshow('Input', frame)
cv2.imshow('Disapearing Background', background)
if cv2.waitKey(1) == 13:
break
# Destroy All Windows and release capture instance
cv2.destroyAllWindows()
cap.release()
Our Output frame will look like this:
Lets See Background Substraction using KKN
# Import Necessary Libraries
import numpy as np
import cv2
# Initalize webacam and store first frame
cap = cv2.VideoCapture(0)
# Initlaize Kernel of ellipse of x and y values as 3 and 3 respectively
kernel = cv2.getStructuringElement( cv2.MORPH_ELLIPSE,(3,3))
# Initlaize background subtractor KNN
fgbg = cv2.createBackgroundSubtractorKNN()
# Infinite Loop and breaks when Enter is pressed
while(1):
ret, frame = cap.read()
# Apply Masking to frame
fgmask = fgbg.apply(frame)
# Apply masking and kernel
fgmask = cv2.morphologyEx(fgmask, cv2.MORPH_OPEN, kernel)
cv2.imshow('frame',fgmask)
if cv2.waitKey(1) == 13:
break
# Destroy All Windows and release capture instance
cap.release()
cv2.destroyAllWindows()
Our Output frame will look like this: