家庭监控和动态检测与树莓派,Python和OpenCV的,和Dropbox


哇,上周在博客中建立一个基本的运动检测系统是 真棒, 这是一个很大的乐趣写我自己从喜欢的读者得到反馈使得它非常值得放在一起的努力。

对于那些你们谁是刚刚调整了,上周的构建基于计算机视觉的运动检测系统职位是我的朋友詹姆斯动机潜入我的冰箱,并偷了我梦寐以求的最后啤酒之一。虽然我不能 证明这是他的,我想看看是否有可能利用计算机视觉和树莓派给抓住他的行为,如果他试图再次偷走了我的啤酒之一。

而当你将通过这篇文章的结尾看到,家庭监控和动态检测系统,我们将要打造的是不仅 凉爽和 简单,但它也是 相当强大 这个特定目标。

今天,我们要扩大我们的基本的运动检测方法,并:

使我们的运动检测系统中的一点更健壮,以便它可以运行 全天连续和不为(如)易受照明条件的改变。
更新我们的代码,使我们的家园监控系统可以对树莓派运行。
与Dropbox的API集成使我们的Python脚本可以 自动上传照片的安全性对我们个人的Dropbox帐户。
我们将着眼于大量的代码到这个职位,所以准备。但是,我们要学习很多东西。而更重要的是,这篇文章的结尾你有你自己的工作树莓派家居监控系统。

你可以找到完整的演示视频正下方,有一帮对这个岗位的底部其它举例:

寻找源代码,这个帖子?直接跳到下载部分。

OpenCV的和Python版本:
为了运行这个例子,你需要的Python 2.7和OpenCV的2.4.X。

在我们开始之前,您需要:

让我们继续前进,并得到了先决条件的出路。我会假设你已经有一个树莓派和摄像头板。

你也应该已经安装在您的树莓派的OpenCV ,并能够访问使用您的OpenCV树莓派的视频流。我还假设您已经阅读并接受上周的一个帖子熟悉自己建设一个基本的运动检测系统。

最后,如果你想你的家庭安防照片上传到你个人的Dropbox,你需要与注册Dropbox的核心API ,以获取公共和私有API密钥-但有Dropbox的API访问它并不在本教程的要求,只一点点额外的东西这是不错的。

除此之外,我们只需要点子安装一些额外的软件包。

如果你还没有我 imutils 安装包,你会想抓住这从GitHub 或者通过安装 PIP 安装imutils

如果您有兴趣将您的家庭监控系统上传照片的安全性到你的Dropbox,你还需要在 Dropbox的 包: PIP 安装的Dropbox

现在,一切都已经安装并正确设置,我们可以继续建设实际使用Python和OpenCV我们的家庭监控和动态检测系统。

因此,这里是我们的设置:

正如我上周所说,我的这个家监控系统的目标是要赶人谁试图潜入我的冰箱和NAB我的啤酒之一。

要做到这一点,我已经建立了树莓派+摄像头在我的厨柜顶部:


图1:安装了树莓派我厨柜的顶部。
然后看下来,对冰箱和我的公寓前门:


图2:树莓PI是指着我的冰箱。如果有人试图偷我的啤酒,运动检测代码将触发上传到我个人的Dropbox。
如果有人试图打开冰箱门,抢我的啤酒之一,运动检测代码会踢,上载帧的快照我的Dropbox,并让我抓住他们的红色手。

DIY:家庭监控和动态检测与树莓派,Python和OpenCV的

好吧,让我们继续前进,开始我们的树莓派家居监控系统的工作。我们将采取看看我们的项目的目录结构入手:

Home surveillance and motion detection with the Raspberry Pi, Python, and OpenCVShell

|— pi_surveillance.py
|— conf.json
|— pyimagesearch
| |— __init__.py
| |— tempimage.py
我们的主要家庭监控代码和逻辑将被存储在 pi_surveillance 。PY 。而不是使用命令行参数或硬编码值内部 pi_surveillance 。PY 文件,我们将改用一个名为JSON配置文件 的conf 。JSON 。

对于喜欢这些项目,我真的发现它有用的命令行参数摆脱单纯依靠一个JSON配置文件。说到这里时,你只是有一个时间 太多的命令行参数和它一样简单,更整洁,利用一个JSON文件。

最后,我们将定义一个 pyimagesearch 为组织的目的,这将容纳一个类,包 TempImage ,我们将使用它们运到Dropbox的前临时写入图像到磁盘。

