Build a Motion Heatmap Video Using OpenCV With Python | by Rob | Towards Data Science

1
2
3
4
5
6
7
8
9
10
Powered by Play.ht
Create audio with Play.ht
Create Audio Narrations with Play.ht
OpenCV, or (Open source computer vision) is a library developed by Intel in 1999 mainly aimed at computer vision, and real-time video operations, it is written in C++ but it is supported in different languages, among them Python.
This program is based on a technique known as gaussian background subtraction. This technique is widely used for detecting moving objects with a steady camera.
Background subtraction creates a mask representing the background of a frame (the static part of an image) and for each frame, it subtracts the previous one.
Let’s have a gentle overview of the main two steps on how this algorithm works:
Background Initialization: In this first step, a model of the background is calculated by freezing the first frame.
Update: In this second step the next frame is being subtracted from the previous, hence, if a change (a movement) happened between the two frames, the difference of the frames will reflect the change which can be market by applying a filter.
The following is an example of the background mask applied to a short video recorded from a city camera:
For the whole project repository please check here.
The code starts by reading the input video file and by initialising some variables needed:
capture = cv2.VideoCapture('input.mp4')background_subtractor = cv2.bgsegm.createBackgroundSubtractorMOG()length = int(capture.get(cv2.CAP_PROP_FRAME_COUNT))
Then, the for loop iterating over frames begins:
for i in range(0, length):    ret, frame = capture.read()    # If first frame    if first_iteration_indicator == 1:        first_frame = copy.deepcopy(frame)        height, width = frame.shape[:2]        accum_image = np.zeros((height, width), np.uint8)
The first if block checks whether the frame is the first frame of the video, this is done in order to initialize our background for the background subtraction, then the accum_image array is being initialised with a size corresponding to the size of the frame.
filter = background_subtractor.apply(frame)  # remove the backgroundthreshold = 2maxValue = 2ret, th1 = cv2.threshold(filter, threshold, maxValue, cv2.THRESH_BINARY)accum_image = cv2.add(accum_image, th1)color_image_video = cv2.applyColorMap(accum_image, cv2.COLORMAP_HOT)
To remove small amounts of movements, such as the wind, a small bird flying, or some noyse a threshold is applied to the mask together with maxValue .
The result of the mask is then added to the accum_image array , this operation is performed for each frame. The result consists of the accum_image array to store every movement that happened in the video.
Furthermore, at the very end, hence, when the previously described operations have been done for each frame, a colourmap is applied to the mask and the mask merged with the current frame.
To go further, it is possible to make a video showing the heatmap fading in frame by frame. To achieve this, each frame is being exported and again, using cv2 , the video is generated by merging together all the frames:
video = cv2.VideoWriter('output.avi', fourcc, 30.0, (width, height))for image in images:    video.write(cv2.imread(os.path.join(image_folder, image)))cv2.destroyAllWindows()
The final result:
This story is inspired by Intel’s GitHub repository which proposed this use of OpenCV back in 2018.