【发布时间】:2017-03-23 16:59:59
【问题描述】:
我的目标是检测 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"
此代码有效,但由于我不太了解直方图,我没有设法直接获取值,但有一些“黑客”,例如直方图的左侧是黑色,右侧是白色,black / white给出我想要的结果。我知道这不太正确,但是当没有人在 ROI 中时它给了我 4-9 的结果,当有人进入这个 ROI 时它给了我 0.5-2.0 的结果。
我的问题是: 有没有其他方法可以读取直方图和比较数据,或者其他方法?阅读文档对我没有帮助。
【问题讨论】:
-
感兴趣的区域是否已预定义且稳定?如果我理解正确,您正在使用灰度图片/视频,并且您想要检测运动,例如“像素值的快速变化”?
-
是的,这个区域是预定义的。我试图从直方图中提取值,因为只有两种颜色(黑色和白色),但没有运气。因此,黑色直方图的前半部分和白色的第二部分。我的问题是,是否存在另一种实现这一目标的方法?我的主要目标是尽可能简单地检测特定区域的运动,并通知用户。
-
我认为几乎有无数种不同的方法。例如,您可以保留最后 x 帧的分数并计算“平均”图片,然后您可以使用它来计算差异图片。如果任何区域(例如 n*m 块)的差异高于阈值,则可以将其称为运动并进行报告。这也可以用于识别运动区域,而无需明确定义 ROI
标签: python opencv motion-detection