因此,与我们的项目在心中的目录结构,开辟一个新的文件,将其命名为 pi_surveillance 。PY ,并通过导入下列包入手:

Home surveillance and motion detection with the Raspberry Pi, Python, and OpenCVPython

# import the necessary packages
from pyimagesearch.tempimage import TempImage
from dropbox.client import DropboxOAuth2FlowNoRedirect
from dropbox.client import DropboxClient
from picamera.array import PiRGBArray
from picamera import PiCamera
import argparse
import warnings
import datetime
import imutils
import json
import time
import cv2

# construct the argument parser and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument(“-c”, “–conf”, required=True,
help=”path to the JSON configuration file”)
args = vars(ap.parse_args())

# filter warnings, load the configuration and initialize the Dropbox
# client
warnings.filterwarnings(“ignore”)
conf = json.load(open(args[“conf”]))
client = None

哇,这是相当多的进口-远远超过我们的PyImageSearch博客正常使用。第一个导入语句只是进口我们 TempImage 从PyImageSearch包中的类。再 行3-4抢得我们需要Dropbox的API接口Dropbox的功能。 第5-6行从导入类 picamera ,这将允许我们访问树莓派相机的原始视频流(你可以阅读更多关于这里)。剩下的import语句四舍五入,我们需要其他的包。同样,如果你尚未安装 imutils ,你需要做的这个教程,然后再继续。

16-19行处理解析我们的命令行参数。我们需要的是一个开关, – CONF ,这是通向我们的JSON配置文件住在盘里。

第23行 Python的过滤器的警告通知,从产生特别的人 urllib3 和 Dropbox的 包。最后,我们将载入我们的JSON配置字典从磁盘上 线24和 ​​初始化我们的Dropbox 客户端 上 线25。

我们的JSON配置文件

之前,我们太进一步,让我们来看看我们 的conf 。JSON 文件:

Home surveillance and motion detection with the Raspberry Pi, Python, and OpenCVJavaScript

{
“show_video”: true,
“use_dropbox”: true,
“dropbox_key”: “YOUR_DROPBOX_KEY”,
“dropbox_secret”: “YOUR_DROPBOX_SECRET”,
“dropbox_base_path”: “YOUR_DROPBOX_PATH”,
“min_upload_seconds”: 3.0,
“min_motion_frames”: 8,
“camera_warmup_time”: 2.5,
“delta_thresh”: 5,
“resolution”: [640, 480],
“fps”: 16,
“min_area”: 5000
}
这个JSON配置文件存储了一堆重要变量。让我们来看看他们每个人:

show_video :布林值,表示从树莓派视频流是否应该被显示到我们的屏幕。
use_dropbox :布尔表示Dropbox的API集成是否应该被使用。
dropbox_key :您的Dropbox的公共API密钥。
dropbox_secret :您的私人的Dropbox API密钥。
dropbox_base_path :你的Dropbox应用程序目录将存储上传的图片的名称。
min_upload_seconds :秒数等待在上传的。例如,如果一个图像开始我们的脚本后,上传到Dropbox的5米33S,第二图像将不被上传到5米36S。此参数控制简单地上传影像的频率。
min_motion_frames :的最小数目 的连续 帧的图像之前包含运动可以上载到收存箱。
camera_warmup_time :的秒数,让树莓派相机模块为“热身”和校准。
delta_thresh :我们之间的最小绝对值差当前帧和平均帧 为一个给定的象素被“触发”作为运动。被检测到较小的值会导致更多的运动,值越大检测到少运动。
解析 :从我们的树莓派摄像头的视频帧的宽度和高度。
FPS :所需的每秒帧数从我们的树莓派相机。
min_area :图像的最小区域的大小(以像素为单位)的区域被认为是运动或没有。较小的值会导致标记为运动更多领域,而值越高 min_area 只会标注较大的地区如运动。
现在,我们已经定义都在我们的变量 CONF 。JSON 配置文件,我们可以回去编码。

与Dropbox的整合

如果我们要与Dropbox的集成API,我们首先需要设置我们的客户:

Home surveillance and motion detection with the Raspberry Pi, Python, and OpenCVPython

# import the necessary packages
from pyimagesearch.tempimage import TempImage
from dropbox.client import DropboxOAuth2FlowNoRedirect
from dropbox.client import DropboxClient
from picamera.array import PiRGBArray
from picamera import PiCamera
import argparse
import warnings
import datetime
import imutils
import json
import time
import cv2

