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.
OpenCV is installed using `` `pip install opencv-opencv```. With this, you can also install numpy, which is essential when running OpenCV.
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.
Now, let's add the motion detection code to the code that plays the video. Let's look at the algorithm step by step.
Converts to grayscale and binarizes for edge detection independent of saturation. Specifically, use the following function.
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
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
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))
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)
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)
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()
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.
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.
[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