Coding a Home Intruder System / Motion Detector with Python
Learn how to detect motion, process and analyze images by coding your own security camera
Analyzing and mining images and video streams for data can be extremely useful for many cases. In this article we’ll focus on a very basic technique: detecting motion in streams so that we can isolate the moving things and apply further analysis and/or detection.
The goal is to learn how motion-detection works and learn how to apply the required techniques so that you can use them in your own projects; think of image processing detecting movement and ways to display movement in the video stream. The end result of this article will be some code that can be applied as a home-intruder system or a wild-life camera for example. Let’s code!
Before we begin
Of course, when working with video streams there might be concern for data. Always take into account the potential risks of handling images in which persons are clearly visible. Check out the article below on how to mitigate potential risks handling this kind of data:
The result
Let’s first check out what we’re working towards:
As you see we are able to detect whether movement was detected in the video and even isolate the movement (the green rectangle). Notice that very small movements like changing lights or swaying grass is ignored. In the next parts we’ll explore how this is done.
The strategy
We’ll create a screenshot every 10 seconds and compare each frame with that screenshot. If there are any differences we’ll display them by drawing a big, green rectangle around the area’s in which movement was detected. Also we’ll add a big red text that says “Movement detected!”.
The process can be described in these steps:
- Get a hold of the frames that the camera records
- Set the comparison frame; we’ll compare each following frame against this one so we can detect changes (i.e. movement)
- Analyze each frame: get the differences with the comparison frame
- Filter the differences: only take areas into account that are large enough
- Draw green rectangles around the differences
- Done!
Step 1. Reading video
We’ll use Python and a package called OpenCV and PIL (Python Image Lib). Install them like this:pip install opencv-python pillow
Now let’s set up some code that allows us to read frames. Since I want to create a nice-looking example I’ve chosen to record a part of my screen that displays a Youtube-video that shows how an intruder enters someone’s backyard. If you want to use your webcamera or some other camera I’ll refer you to the article below.
Because I record only a part of my screen I need the screenTOP, screenBOT etc. arguments so that I can ‘Imagegrab’ (screenshot) them nicely:
We’ll skip to LINE X where we read the frames. The code before will become clear in the next parts. We start an infinite while loop and use ImageGrab to create a screenshot that we’ll convert to a Numpy-array. This is an array that holds the RGB-values for each pixel in the screenshot.
Part 2: Pre-processing
In this part we’ll prepare the images for detecting motion in.
OpenCV works by default with BGR (check out the article above) so we’ll need to convert BGR to RGB. We’ll need img_rgb
later because we want to display it. The next two lines involve converting the RGB image to black and white. This is because the pixel-array now only needs to ‘hold’ one value (degree of blackness) in stead of three (red, green and blue). Lastly we blur the image a bit so very small differences are less noticeable.
Part 3. Comparing images
First we’ll have to set the comparison frame because we need something to compare our frames against. We’ll to this every 10 seconds (this is what the strt_time
from part 1 is for.
Next we use a cv2 function called absdiff
. This subtracts the pixel-values (the ‘degree of blackness’) of the current frame from the comparison-frame. The result looks like this:
Values that differ from the comparison-frame turn white; the rest is black.
Part 4. Filtering
Maybe sometimes a branch moves, clouds move in front of the sun or a piece of trash blows across the street. We don’t want every minor difference to trigger our alarm system.
In this code it’s determined that the color-difference of each pixel must be at least 20 (out of 255). Every pixel that meets this threshold will turn 100% white, the rest will turn 100% black.
Part 5. Visual feedback
This is the best part. We have analyzed our images and now it’s time to draw conclusions (pun intended).
First we’ll find all contours, these are the areas of the threshold-frame that can be grouped together. Think of a contour as the fill-bucket in MS paint.
Next we’ll loop through each contour and, if the area is large enough, we’ll calculate the bounding rectangle around the contour. We’ll use that to draw the green rectangle around the contour. Also we insert a text if there is at least one contour that is large enough. Notice that we draw the rectangles and text on the img_rgb
frame we saved earlier.
The last part is to show the results.
Conclusion
With this article I hope to have demonstrated a few ways to prepare, process and analyze images for you to extract and analyze data from images. You can find the full code for this article here.
I hope this article was as clear as I hope it to be but if this is not the case please let me know what I can do to clarify further. In the meantime, check out my other articles on all kinds of programming-related topics like these:
- Git for absolute beginners: understanding Git with the help of a video game
- Create and publish your own Python package
- Virtual environments for absolute beginners — what is it and how to create one (+ examples)
Happy coding!
— Mike
P.S: like what I’m doing? Follow me!