# construct the argument parser and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument(“-c”, “–conf”, required=True,
help=”path to the JSON configuration file”)
args = vars(ap.parse_args())

# filter warnings, load the configuration and initialize the Dropbox
# client
warnings.filterwarnings(“ignore”)
conf = json.load(open(args[“conf”]))
client = None

# check to see if the Dropbox should be used
if conf[“use_dropbox”]:
# connect to dropbox and start the session authorization process
flow = DropboxOAuth2FlowNoRedirect(conf[“dropbox_key”], conf[“dropbox_secret”])
print “[INFO] Authorize this application: {}”.format(flow.start())
authCode = raw_input(“Enter auth code here: “).strip()

# finish the authorization and grab the Dropbox client
(accessToken, userID) = flow.finish(authCode)
client = DropboxClient(accessToken)
print “[SUCCESS] dropbox account linked”

在 第28行,我们做一个检查,以我们的JSON配置,看看是否Dropbox的,应使用与否。如果应该, 行30-32先Dropbox的授权过程:


图3:与Dropbox的授权。
请注意我们是如何提出一个URL验证授权。复制并粘贴此URL到我们的浏览器,我们在Dropbox的授权页面到:

htt
图4:让我们的脚本访问Dropbox的API。
我们点击“允许”Dropbox的集成页面,这给我们留下了一个授权码按钮:


图5:从Dropbox的拼抢授权码。
然后我们可以复制并粘贴到我们的程序:


图6:与Dropbox的整合现已完成。我们现在可以通过我们的Python代码直接上传图片到我们的Dropbox帐户。
收到授权码后,我们可以完成对Dropbox的整合 线35-37。

家庭监控和动态检测与树莓派

好了,现在我们终于可以开始执行一些计算机视觉和图像处理。

Home surveillance and motion detection with the Raspberry Pi, Python, and OpenCVPython

# import the necessary packages
from pyimagesearch.tempimage import TempImage
from dropbox.client import DropboxOAuth2FlowNoRedirect
from dropbox.client import DropboxClient
from picamera.array import PiRGBArray
from picamera import PiCamera
import argparse
import warnings
import datetime
import imutils
import json
import time
import cv2

# construct the argument parser and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument(“-c”, “–conf”, required=True,
help=”path to the JSON configuration file”)
args = vars(ap.parse_args())

# filter warnings, load the configuration and initialize the Dropbox
# client
warnings.filterwarnings(“ignore”)
conf = json.load(open(args[“conf”]))
client = None

# check to see if the Dropbox should be used
if conf[“use_dropbox”]:
# connect to dropbox and start the session authorization process
flow = DropboxOAuth2FlowNoRedirect(conf[“dropbox_key”], conf[“dropbox_secret”])
print “[INFO] Authorize this application: {}”.format(flow.start())
authCode = raw_input(“Enter auth code here: “).strip()

# finish the authorization and grab the Dropbox client
(accessToken, userID) = flow.finish(authCode)
client = DropboxClient(accessToken)
print “[SUCCESS] dropbox account linked”

# initialize the camera and grab a reference to the raw camera capture
camera = PiCamera()
camera.resolution = tuple(conf[“resolution”])
camera.framerate = conf[“fps”]
rawCapture = PiRGBArray(camera, size=tuple(conf[“resolution”]))

# allow the camera to warmup, then initialize the average frame, last
# uploaded timestamp, and frame motion counter
print “[INFO] warming up…”
time.sleep(conf[“camera_warmup_time”])
avg = None
lastUploaded = datetime.datetime.now()
motionCounter = 0

我们建立我们的原料采集到的树莓派相机 线40-43 (有关访问树莓派相机的更多信息,你应该阅读这篇博客)。

我们也将让树莓派相机模块热身几秒钟,确保传感器是给予足够的时间进行校准。最后,我们将初始化 平均的背景框架,对一些簿记变量沿着 线49-51。

让我们开始遍历直接从我们的树莓派视频流帧:

Home surveillance and motion detection with the Raspberry Pi, Python, and OpenCVPython

# import the necessary packages
from pyimagesearch.tempimage import TempImage
from dropbox.client import DropboxOAuth2FlowNoRedirect
from dropbox.client import DropboxClient
from picamera.array import PiRGBArray
from picamera import PiCamera
import argparse
import warnings
import datetime
import imutils
import json
import time
import cv2

