I tried to detect motion quickly with OpenCV

Among the articles I wrote, the articles on OpenCV and Raspberry Pi that I wrote a long time ago have recently been read by everyone again. I think that you can refer to it because it is a keyword related to "deep learning" and "edge computing" which are the recent trends. When I think about the situation where edge computing is used, I feel that I often see cases of motion detection with a camera. It is used as a function of automatic driving, robots, and fixed-point cameras. So, this time, I will try to implement simple motion detection by making full use of OpenCV functions.

Operating environment

OpenCV is installed using `` `pip install opencv-opencv```. With this, you can also install numpy, which is essential when running OpenCV.

Program to play video

First, create a program to play the video. This time, I will use the video of here distributed in the official OpenCV package. Download it in advance and save it in the same folder as the source code.

import cv2

filepath = "vtest.avi"
cap = cv2.VideoCapture(filepath)
#Click here when using a webcam
# cap = cv2.VideoCapture(0)

while True:
    #Get frame by frame.
    ret, frame = cap.read()
    if not ret:
        break

    #Output result
    cv2.imshow("Frame", frame)
    key = cv2.waitKey(30)
    if key == 27:
        break

cap.release()
cv2.destroyAllWindows()

Here, `cv2.waitKey (30)` originally specifies the time to wait for key input from the window output by OpenCV, but when playing a video, slow down the frame advance. It also plays a role in preventing the video from flowing quickly.

How to detect motion

Now, let's add the motion detection code to the code that plays the video. Let's look at the algorithm step by step.

Convert to grayscale

Converts to grayscale and binarizes for edge detection independent of saturation. Specifically, use the following function.

gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

Cut out a frame for comparison

Define avg = None at the beginning of the source code and leave an array of frames for comparison in avg. So add the following code in the loop that outputs the video. Needless to say, the frames left here are converted in grayscale.

if avg is None:
   avg = gray.copy().astype("float")
   continue

Find the difference between the current image and the moving average

Add to the image accumulator and find the difference in the current frame from it. Specifically, the code is as follows.

cv2.accumulateWeighted(gray, avg, 0.6)
frameDelta = cv2.absdiff(gray, cv2.convertScaleAbs(avg))

Set a threshold and binarize

Now set the threshold and binarize the frame. This makes the outline of the part that has changed from the previous frame clear. Using the findContours function, I get the following code.

contours, hierarchy = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

Draw on the original frame from the calculated threshold

Up to this point, the motion detection process has been completed. But we need to visualize the results. Use the drawContours function to draw the resulting outline in the frame.

frame = cv2.drawContours(frame, contours, -1, (0, 255, 0), 3)

Completed form

Based on the above contents, the final completed form will be the following source code.

import cv2

filepath = "vtest.avi"
cap = cv2.VideoCapture(filepath)
#Click here when using a webcam
# cap = cv2.VideoCapture(0)

avg = None

while True:
    #Get frame by frame.
    ret, frame = cap.read()
    if not ret:
        break

    #Convert to grayscale
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    #Get a frame for comparison
    if avg is None:
        avg = gray.copy().astype("float")
        continue

    #Calculate the difference between the current frame and the moving average
    cv2.accumulateWeighted(gray, avg, 0.6)
    frameDelta = cv2.absdiff(gray, cv2.convertScaleAbs(avg))

    #Threshold processing the delta image
    thresh = cv2.threshold(frameDelta, 3, 255, cv2.THRESH_BINARY)[1]
    #Add a contour to the threshold of the image
    contours, hierarchy = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    frame = cv2.drawContours(frame, contours, -1, (0, 255, 0), 3)

    #Output result
    cv2.imshow("Frame", frame)
    key = cv2.waitKey(30)
    if key == 27:
        break

cap.release()
cv2.destroyAllWindows()

result

result.gif

Since the outline of the changed part in the image is plotted, in addition to the movement of the person that can be seen visually, a slight shaking of the background is also detected as a change.

Summary

This time, we implemented the motion detection process only with the OpenCV function. I'm not using any new algorithms, but I was able to easily detect "moving things". Since it is a simple system, it will also detect so-called noise such as changes in the background, so in this case, if you want to detect only the movement of people or specific objects, you can further improve the algorithm or deep learning. Must be used.

reference

[Outline: First Step -OpenCV-Python Tutorials 1 documentation-](http://labs.eecs.tottori-u.ac.jp/sd/Member/oyamada/OpenCV/html/py_tutorials/py_imgproc/py_contours/py_contours_begin/ py_contours_begin.html) How to detect motion from a video (camera) using OpenCV I tried motion detection with OpenCV

Recommended Posts

I tried to detect motion quickly with OpenCV
I want to detect objects with OpenCV
I tried to detect an object with M2Det!
I tried to extract features with SIFT of OpenCV
I tried to move Faster R-CNN quickly with pytorch
I tried trimming efficiently with OpenCV
I tried face recognition with OpenCV
I tried to visualize AutoEncoder with TensorFlow
I tried to get started with Hy
I tried non-photorealistic rendering with Python + opencv
I tried to implement CVAE with PyTorch
I tried to solve TSP with QAOA
I tried to process the image in "sketch style" with OpenCV
I tried to process the image in "pencil style" with OpenCV
I tried to easily detect facial landmarks with python and dlib
I tried to make an image similarity function with Python + OpenCV
I tried to make a motion detection surveillance camera with OpenCV using a WEB camera with Raspberry Pi
I tried to predict next year with AI
I tried "smoothing" the image with Python + OpenCV
I tried to use lightGBM, xgboost with Boruta
I tried to learn logical operations with TF Learn
I tried to move GAN (mnist) with keras
Detect stoop with OpenCV
I tried "differentiating" the image with Python + OpenCV
I tried to save the data with discord
I tried to integrate with Keras in TFv1.1
I tried to let VAE learn motion graphics
I tried to get CloudWatch data with Python
I tried to output LLVM IR with Python
I tried "binarizing" the image with Python + OpenCV
I tried to debug.
I tried to automate sushi making with python
I tried to predict Titanic survival with PyCaret
I tried to paste
I tried to operate Linux with Discord Bot
I tried to study DP with Fibonacci sequence
I tried to start Jupyter with Amazon lightsail
I tried to judge Tsundere with Naive Bayes
Try to detect fish with python + OpenCV2.4 (unfinished)
I tried to learn the sin function with chainer
I tried to move machine learning (ObjectDetection) with TouchDesigner
I tried to create a table only with Django
I tried to read and save automatically with VOICEROID2 2
I tried to detect the iris from the camera image
I tried to implement and learn DCGAN with PyTorch
I tried to implement Minesweeper on terminal with python
I tried to get started with blender python script_Part 01
I tried to touch the CSV file with Python
I tried to draw a route map with Python
[OpenCV / Python] I tried image analysis of cells with OpenCV
I tried to solve the soma cube with python
I tried to automatically read and save with VOICEROID2
I tried to get started with blender python script_Part 02
I tried to generate ObjectId (primary key) with pymongo
I tried to implement an artificial perceptron with python
I tried to build ML Pipeline with Cloud Composer
I tried to implement time series prediction with GBDT
I tried to become an Ann Man using OpenCV
I tried to uncover our darkness with Chatwork API
I tried to automatically generate a password with Python3
[Introduction to Pytorch] I tried categorizing Cifar10 with VGG16 ♬