紧接上篇文章(《Galileo开发板+微信公众平台实现简单的物联网家庭监控》( http://blog.jcix.top/2015-11-27/galileo_wechat/ ) ),
以下功能做了改进:
* 实现了Galileo开发板上用USB摄像头+python版opencv监控并通过微信公众平台进行异常报警的功能。
* 通过connman实现了wifi网络的自动连接和随时修改功能。
* 通过post到服务器,实现了微信控制led灯亮、灭或者光控的功能。
视频监控功能的实现
(完整代码在github: https://github.com/zhangjaycee/galileo_pys/blob/master/cam_wechat.py )
1.图像采集
galileo支持python的opencv库,这给简单的图像处理提供了极大的便利。
图像采集:
cap = cv2.VideoCapture(0)#打开摄像头
cap.set(3,320)
cap.set(4,240)
while True:
ret, frame = cap.read()
2.图像处理
我们要做键控,所以可以记录第一帧,然后通过帧间差别进行报警。
cap = cv2.VideoCapture(0)
<!--more-->
cap.set(3,320)
cap.set(4,240)
avg = None
lastUploaded = datetime.datetime.now()
motionCounter = 0
normal_count = 0
start_flag = 0
time.sleep(10)
while True:
timestamp = datetime.datetime.now()
text = "ok"
ret, frame = cap.read()
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
if avg is None:
print "starting backfground model..."
avg = gray.copy().astype("float")
continue
cv2.accumulateWeighted(gray, avg, 0.5)
frameDelta = cv2.absdiff(gray, cv2.convertScaleAbs(avg))
# 对变化图像进行阀值化, 膨胀阀值图像来填补
# 孔洞, 在阀值图像上找到轮廓线
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)
# 遍历轮廓线
for c in cnts:
# if the contour is too small, ignore it
if cv2.contourArea(c) < conf["min_area"]:
continue
# 计算轮廓线的外框, 在当前帧上画出外框,
# 并且更新文本
(x, y, w, h) = cv2.boundingRect(c)
cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
text = "Attention!"
#print "[", text, "]"
# 在当前帧上标记文本和时间戳
ts = timestamp.strftime("%A %d %B %Y %I:%M:%S%p")
#print ts
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)
normal_count += 1
3.报警机制和图像上传
if text == "Attention!":
# 判断上传时间间隔是否已经达到
if (timestamp - lastUploaded).seconds >= conf["min_upload_seconds"]:
# 运动检测计数器递增
motionCounter += 1
# 判断包含连续运动的帧数是否已经
# 足够多
if motionCounter >= conf["min_motion_frames"]:
# 判断Dropbox是否被使用
if conf["use_wechat"] and start_flag == 1:
cv2.imwrite('/home/root/galileo_dangerous.jpg',frame)
os.system("scp /home/root/galileo_dangerous.jpg root@xdjc.date:/root/wechat_galileo/")
request = urllib2.Request(
url = r'http://galileo.xdjc.date/?signature=1ce507b0abfa4d231b538988c01127c9e03a02ad×tamp=1408377801&nonce=959202980',
headers = {'Content-Type' : 'text/xml'},
data = data)
print opener.open(request).read()
# 更新最近一次上传的时间戳并且重置运动
# 计数器
print "[ Dangerous! ]"
lastUploaded = timestamp
motionCounter = 0
#否则, 该房间没有“被占领”
else:
motionCounter = 0
# 判断安保视频是否需要显示在屏幕上
if conf["show_video"]:
# 显示安视频
cv2.imshow("Security Feed", frame)
key = cv2.waitKey(1) & 0xFF
# 如果q被按下,跳出循环
if key == ord("q"):
break
参考:
《用树莓派 + Python + OpenCV 实现家庭监控和移动目标探测(下》( http://python.jobbole.com/81645/ )
connman wifi功能的详细配置
这个过程我写在了下边这篇博客里:
《Intel Galileo开发版PCI-e无线网卡wifi配置》( http://blog.jcix.top/2015-12-10/galileo_connman/ )
实现led灯的亮灭或者光控功能
这个很简单,只要一个post,在服务器端进行相应控制即可。
代码
#! /usr/bin/env python
import sys
import urllib2
import time
import pyupm_grove as grove
led = grove.GroveLed(3)
light = grove.GroveLight(2)
print "[start....]"
time.sleep(20)
while True:
light_value = light.raw_value()
data = '''<xml>
<light><![CDATA[%s]]></light>
</xml>''' % light_value
cookies = urllib2.HTTPCookieProcessor()
opener = urllib2.build_opener(cookies)
request = urllib2.Request(
url = r'http://galileo.xdjc.date/?signature=1ce507b0abfa4d231b538988c01127c9e03a02ad×tamp=1408377801&nonce=959202980',
headers = {'Content-Type' : 'text/xml'},
data = data)
state = int(opener.open(request).read())
if state == 2:
if light_value <= 300:
led.on()
else:
led.off()
elif state == 0:
led.off()
elif state == 1:
led.on()
time.sleep(1)
最终功能
只要Intel Galileo开发板自动连接了家中的WiFi,就开始和我们所搭建的云服务器进行通信,进而通过微信公众号和主人进行双向通信,实现智能家庭监控的一系列功能:
1. 在微信中回复“温度”,查询当前室温。
2. 回复“开灯”,自动打开Galileo开发板所控制的灯(本次设计采用LED代替演示);回复关闭,则自动关闭;回复“光控”,则开发板根据光线传感器采集的室内亮度信息自动开或者关灯。
3. 回复“状态”,返回一张实时的家中照片。
4. 回复“打开监控”,开发板通过所连接的USB摄像头开始进行视频监控,若检测到有异常情况发生,自动通过微信向主人报警,并返回一张标记有异常目标和具体时间的监控照片;回复“关闭监控”,会暂停监控和报警。