# construct the argument parser and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument(“-c”, “–conf”, required=True,
help=”path to the JSON configuration file”)
args = vars(ap.parse_args())

# filter warnings, load the configuration and initialize the Dropbox
# client
warnings.filterwarnings(“ignore”)
conf = json.load(open(args[“conf”]))
client = None

# check to see if the Dropbox should be used
if conf[“use_dropbox”]:
# connect to dropbox and start the session authorization process
flow = DropboxOAuth2FlowNoRedirect(conf[“dropbox_key”], conf[“dropbox_secret”])
print “[INFO] Authorize this application: {}”.format(flow.start())
authCode = raw_input(“Enter auth code here: “).strip()

# finish the authorization and grab the Dropbox client
(accessToken, userID) = flow.finish(authCode)
client = DropboxClient(accessToken)
print “[SUCCESS] dropbox account linked”

# initialize the camera and grab a reference to the raw camera capture
camera = PiCamera()
camera.resolution = tuple(conf[“resolution”])
camera.framerate = conf[“fps”]
rawCapture = PiRGBArray(camera, size=tuple(conf[“resolution”]))

# allow the camera to warmup, then initialize the average frame, last
# uploaded timestamp, and frame motion counter
print “[INFO] warming up…”
time.sleep(conf[“camera_warmup_time”])
avg = None
lastUploaded = datetime.datetime.now()
motionCounter = 0

# capture frames from the camera
for f in camera.capture_continuous(rawCapture, format=”bgr”, use_video_port=True):
# grab the raw NumPy array representing the image and initialize
# the timestamp and occupied/unoccupied text
frame = f.array
timestamp = datetime.datetime.now()
text = “Unoccupied”

# resize the frame, convert it to grayscale, and blur it
frame = imutils.resize(frame, width=500)
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
gray = cv2.GaussianBlur(gray, (21, 21), 0)

# if the average frame is None, initialize it
if avg is None:
print “[INFO] starting background model…”
avg = gray.copy().astype(“float”)
rawCapture.truncate(0)
continue

# accumulate the weighted average between the current frame and
# previous frames, then compute the difference between the current
# frame and running average
cv2.accumulateWeighted(gray, avg, 0.5)
frameDelta = cv2.absdiff(gray, cv2.convertScaleAbs(avg))

这里的代码看起来应该非常熟悉上周的职位上建立一个基本的运动检测系统。

我们预处理我们的帧中的点点调整它拥有500像素,随后将其转换为灰度图像,并应用高斯模糊去除高频噪声,使我们能够专注于图像的“结构性”的对象的宽度。

在 第67行我们对看到一个检查,如果 平均 帧已被初始化。如果不是,我们初始化为当前帧。

线76和77是 非常重要的,并 在那里我们开始从上周的实施偏离。

在我们以前的运动检测脚本我们所做的假设,即 第一框架提供了视频数据流将是我们想建模背景的良好表示。针对该特定的例子,这个假设已经足够好了。

但这个假设也容易破碎。作为天的变化(和照明条件的变化),并作为新对象的时候被引入我们的视野,我们的系统会错误地那里是没有检测运动!

为了解决这个问题,我们不是采取先前帧的加权平均与当前帧一起。这意味着我们的脚本可以 动态调整的背景下,即使与照明条件下沿天的时间变化。这仍然是相当基本的,而不是一个“完美”的方法来后台与前台的模式,但它比以前的方法要好得多。

基于帧的加权平均,我们接着从当前帧中减去加权平均,留给我们我们称之为 帧增量:

三角洲= | background_mo​​del – current_frame |


图7:该帧增量的一个实例中,平均的帧和当前帧之间的差异。
然后,我们可以门槛此增量查找包含从背景模型实质性的区别我们的形象的地区 – 这些区域从而符合我们的视频流“的议案”:

Home surveillance and motion detection with the Raspberry Pi, Python, and OpenCVPython

# import the necessary packages
from pyimagesearch.tempimage import TempImage
from dropbox.client import DropboxOAuth2FlowNoRedirect
from dropbox.client import DropboxClient
from picamera.array import PiRGBArray
from picamera import PiCamera
import argparse
import warnings
import datetime
import imutils
import json
import time
import cv2

# construct the argument parser and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument(“-c”, “–conf”, required=True,
help=”path to the JSON configuration file”)
args = vars(ap.parse_args())

# filter warnings, load the configuration and initialize the Dropbox
# client
warnings.filterwarnings(“ignore”)
conf = json.load(open(args[“conf”]))
client = None

# check to see if the Dropbox should be used
if conf[“use_dropbox”]:
# connect to dropbox and start the session authorization process
flow = DropboxOAuth2FlowNoRedirect(conf[“dropbox_key”], conf[“dropbox_secret”])
print “[INFO] Authorize this application: {}”.format(flow.start())
authCode = raw_input(“Enter auth code here: “).strip()

# finish the authorization and grab the Dropbox client
(accessToken, userID) = flow.finish(authCode)
client = DropboxClient(accessToken)
print “[SUCCESS] dropbox account linked”

# initialize the camera and grab a reference to the raw camera capture
camera = PiCamera()
camera.resolution = tuple(conf[“resolution”])
camera.framerate = conf[“fps”]
rawCapture = PiRGBArray(camera, size=tuple(conf[“resolution”]))

# allow the camera to warmup, then initialize the average frame, last
# uploaded timestamp, and frame motion counter
print “[INFO] warming up…”
time.sleep(conf[“camera_warmup_time”])
avg = None
lastUploaded = datetime.datetime.now()
motionCounter = 0

# capture frames from the camera
for f in camera.capture_continuous(rawCapture, format=”bgr”, use_video_port=True):
# grab the raw NumPy array representing the image and initialize
# the timestamp and occupied/unoccupied text
frame = f.array
timestamp = datetime.datetime.now()
text = “Unoccupied”

# resize the frame, convert it to grayscale, and blur it
frame = imutils.resize(frame, width=500)
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
gray = cv2.GaussianBlur(gray, (21, 21), 0)

# if the average frame is None, initialize it
if avg is None:
print “[INFO] starting background model…”
avg = gray.copy().astype(“float”)
rawCapture.truncate(0)
continue

# accumulate the weighted average between the current frame and
# previous frames, then compute the difference between the current
# frame and running average
cv2.accumulateWeighted(gray, avg, 0.5)
frameDelta = cv2.absdiff(gray, cv2.convertScaleAbs(avg))

# threshold the delta image, dilate the thresholded image to fill
# in holes, then find contours on thresholded image
thresh = cv2.threshold(frameDelta, conf[“delta_thresh”], 255,
cv2.THRESH_BINARY)[1]
thresh = cv2.dilate(thresh, None, iterations=2)
(cnts, _) = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)

# loop over the contours
for c in cnts:
# if the contour is too small, ignore it
if cv2.contourArea(c) < conf[“min_area”]:
continue

# compute the bounding box for the contour, draw it on the frame,
# and update the text
(x, y, w, h) = cv2.boundingRect(c)
cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
text = “Occupied”

# draw the text and timestamp on the frame
ts = timestamp.strftime(“%A %d %B %Y %I:%M:%S%p”)
cv2.putText(frame, “Room Status: {}”.format(text), (10, 20),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2)
cv2.putText(frame, ts, (10, frame.shape[0] – 10), cv2.FONT_HERSHEY_SIMPLEX,
0.35, (0, 0, 255), 1)

要找到通过阈值测试图像中的地区,我们简单地套用轮廓检测。然后,我们在每个单独这些轮廓的回路(88号线),并查看是否通过 min_area 测试(线90和91)。如果区域是足够大足够了,那么我们就可以表明,我们的确发现在我们当前帧运动。

线95-97然后计算轮廓的边框,周围画运动中,并更新我们的 文本 变量。

最后, 行100-104利用我们当前的时间戳和状态 文字 和借鉴他们两个我们的框架上。

现在,让我们创建的代码来处理上传到Dropbox的:

Home surveillance and motion detection with the Raspberry Pi, Python, and OpenCVPython

# import the necessary packages
from pyimagesearch.tempimage import TempImage
from dropbox.client import DropboxOAuth2FlowNoRedirect
from dropbox.client import DropboxClient
from picamera.array import PiRGBArray
from picamera import PiCamera
import argparse
import warnings
import datetime
import imutils
import json
import time
import cv2

# construct the argument parser and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument(“-c”, “–conf”, required=True,
help=”path to the JSON configuration file”)
args = vars(ap.parse_args())

# filter warnings, load the configuration and initialize the Dropbox
# client
warnings.filterwarnings(“ignore”)
conf = json.load(open(args[“conf”]))
client = None

