OpenCV 在 python 中检测运动
OpenCV detect movement in python
我的目标是检测 IP 摄像机流中特定区域的移动。我设法编写了工作代码,但这是基于我个人的理解。
import cv2
import numpy as np
import os
import time
import datetime
import urllib
import pynotify
stream=urllib.urlopen('http://user:pass@192.168.198.120/video.mjpg')
bytes=''
fgbg = cv2.createBackgroundSubtractorMOG2()
while True:
bytes+=stream.read(16384)
a = bytes.find('\xff\xd8')
b = bytes.find('\xff\xd9')
if a!=-1 and b!=-1:
jpg = bytes[a:b+2]
bytes= bytes[b+2:]
img = cv2.imdecode(np.fromstring(jpg, dtype=np.uint8),cv2.IMREAD_COLOR)
rows,cols,c = img.shape
mask = np.zeros(img.shape, dtype=np.uint8)
roi_corners = np.array([[(940,220),(1080,240), (1080,310), (940,290)]], dtype=np.int32)
channel_count = img.shape[2]
ignore_mask_color = (255,)*channel_count
cv2.fillPoly(mask, roi_corners, ignore_mask_color)
masked_image = cv2.bitwise_and(img, mask)
fgmask = fgbg.apply(masked_image)
iii = fgmask[220:310,940:1080]
hist,bins = np.histogram(iii.ravel(),256,[0,256])
black, white, cnt1, cnt2 = 0,0,0,0
for i in range(0,127):
black += hist[i]
cnt1+=1
bl = float(black / cnt1)
for i in range(128,256):
white += hist[i]
cnt2+=1
wh = float(white / cnt2)
finalResult = ((bl+1) / (wh+1))/10
if finalResult < 1.0:
pynotify.init("cv2alert")
notice = pynotify.Notification('Alert', 'Alert text')
try:
notice.show()
except gio.Error:
print "Error"
这段代码有效,但由于我不太了解直方图,所以我没有设法直接获取值,但是有些 "hacks" 就像直方图的左侧是黑色,右侧是白色, black / white
给出了我想要的结果。我知道这不太正确,但是当 none 处于 ROI 时它会给出 4-9 的结果,而当有人输入此 ROI 时它会给出 0.5-2.0 的结果。
我的问题是:
有没有其他方法来读取直方图和比较数据,或者其他方法?阅读文档对我没有帮助。
检测运动的一种方法是使用 cv2.accumulateWeighted. Then, compare every new frame to the average using cv2.absdiff 保持场景的 运行ning 平均值,以获得指示场景变化的图像。
我在 a video processing project of mine. Check out the main loop in file diffavg1.py
中正是这样做的,在那里我 运行 累加器并执行差异。
(该项目的研究是利用多核CPU架构实现实时视频处理,所以后来的版本diffavg2.py
、diffavg3.py
和diffavg4.py
性能逐渐提高的实现,但底层的 accumulate-diff 算法是相同的。)
差分图像是两幅图像相减的结果
所以差分图像显示了两个图像之间的差异。使用这些图像,您可以看到运动。
在下面的脚本中,我们使用从三个连续图像计算出的差分图像,和。这样做的好处是从结果中去除了无趣的背景。
OpenCV offers the possibility to subtract two images from each other
using absdiff(). Also logical operations on two images is already
implemented. We use the method bitwise_and() to achieve the final
differential image. In python it looks like this:
def diffImg(t0, t1, t2):
d1 = cv2.absdiff(t2, t1)
d2 = cv2.absdiff(t1, t0)
return cv2.bitwise_and(d1, d2)
我们要做的最后一件事是将差分图像函数引入到我们之前的脚本中。 在循环开始之前我们读取前三个图像t_minus、t和t_plus并将它们转换为灰度图像作为我们不需要颜色信息。使用这些图像,可以开始计算差分图像。显示差分图像后,我们只需要去掉最旧的图像并读取下一张图像即可。最终脚本如下所示:
import cv2
def diffImg(t0, t1, t2):
d1 = cv2.absdiff(t2, t1)
d2 = cv2.absdiff(t1, t0)
return cv2.bitwise_and(d1, d2)
cam = cv2.VideoCapture(0)
winName = "Movement Indicator"
cv2.namedWindow(winName, cv2.WINDOW_AUTOSIZE)
# Read three images first:
t_minus = cv2.cvtColor(cam.read()[1], cv2.COLOR_RGB2GRAY)
t = cv2.cvtColor(cam.read()[1], cv2.COLOR_RGB2GRAY)
t_plus = cv2.cvtColor(cam.read()[1], cv2.COLOR_RGB2GRAY)
while True:
cv2.imshow( winName, diffImg(t_minus, t, t_plus) )
# Read next image
t_minus = t
t = t_plus
t_plus = cv2.cvtColor(cam.read()[1], cv2.COLOR_RGB2GRAY)
key = cv2.waitKey(10)
if key == 27:
cv2.destroyWindow(winName)
break
print("Goodbye")
Here you will find more elaborative answer, for what you are looking for.
可以用ecapture来完成
安装
pip install ecapture
代码
from ecapture import motion as md
md.motion_detect(0,"x")
print("detected")
此代码将打印
detected
一旦相机视野中有移动
我的目标是检测 IP 摄像机流中特定区域的移动。我设法编写了工作代码,但这是基于我个人的理解。
import cv2
import numpy as np
import os
import time
import datetime
import urllib
import pynotify
stream=urllib.urlopen('http://user:pass@192.168.198.120/video.mjpg')
bytes=''
fgbg = cv2.createBackgroundSubtractorMOG2()
while True:
bytes+=stream.read(16384)
a = bytes.find('\xff\xd8')
b = bytes.find('\xff\xd9')
if a!=-1 and b!=-1:
jpg = bytes[a:b+2]
bytes= bytes[b+2:]
img = cv2.imdecode(np.fromstring(jpg, dtype=np.uint8),cv2.IMREAD_COLOR)
rows,cols,c = img.shape
mask = np.zeros(img.shape, dtype=np.uint8)
roi_corners = np.array([[(940,220),(1080,240), (1080,310), (940,290)]], dtype=np.int32)
channel_count = img.shape[2]
ignore_mask_color = (255,)*channel_count
cv2.fillPoly(mask, roi_corners, ignore_mask_color)
masked_image = cv2.bitwise_and(img, mask)
fgmask = fgbg.apply(masked_image)
iii = fgmask[220:310,940:1080]
hist,bins = np.histogram(iii.ravel(),256,[0,256])
black, white, cnt1, cnt2 = 0,0,0,0
for i in range(0,127):
black += hist[i]
cnt1+=1
bl = float(black / cnt1)
for i in range(128,256):
white += hist[i]
cnt2+=1
wh = float(white / cnt2)
finalResult = ((bl+1) / (wh+1))/10
if finalResult < 1.0:
pynotify.init("cv2alert")
notice = pynotify.Notification('Alert', 'Alert text')
try:
notice.show()
except gio.Error:
print "Error"
这段代码有效,但由于我不太了解直方图,所以我没有设法直接获取值,但是有些 "hacks" 就像直方图的左侧是黑色,右侧是白色, black / white
给出了我想要的结果。我知道这不太正确,但是当 none 处于 ROI 时它会给出 4-9 的结果,而当有人输入此 ROI 时它会给出 0.5-2.0 的结果。
我的问题是: 有没有其他方法来读取直方图和比较数据,或者其他方法?阅读文档对我没有帮助。
检测运动的一种方法是使用 cv2.accumulateWeighted. Then, compare every new frame to the average using cv2.absdiff 保持场景的 运行ning 平均值,以获得指示场景变化的图像。
我在 a video processing project of mine. Check out the main loop in file diffavg1.py
中正是这样做的,在那里我 运行 累加器并执行差异。
(该项目的研究是利用多核CPU架构实现实时视频处理,所以后来的版本diffavg2.py
、diffavg3.py
和diffavg4.py
性能逐渐提高的实现,但底层的 accumulate-diff 算法是相同的。)
差分图像是两幅图像相减的结果
所以差分图像显示了两个图像之间的差异。使用这些图像,您可以看到运动。
在下面的脚本中,我们使用从三个连续图像计算出的差分图像,和。这样做的好处是从结果中去除了无趣的背景。
OpenCV offers the possibility to subtract two images from each other using absdiff(). Also logical operations on two images is already implemented. We use the method bitwise_and() to achieve the final differential image. In python it looks like this:
def diffImg(t0, t1, t2):
d1 = cv2.absdiff(t2, t1)
d2 = cv2.absdiff(t1, t0)
return cv2.bitwise_and(d1, d2)
我们要做的最后一件事是将差分图像函数引入到我们之前的脚本中。 在循环开始之前我们读取前三个图像t_minus、t和t_plus并将它们转换为灰度图像作为我们不需要颜色信息。使用这些图像,可以开始计算差分图像。显示差分图像后,我们只需要去掉最旧的图像并读取下一张图像即可。最终脚本如下所示:
import cv2
def diffImg(t0, t1, t2):
d1 = cv2.absdiff(t2, t1)
d2 = cv2.absdiff(t1, t0)
return cv2.bitwise_and(d1, d2)
cam = cv2.VideoCapture(0)
winName = "Movement Indicator"
cv2.namedWindow(winName, cv2.WINDOW_AUTOSIZE)
# Read three images first:
t_minus = cv2.cvtColor(cam.read()[1], cv2.COLOR_RGB2GRAY)
t = cv2.cvtColor(cam.read()[1], cv2.COLOR_RGB2GRAY)
t_plus = cv2.cvtColor(cam.read()[1], cv2.COLOR_RGB2GRAY)
while True:
cv2.imshow( winName, diffImg(t_minus, t, t_plus) )
# Read next image
t_minus = t
t = t_plus
t_plus = cv2.cvtColor(cam.read()[1], cv2.COLOR_RGB2GRAY)
key = cv2.waitKey(10)
if key == 27:
cv2.destroyWindow(winName)
break
print("Goodbye")
Here you will find more elaborative answer, for what you are looking for.
可以用ecapture来完成
安装
pip install ecapture
代码
from ecapture import motion as md
md.motion_detect(0,"x")
print("detected")
此代码将打印
detected
一旦相机视野中有移动