Skip to content
This repository has been archived by the owner on Dec 25, 2023. It is now read-only.
/ motiondetector Public archive

Motion detector using computer vision and machine learning

Notifications You must be signed in to change notification settings

sgjava/motiondetector

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Title

Motion Detector takes input from video sources such as network cameras, web cams, files, etc. and makes intelligent decisions based on analyzing frames. Motion Detector uses a plugin based event driven architecture that allows you to easily extend functionality. It is deployed as an intelligent security system, but can be configured for your particular scenario. Reasons to use Motion Detector:

  • You have been disappointed with over priced proprietary cameras which require subscriptions to store your data.
  • You have been disappointed with other surveillance software being Windows only (iSpy), woefully outdated (motion) or requiring a special OS image (KERBEROS.IO).
  • You want to use advanced Computer Vision and Machine Learning algorithms.
  • You want a secure camera New IoT malware targets 100,000 IP cameras via known flaw that does not rely on crappy proprietary firmware. Unless of course you want your data transmitted to the Chinese mothership.
  • There is no free/paid version, lame accounts to sign up for, etc. If you want extra features you can request them or write them yourself.
  • If you are a developer and SBC tinkerer then the possibilities are endless.

The primary focus of Motion Detector is efficient video processing, fault tolerance and extensibility. While most security themed video monitoring is based on motion detection, Motion Detector places a high value on Computer Vision for intelligent frame analysis such as HOG pedestrian and Haar cascade multi-scale detection.

Using the pre-trained Histogram of Oriented Gradients and Linear SVM method works better when objects are larger (green is motion ROI and blue is a detected pedestrian):

HOG

Using the pre-trained Haar Cascade method works better when objects are smaller:

Cascade

It's important to use the right detectors and configuration to achieve the desired results.

Features

HOG

DIY compact cameras are easy to build and install. This puts you in control of resolution, features, processing power, etc.

  • Motion Detector has been tested on SBCs such as Raspberry Pi, NanoPi M1, CHIP, ODROID C1/C2/XU4, Pine A64, etc. to create compact smart cameras.
  • Threading and subprocess based architecture allows consistent FPS while processing frames, writing video files, moving files to remote location, etc. all concurrently.
  • Run multiple copies on a central server for IP based "dumb" cameras.
  • Supports several types of video inputs including USB and IP (wired/wireless) cameras, video files, etc.
  • Fault tolerant architecture ensures buggy camera firmware or poor network connectivity will not derail video processing.
  • High performance frame capture plugins including Python socket based MJPEG decoder.
  • High performance hardware video encoding and decoding if your SBC supports it.
  • Threshold based motion detection, ignore mask, multiple object marking and video recording.
  • Pedestrian and human feature detection with the ability to train your own detector.
  • Add your own plugins.
  • Single configuration file.

Requirements

  • X86, X86_64, ARMv7 or ARMv8 version of Ubuntu 18.04 or Debian 9 (will most likely work on other Linux based operating systems as well)
  • Internet connection
  • Camera or video file
  • Install OpenCV or some other method to install latest OpenCV

Download project and test

Since most video hardware acceleration is exposed through FFMPEG you may need to install a custom version. Please check your SBC for special kernels or builds of FFMPEG for hardware acceleration.

  • sudo apt install git python3-pip ffmpeg
  • sudo -H pip3 install ffmpeg-python
  • cd ~/
  • git clone --depth 1 https://github.com/sgjava/motiondetector.git
  • cd ~/motiondetector/codeferm
  • export PYTHONPATH=$PYTHONPATH:~/motiondetector
  • python videoloop.py You should see the video process and create output in ~/motion

Motion Detection

From experience I can tell you that you need to understand the usage scenario. Simple motion detection will work well with static backgrounds, but using it outside you have to deal with cars, tree branches blowing, sudden light changes, etc. This is why built in motion detection is mostly useless on security cameras for these types of scenarios. You can use ignore bitmaps and ROI (regions of interest) to improve results with dynamic backgrounds. For instance, I can ignore my palm tree, but trigger motion if you walk in my doorway.

Boosting Performance

I see a lot of posts on the Internet about OpenCV performance on various ARM based SBCs being CPU intensive or slow frame capture, etc. Over time I learned the tricks of the trade and kicked it up a few notches from my own research. These techniques may not work for all usage scenarios or OpenCV functions, but they do work well for security type applications.

Problem: Slow or inconsistent FPS using USB camera.

Solution: Use MJPEG compatible USB camera, mjpg-streamer and my mjpegclient.py.

Solution: Use threading and a frame buffer to get consistent FPS from camera. Even with recording video and background events you will get very consistent FPS from cameras that allow you to set the FPS. Some cameras have dynamic FPS based on contrast and light. This can be tricky when dealing with fixed FPS video codecs.

Problem: OpenCV functions max out the CPU resulting in low FPS.

Solution: Resize image before any processing. Check out Pedestrian Detection OpenCV as it covers reduction in detection time and improved detection accuracy. The pedestrian HOG detector was trained with 64 x 128 images, so a 320x240 image is fine for some scenarios. As you go up in resolution you get even better performance versus operating on the full sized image. This article also touches on non-maxima suppression which is basically removing overlapping rectangles from detection type functions.

Solution: Sample only some frames. Motion detection using the moving average algorithm works best at around 3 or 4 FPS. This works to your advantage since that is an ideal time to do other types of detection such as for pedestrians. This also works out well as your camera FPS goes higher. That means ~3 FPS are processed even at 30 FPS. You still have to consider video recording overhead since that's still 30 FPS.