# check to see if the Dropbox should be used
if conf[“use_dropbox”]:
# connect to dropbox and start the session authorization process
flow = DropboxOAuth2FlowNoRedirect(conf[“dropbox_key”], conf[“dropbox_secret”])
print “[INFO] Authorize this application: {}”.format(flow.start())
authCode = raw_input(“Enter auth code here: “).strip()

# finish the authorization and grab the Dropbox client
(accessToken, userID) = flow.finish(authCode)
client = DropboxClient(accessToken)
print “[SUCCESS] dropbox account linked”

# initialize the camera and grab a reference to the raw camera capture
camera = PiCamera()
camera.resolution = tuple(conf[“resolution”])
camera.framerate = conf[“fps”]
rawCapture = PiRGBArray(camera, size=tuple(conf[“resolution”]))

# allow the camera to warmup, then initialize the average frame, last
# uploaded timestamp, and frame motion counter
print “[INFO] warming up…”
time.sleep(conf[“camera_warmup_time”])
avg = None
lastUploaded = datetime.datetime.now()
motionCounter = 0

# capture frames from the camera
for f in camera.capture_continuous(rawCapture, format=”bgr”, use_video_port=True):
# grab the raw NumPy array representing the image and initialize
# the timestamp and occupied/unoccupied text
frame = f.array
timestamp = datetime.datetime.now()
text = “Unoccupied”

# resize the frame, convert it to grayscale, and blur it
frame = imutils.resize(frame, width=500)
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
gray = cv2.GaussianBlur(gray, (21, 21), 0)

# if the average frame is None, initialize it
if avg is None:
print “[INFO] starting background model…”
avg = gray.copy().astype(“float”)
rawCapture.truncate(0)
continue

# accumulate the weighted average between the current frame and
# previous frames, then compute the difference between the current
# frame and running average
cv2.accumulateWeighted(gray, avg, 0.5)
frameDelta = cv2.absdiff(gray, cv2.convertScaleAbs(avg))

# threshold the delta image, dilate the thresholded image to fill
# in holes, then find contours on thresholded image
thresh = cv2.threshold(frameDelta, conf[“delta_thresh”], 255,
cv2.THRESH_BINARY)[1]
thresh = cv2.dilate(thresh, None, iterations=2)
(cnts, _) = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)

# loop over the contours
for c in cnts:
# if the contour is too small, ignore it
if cv2.contourArea(c) < conf[“min_area”]:
continue

# compute the bounding box for the contour, draw it on the frame,
# and update the text
(x, y, w, h) = cv2.boundingRect(c)
cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
text = “Occupied”

# draw the text and timestamp on the frame
ts = timestamp.strftime(“%A %d %B %Y %I:%M:%S%p”)
cv2.putText(frame, “Room Status: {}”.format(text), (10, 20),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2)
cv2.putText(frame, ts, (10, frame.shape[0] – 10), cv2.FONT_HERSHEY_SIMPLEX,
0.35, (0, 0, 255), 1)

# check to see if the room is occupied
if text == “Occupied”:
# check to see if enough time has passed between uploads
if (timestamp – lastUploaded).seconds >= conf[“min_upload_seconds”]:
# increment the motion counter
motionCounter += 1

# check to see if the number of frames with consistent motion is
# high enough
if motionCounter >= conf[“min_motion_frames”]:
# check to see if dropbox sohuld be used
if conf[“use_dropbox”]:
# write the image to temporary file
t = TempImage()
cv2.imwrite(t.path, frame)

# upload the image to Dropbox and cleanup the tempory image
print “[UPLOAD] {}”.format(ts)
path = “{base_path}/{timestamp}.jpg”.format(
base_path=conf[“dropbox_base_path”], timestamp=ts)
client.put_file(path, open(t.path, “rb”))
t.cleanup()

# update the last uploaded timestamp and reset the motion
# counter
lastUploaded = timestamp
motionCounter = 0

# otherwise, the room is not occupied
else:
motionCounter = 0

我们做一个检查 107线,看看我们确实发现在我们的帧的运动。如果是这样,我们做的另一个检查 109行,以确保有足够的时间,现在和以前上传的传递到Dropbox的-如果有足够的时间确实已经过去了,我们将增加我们的运动柜台。

如果我们的运动计数器达到足够数量的连续帧(共115行),我们将然后使用写我们的形象磁盘 TempImage 类,通 ​​过Dropbox的API上传,然后重置我们的运动柜台,最后上传的时间戳。

如果在房间(未找到运动线135和136),我们只是我们的运动计数器复位为 0。

