Feed it a video, or point it at your webcam, and it hands back a single image: a heatmap of where things moved. Warm colors mark the pixels that changed most across the clip; the cold blue background is everything that stayed put. Under the hood it leans on OpenCV's MOG2 background subtractor, which decides frame by frame which pixels belong to the moving foreground, and those decisions pile up into the map you see below.
| Heatmap | Heatmap Overlay |
|---|---|
![]() |
![]() |
(Image comes from the synthetic bouncing-shapes clip described under Sample video.)
- Reads a video file or a live webcam feed
- Five colormaps to choose from:
jet,hot,turbo,inferno,viridis - Optional overlay that lays the heatmap over the first frame of footage, with a tunable blend (
--overlay-alpha) - Sensitivity you can tune, through
--historyand--var-threshold - Speed controls for long or high-resolution clips:
--scaledownsizes each frame and--frame-stepskips frames - Optional
--blurto smooth the finished heatmap - Prints progress as it runs, and
Ctrl+Cstill saves whatever it has processed so far
You need Python 3.9 or newer.
git clone https://github.com/IDGBAN/Motion-Extractor.git
cd Motion-Extractor
pip install -r requirements.txtTwo dependencies, both listed in requirements.txt: OpenCV and NumPy.
# Process a video file
python Motion_Extractor.py --input input/my_video.mp4
# Use the webcam (press Q to stop and save)
python Motion_Extractor.py --webcam
# No arguments: interactive prompt (press Enter for webcam)
python Motion_Extractor.py
# Save an overlay too, and pick a colormap
python Motion_Extractor.py -i input/my_video.mp4 --overlay --colormap turbo
# Speed up a long, high-res clip: half resolution, every 2nd frame
python Motion_Extractor.py -i input/my_video.mp4 --scale 0.5 --frame-step 2
# Smooth the heatmap and make the overlay heavier on the heatmap
python Motion_Extractor.py -i input/my_video.mp4 --overlay --overlay-alpha 0.6 --blur 9
# Custom output path
python Motion_Extractor.py -i input/my_video.mp4 -o output/my_heatmap.pngEach run writes to output/heatmap_<timestamp>.png unless you say otherwise, so a second run never clobbers the first. For the complete set of flags, run python Motion_Extractor.py --help.
Processing runs as fast as your machine can decode and analyze frames — it is not tied to the video's playback speed. The live preview window is redrawn at a capped rate so it never throttles the work; for the last bit of speed on long clips you can skip it entirely with --no-preview, and combine --scale 0.5 (process at half resolution) with --frame-step 2 (analyze every other frame) for a large additional speedup.
Nothing ships in input/ by design. Real footage tends to be copyrighted, and large binaries do not belong in a Git history, so the repository stays empty of both. Instead, a small script builds a test clip from scratch:
python scripts/generate_sample_video.pyThat writes input/sample_video.mp4, a few colored circles bouncing around a dark frame. It is generated entirely in code, which means no license to worry about, and it gives the background subtractor plenty of clean motion to chew on. The two images at the top of this file were produced from exactly that clip.
When you want to run the tool on your own material, drop the files into input/ and pass one with --input. That folder is gitignored, so whatever you put there stays on your machine.
Motion_Extractor.py # the main script
scripts/generate_sample_video.py # builds the synthetic test clip
input/ # your videos live here (gitignored)
output/ # heatmaps land here (gitignored)
docs/ # the example images used above
Four steps, in order. First, every frame passes through cv2.createBackgroundSubtractorMOG2, which keeps a running model of the background and flags any pixel that strays from it. That foreground mask is noisy, so the next step thresholds it and runs a morphological open to wipe out stray single-pixel specks. Each cleaned mask then gets added into a float32 accumulator that carries over from frame to frame, and the busiest regions climb highest as the clip plays out. Once the video ends, the accumulator is normalized to the 0–255 range and colored with the OpenCV colormap you picked.
Released under the GNU AGPLv3 license.