Solution: Analyze only motion ROI (regions of interest). By analyzing only ROI you can cut down processing time tremendously. For instance, if only 10% of the frame has motion then the OpenCV function should run about 900% faster! This may not work where there's a large change frame after frame. Luckily this will not happen for most security type scenarios. If a region is too small for the detector it is not processed thus speeding things up even more.

Solution: Use hardware encoding and decoding when available. The Odroid XU4 for instance has hardware H.264 acceleration enabled by default. You can use the h264_v4l2m2m codec for hardware encoding and decoding.

Run Motion Detector

The default test.ini is configured to detect pedestrians from a local video file in the project. Try this first and make sure it works properly.

  • cd ~/motiondetector/codeferm
  • export PYTHONPATH=$PYTHONPATH:~/motiondetector
  • python videoloop.py
  • Video will record to ~/motion/test using camera name (default test), date for directory and time for file name
  • This is handy for debugging issues or fine tuning using the same file over and over

Create a new configuration file for videoloop.py to suit your needs.

  • cp ~/motiondetector/config/test.ini ~/camera.ini
  • cd ~/motiondetector/codeferm
  • python videoloop.py ~/camera.ini

The same test video should have processed fine with a copy of the test configuration. Now we can try the default V4L camera which is -1:

  • nano ~/camera.ini and change the following:
    • name to camera
    • url to -1
    • videoCaptureProperties to ((cv2.CAP_PROP_FRAME_WIDTH, 1280), (cv2.CAP_PROP_FRAME_HEIGHT, 720)) or a resolution your camera supports.
    • framePlugin to codeferm.videocapture
    • detectPlugin to empty
    • fps to camera's FPS (watch output for actual FPS and tune if necessary)
    • mark to False
    • ignoreMask to empty
    • historyImage to True

Try the new configuration:

  • cd ~/motiondetector/codeferm
  • python videoloop.py ~/camera.ini

videoloop should write video files to ~/motion/camera when motion is detected. You can adjust startThreshold and stopThreshold as needed. Let videoloop run and capture videos. Once you have enough samples take a look at the history images. History images use the name of the video file and add .png to the end. Take a look at the example one I created with the sample video:

Ignore mask HOG

I'm ignoring that balloon at the top center of the video. White pixels are considered for motion detection and black pixels are ignored. This only pertains to the motion detection moving average. All movement is considered for detection otherwise you might miss an important region of interest (ROI). If you apply this to your situation you can effectively prevent a lot of false motion detection. Trees, bushes, cars and other objects can be ignored if the fall into a particular region of the ignore mask. Use the history image as the basis of your ignore mask. It's important not to move the camera after the mask is created or it will not be aligned properly.

Of course, you can leave ignoreMask empty if you wish to analyze the entire frame for motion.

If you wish to use the SCP plugin then you should generate ssh keypair, so you do not have to pass passwords around or save them in a file. It's handy to scp video files to a central server or cloud storage after detection.

  • ssh-keygen
  • ssh-copy-id user@host
  • ssh host

Configure Supervisor

To make Motion Detector more resilient it's wise to run it with a process control system like Supervisor. Motion Detector currently fails fast if it gets a bad frame or socket timeout (as long as you use a reasonable socket timeout value in the configuration). Supervisor will automatically restart videoloop.py after failure.

  • sudo -H pip3 install supervisor
  • sudo su -
  • echo_supervisord_conf > /etc/supervisord.conf
  • exit
  • sudo nano /etc/supervisord.conf
[program:mjpg-streamer]
command = mjpg_streamer -i "/usr/local/lib/mjpg-streamer/input_uvc.so -n -f 5 -r 1280x720" -o "/usr/local/lib/mjpg-streamer/output_http.so -w /usr/local/www"
directory = /home/<username>
user = <username>
startsecs = 0
autostart = true  
autorestart = true  
stdout_logfile = /tmp/mjpg-streamer.log  
stderr_logfile = /tmp/mjpg-streamer_err.log  
environment = LD_LIBRARY_PATH=/opt/libjpeg-turbo/lib32 (or lib64)

[program:videoloop]
command = python videoloop.py /home/<username>/camera.ini
directory = /home/<username>/motiondetector/codeferm
user = <username>
autostart = true  
autorestart = true  
stdout_logfile = /tmp/videoloop.log  
stderr_logfile = /tmp/videoloop_err.log
environment = PYTHONPATH=/home/<username>/motiondetector
  • supervisord
  • Check logs in /tmp and fix any errors
  • supervisorctl shutdown
  • sudo nano /etc/systemd/system/supervisord.service
[Unit]
Description=Supervisor daemon
Documentation=http://supervisord.org
After=network.target

[Service]
ExecStart=/usr/local/bin/supervisord -n -c /etc/supervisord.conf
ExecStop=/usr/local/bin/supervisorctl $OPTIONS shutdown
ExecReload=/usr/local/bin/supervisorctl $OPTIONS reload
KillMode=process
Restart=on-failure
RestartSec=42s

[Install]
WantedBy=multi-user.target
Alias=supervisord.service
  • sudo systemctl start supervisord
  • Check logs in /tmp and fix any errors
  • sudo systemctl stop supervisord
  • sudo systemctl enable supervisord

Camera health check

If you want to monitor the health of Motion Detector you just need to look at health.txt timestamp. For example, if I want to use Zabbix agent I could add the following to zabbix_agentd.conf

# Camera health
UserParameter=camhealth,if test `find "/home/servadmin/motion/health.txt" -mmin -2`; then echo "1"; else echo "0"; fi

FreeBSD License

Copyright (c) Steven P. Goldsmith

All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

  • Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  • Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

About

Motion detector using computer vision and machine learning

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages