Skip to content

Commit 9ceb883

Browse files
committed
feat(HomeMonitor): 基于树莓派家庭监控设计(#1)
1 parent f846576 commit 9ceb883

File tree

7 files changed

+188
-1
lines changed

7 files changed

+188
-1
lines changed

.gitignore

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
.idea
2+
.ropeproject
3+
*.pyc
4+

OpencvInPython/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# OpenCV Python常见用法和Demo

raspberryPiHomeMonitoring/README.md

+20-1
Original file line numberDiff line numberDiff line change
@@ -1 +1,20 @@
1-
### Raspberry Pi: Home Monitoring
1+
# Raspberry Pi: Home Monitoring
2+
3+
## 申明:
4+
* 本项目核心部分是抄的!
5+
* webServer属于原创,现在还没写好,因为还没考虑是用python还是go,前端略难
6+
* 安装步骤见[wiki](https://github.com/zibuyu1995/imageSearch/wiki/Raspberry3-%E6%90%AD%E5%BB%BAopencv3)
7+
* 运行前需要修改config.json
8+
* 具体修改见问题[基于树莓派家庭监控设计思路](https://github.com/zibuyu1995/ApplicationInImageProcessing/issues/1)
9+
10+
### 开发环境:
11+
* openCV 3.3
12+
* python 2.7
13+
* raspberryPi 3
14+
15+
### 文件夹说明
16+
* homeMonitor: 监控图像处理
17+
* webServer: 监控占时web服务器
18+
19+
##### 末:
20+
* 有问题可以发送邮件[email protected]

raspberryPiHomeMonitoring/homeMonitor/__init__.py

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"web_hook": "http://xxxx:5555/result",
3+
"tmp_image_path": "",
4+
"min_upload_seconds": 3.0,
5+
"min_motion_frames": 7,
6+
"camera_warmup_time": 3.0,
7+
"delta_thresh": 5,
8+
"resolution": [400, 300],
9+
"fps": 16,
10+
"min_area": 3500
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
# -*- coding: utf-8 -*-
2+
3+
import cv2
4+
import json
5+
import time
6+
import imutils
7+
import argparse
8+
import datetime
9+
import warnings
10+
import uuid
11+
12+
from requests import Session
13+
from picamera import PiCamera
14+
from picamera.array import PiRGBArray
15+
16+
17+
# 参数解析
18+
ap = argparse.ArgumentParser()
19+
ap.add_argument("-c", "--conf", required=True, help="path to the JSON configuration file")
20+
ap.add_argument('-s', "--show", required=True, help="is show video")
21+
args = vars(ap.parse_args())
22+
23+
# 过滤警告,加载配置文件
24+
warnings.filterwarnings("ignore")
25+
conf = json.load(open(args["conf"]))
26+
27+
# 初始化requests session
28+
s_request = Session()
29+
30+
# 初始化摄像头并且获取一个指向原始数据的引用
31+
camera = PiCamera()
32+
camera.resolution = tuple(conf["resolution"])
33+
camera.framerate = conf["fps"]
34+
rawCapture = PiRGBArray(camera, size=tuple(conf["resolution"]))
35+
36+
# 等待摄像头启动初始化平均值
37+
print "[INFO] warming up..."
38+
time.sleep(conf["camera_warmup_time"])
39+
avg = None
40+
lastUploaded = datetime.datetime.now()
41+
motionCounter = 0
42+
43+
# 从摄像头捕获数据
44+
for f in camera.capture_continuous(rawCapture, format="bgr", use_video_port=True):
45+
# 抓取原始NumPy数组来表示图像并且初始化
46+
frame = f.array
47+
# 时间戳以及occupied/unoccupied文本
48+
timestamp = datetime.datetime.now()
49+
# 无人入侵
50+
text = "Unoccupied"
51+
52+
# 调整图像尺寸
53+
frame = imutils.resize(frame, width=320)
54+
# bgr 图像转 灰度图像
55+
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
56+
# 0 是指根据窗口大小(21, 21)来计算高斯函数标准差
57+
gray = cv2.GaussianBlur(gray, (21, 21), 0)
58+
59+
# 初始化平均值
60+
if avg is None:
61+
print "[INFO] starting background model..."
62+
# 浮点数转化
63+
avg = gray.copy().astype("float")
64+
# 依据尺寸来截取图像
65+
rawCapture.truncate(0)
66+
continue
67+
68+
# 累计当前帧,计算加权平均值
69+
cv2.accumulateWeighted(gray, avg, 0.5)
70+
frameDelta = cv2.absdiff(gray, cv2.convertScaleAbs(avg))
71+
72+
# 计算阈值,膨胀阈值图像
73+
thresh = cv2.threshold(frameDelta, conf["delta_thresh"], 255, cv2.THRESH_BINARY)[1]
74+
thresh = cv2.dilate(thresh, None, iterations=2)
75+
# 发现入侵图像轮廊
76+
(_, cnts, _) = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
77+
78+
# 遍历轮廊线
79+
for c in cnts:
80+
# 如果轮廊小于min_area 则忽略他
81+
if cv2.contourArea(c) < conf["min_area"]:
82+
continue
83+
# 计算轮廊线,
84+
(x, y, w, h) = cv2.boundingRect(c)
85+
# 画出轮廊矩阵
86+
cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
87+
# 更新入侵状态
88+
text = "Occupied"
89+
90+
# 在当前帧数上标记文本和时间戳
91+
ts = timestamp.strftime("%Y %I:%M:%S")
92+
cv2.putText(
93+
frame,
94+
"Room Status: {}".format(text),
95+
(10, 20), cv2.FONT_HERSHEY_SIMPLEX,
96+
0.5, (0, 0, 255), 2)
97+
cv2.putText(
98+
frame,
99+
ts, (10, frame.shape[0] - 10),
100+
cv2.FONT_HERSHEY_SIMPLEX,
101+
0.35, (0, 0, 255), 1
102+
)
103+
104+
# 检查房间是否被入侵
105+
if text == "Occupied":
106+
# 判断上一次上传数据图像时间是否达到上传间隔
107+
if (timestamp - lastUploaded).seconds >= conf["min_upload_seconds"]:
108+
# 增加计数器
109+
motionCounter += 1
110+
111+
# 判断连续运动时间是否已经足够多
112+
if motionCounter >= conf["min_motion_frames"]:
113+
# 写入零时图片
114+
file_uuid = uuid.uuid1()
115+
if conf.get('tmp_image_path'):
116+
tmp_path = os.path.join(
117+
conf.get('tmp_image_path'),
118+
'{file_uuid}.jpg'.format(file_uuid=file_uuid)
119+
)
120+
else:
121+
tmp_path = os.path.join(
122+
'./result',
123+
'{file_uuid}.jpg'.format(file_uuid=file_uuid)
124+
)
125+
cv2.imwrite(tmp_path, frame)
126+
# 将入侵图像上传到服务器
127+
try:
128+
resp = s_request.request(
129+
'POST', conf['web_hook'],
130+
files={'file': open(tmp_path, 'r')}
131+
)
132+
if resp.status_code == 201:
133+
print u'上传图片成功'
134+
except Exception:
135+
print u'上传图片失败'
136+
motionCounter = 0
137+
lastUploaded = timestamp
138+
# 房间没有被入侵
139+
else:
140+
motionCounter = 0
141+
# 查看是否将视频显示在桌面
142+
if args['show'] == 'True':
143+
# display the security feed
144+
cv2.imshow("Security Feed", frame)
145+
key = cv2.waitKey(1) & 0xFF
146+
# 如果用户键盘输入q则退出程序
147+
if key == ord("q"):
148+
break
149+
# 清理数据
150+
rawCapture.truncate(0)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
backports.shutil-get-terminal-size==1.0.0
2+
numpy==1.13.3

0 commit comments

Comments
 (0)