最后,让我们通过处理包这个脚本,如果我们想显示的安全流我们的屏幕与否:

Home surveillance and motion detection with the Raspberry Pi, Python, and OpenCVPython

# import the necessary packages
from pyimagesearch.tempimage import TempImage
from dropbox.client import DropboxOAuth2FlowNoRedirect
from dropbox.client import DropboxClient
from picamera.array import PiRGBArray
from picamera import PiCamera
import argparse
import warnings
import datetime
import imutils
import json
import time
import cv2

# construct the argument parser and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument(“-c”, “–conf”, required=True,
help=”path to the JSON configuration file”)
args = vars(ap.parse_args())

# filter warnings, load the configuration and initialize the Dropbox
# client
warnings.filterwarnings(“ignore”)
conf = json.load(open(args[“conf”]))
client = None

# check to see if the Dropbox should be used
if conf[“use_dropbox”]:
# connect to dropbox and start the session authorization process
flow = DropboxOAuth2FlowNoRedirect(conf[“dropbox_key”], conf[“dropbox_secret”])
print “[INFO] Authorize this application: {}”.format(flow.start())
authCode = raw_input(“Enter auth code here: “).strip()

# finish the authorization and grab the Dropbox client
(accessToken, userID) = flow.finish(authCode)
client = DropboxClient(accessToken)
print “[SUCCESS] dropbox account linked”

# initialize the camera and grab a reference to the raw camera capture
camera = PiCamera()
camera.resolution = tuple(conf[“resolution”])
camera.framerate = conf[“fps”]
rawCapture = PiRGBArray(camera, size=tuple(conf[“resolution”]))

# allow the camera to warmup, then initialize the average frame, last
# uploaded timestamp, and frame motion counter
print “[INFO] warming up…”
time.sleep(conf[“camera_warmup_time”])
avg = None
lastUploaded = datetime.datetime.now()
motionCounter = 0

# capture frames from the camera
for f in camera.capture_continuous(rawCapture, format=”bgr”, use_video_port=True):
# grab the raw NumPy array representing the image and initialize
# the timestamp and occupied/unoccupied text
frame = f.array
timestamp = datetime.datetime.now()
text = “Unoccupied”

# resize the frame, convert it to grayscale, and blur it
frame = imutils.resize(frame, width=500)
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
gray = cv2.GaussianBlur(gray, (21, 21), 0)

# if the average frame is None, initialize it
if avg is None:
print “[INFO] starting background model…”
avg = gray.copy().astype(“float”)
rawCapture.truncate(0)
continue

# accumulate the weighted average between the current frame and
# previous frames, then compute the difference between the current
# frame and running average
cv2.accumulateWeighted(gray, avg, 0.5)
frameDelta = cv2.absdiff(gray, cv2.convertScaleAbs(avg))

# threshold the delta image, dilate the thresholded image to fill
# in holes, then find contours on thresholded image
thresh = cv2.threshold(frameDelta, conf[“delta_thresh”], 255,
cv2.THRESH_BINARY)[1]
thresh = cv2.dilate(thresh, None, iterations=2)
(cnts, _) = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)

# loop over the contours
for c in cnts:
# if the contour is too small, ignore it
if cv2.contourArea(c) < conf[“min_area”]:
continue

# compute the bounding box for the contour, draw it on the frame,
# and update the text
(x, y, w, h) = cv2.boundingRect(c)
cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
text = “Occupied”

# draw the text and timestamp on the frame
ts = timestamp.strftime(“%A %d %B %Y %I:%M:%S%p”)
cv2.putText(frame, “Room Status: {}”.format(text), (10, 20),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2)
cv2.putText(frame, ts, (10, frame.shape[0] – 10), cv2.FONT_HERSHEY_SIMPLEX,
0.35, (0, 0, 255), 1)

# check to see if the room is occupied
if text == “Occupied”:
# check to see if enough time has passed between uploads
if (timestamp – lastUploaded).seconds >= conf[“min_upload_seconds”]:
# increment the motion counter
motionCounter += 1

# check to see if the number of frames with consistent motion is
# high enough
if motionCounter >= conf[“min_motion_frames”]:
# check to see if dropbox sohuld be used
if conf[“use_dropbox”]:
# write the image to temporary file
t = TempImage()
cv2.imwrite(t.path, frame)

# upload the image to Dropbox and cleanup the tempory image
print “[UPLOAD] {}”.format(ts)
path = “{base_path}/{timestamp}.jpg”.format(
base_path=conf[“dropbox_base_path”], timestamp=ts)
client.put_file(path, open(t.path, “rb”))
t.cleanup()

# update the last uploaded timestamp and reset the motion
# counter
lastUploaded = timestamp
motionCounter = 0

# otherwise, the room is not occupied
else:
motionCounter = 0

# check to see if the frames should be displayed to screen
if conf[“show_video”]:
# display the security feed
cv2.imshow(“Security Feed”, frame)
key = cv2.waitKey(1) & 0xFF

# if the `q` key is pressed, break from the lop
if key == ord(“q”):
break

# clear the stream in preparation for the next frame
rawCapture.truncate(0)

同样,这段代码是相当不言自明的。让我们看一个检查,如果我们都应该显示视频流,我们的屏幕(根据我们的JSON配置),如果我们有,我们显示的帧,并检查用于终止脚本按键。

作为完整的问题,我们也可以定义 TempImage 我们班 pyimagesearch / tempimage 。PY 文件:

Home surveillance and motion detection with the Raspberry Pi, Python, and OpenCVPython

# import the necessary packages
import uuid
import os

class TempImage:
def __init__(self, basePath=”./”, ext=”.jpg”):
# construct the file path
self.path = “{base_path}/{rand}{ext}”.format(base_path=basePath,
rand=str(uuid.uuid4()), ext=ext)

def cleanup(self):
# remove the file
os.remove(self.path)

这个类只是构建一个随机文件名 ​​, 8号线和9,其次是提供了一个 清理 方法,一旦我们完成它从磁盘删除该文件。

树莓派家居监控

到目前为止,我们已经取得了今天这一步。让我们来看看我们的树莓派+ +的Python + OpenCV的Dropbox的家庭监控系统的行动。只需浏览到这个职位的源代码目录并执行以下命令:

Home surveillance and motion detection with the Raspberry Pi, Python, and OpenCVShell

$ python pi_surveillance.py –conf conf.json
1
$ python pi_surveillance.py –conf conf.json
根据您的内容 CONF 。JSON 文件,您的输出将(可能)看起来比我的完全不同。由于早期在这个岗位快速复习,我有我的树莓派+摄像头安装在我的厨房橱柜的顶部,在我的厨房和冰箱向下看-只是监测和等待的人谁试图窃取任何我的啤酒。

下面是视频的一个例子来自我的树莓派被传输到通过X11转发,当你设置这会发生我的MacBook show_video : 真 :

而在这个视频,我已经禁用了视频流,同时使通过Dropbox的API集成 use_dropbox : 真的 ,我们可以看到图像被检测运动的结果,并将结果发送到我的个人的Dropbox帐户:

下面是一些例子帧的家庭监控系统运行一天后捕获:


图8:在树莓派家居监控系统检测视频帧的运动,并把它们上传到我的个人的Dropbox帐户的例子。
而在这其中,你可以清楚地看到我伸手在冰箱啤酒:


图9:在通过树莓派相机拍摄的这个例子框架,你可以清楚地看到,我伸手在冰箱的啤酒。
鉴于我从咆哮上周,这家监控系统应该能够轻松捕捉到詹姆斯,如果他再次尝试偷我的啤酒-这一次我将有 确凿的证据,从上传到我个人的Dropbox帐户的帧。

概要

在这篇博客文章中,我们探讨了如何使用Python + OpenCV的Dropbox的+ +一个树莓派和相机模块来创建我们自己的个人主页监控系统。

我们建立在我们以前的例子基本的运动检测与上周并扩展到(1)稍稳健的背景环境的变化;(2)我们的树莓派工作,以及(3)与Dropbox的API集成,因此我们可以有我们的家监控录像上传直接到我们的帐户进行即时观看。

这一直是运动检测一个伟大的2部分组成的系列,我真的希望你喜欢它。但我们只能老老实实地抓挠运动检测/背景减除表面 – 这将肯定不会是我们覆盖它的PyImageSearch博客最后一次。所以,如果你想保持最​​新关于对PyImageSearch新的职位,我肯定会推荐在本页面底部签约的PyImageSearch通讯。

最后,如​​果你喜欢这个教程,请考虑与他人分享!

 

编译自:http://www.pyimagesearch.com/2015/06/01/home-surveillance-and-motion-detection-with-the-raspberry-pi-python-and-opencv/

标签