MobileNet-SSD + imagezmq部署树莓派搭建监控系统

如果家中有多个树莓派在吃灰,可以拿出来做个简单的家庭监控系统,比如监控门前的车辆,鱼缸里的鱼儿,养的宠物等。

1.MobileNet-SSD

MobileNet-SSD是MobileNet的改版,mobilenet论文地址:《MobileNets: Efficient Convolutional Neural Networks for Mobile Vision Applications
MobileNet-SSD项目地址:https://github.com/chuanqi305/MobileNet-SSD
这里主要用到了预训练模型deploy,也可以自己重新训练模型。

2.IMAGEZMQ

imagezmq是用于分布式图像处理网络的易于使用的图像传输机制。imagezmq是基于ZMQ开发的,我们先了解一下ZMQ。

2.1 ZMQ

ZMQ(ØMQ、ZeroMQ)看起来像是一套嵌入式的网络链接库,但工作起来更像是一个并发式的框架。它提供的套接字可以在多种协议中传输消息,如线程间、进程间、TCP、广播等。
请求-回复(REQ / REP):
拿Hello World举例,我们会创建一个客户端和一个服务端,客户端发送Hello给服务端,服务端返回World。
在这里插入图片描述
发布-订阅(PUB / SUB):
这种消息模式是单向数据分发,服务端将更新事件发送给一组客户端。
在这里插入图片描述
分布式处理:

  • 任务分发器会生成大量可以并行计算的任务
  • 有一组worker会处理这些任务
  • 结果收集器会在末端接收所有worker的处理结果,进行汇总
    在这里插入图片描述
2.2 imagezmq

imagezmq是一组Python类,它们使用PyZMQ消息传递将OpenCV图像从一台计算机传输到另一台计算机。项目地址:https://github.com/jeffbass/imagezmq

3.部署代码

控制流程图:
在这里插入图片描述
这里的使用两个树莓派,一个是pi-3,另一个是pi-4。服务端用win10电脑。
在这里插入图片描述

3.1 服务端部署

在win10电脑上,python环境下安装必要的包:


# 运行命令,--montageW=2为横向两个屏幕(两列),--montageH=1竖向一行,可根据自己树莓派数量自行调整
# python server.py --prototxt MobileNetSSD_deploy.prototxt --model MobileNetSSD_deploy.caffemodel --montageW 2 --montageH 1

from imutils import build_montages
from datetime import datetime
import numpy as np
import imagezmq
import argparse
import imutils
import cv2

# 构造参数
ap = argparse.ArgumentParser()
ap.add_argument("-p", "--prototxt", required=True,
	help="Caffe MobileNetSSD网络路径")
ap.add_argument("-m", "--model", required=True,
	help="Caffe MobileNetSSD 预训练模型路径")
ap.add_argument("-c", "--confidence", type=float, default=0.2,
	help="置信度阈值,过虑低于此值的检测目标")
ap.add_argument("-mW", "--montageW", required=True, type=int,
	help="蒙太奇图像宽度")
ap.add_argument("-mH", "--montageH", required=True, type=int,
	help="蒙太奇图像高度")
args = vars(ap.parse_args())

# 初始化 ImageHub对象,接受来自每个Raspberry Pi的连接,
# 它实质上是用socket和ZMQ来接收帧(并发送回确认信息)
imageHub = imagezmq.ImageHub()

# MobileNet-SSD的分类标签,一共21类(算上背景)
CLASSES = ["background", "aeroplane", "bicycle", "bird", "boat",
	"bottle", "bus", "car", "cat", "chair", "cow", "diningtable",
	"dog", "horse", "motorbike", "person", "pottedplant", "sheep",
	"sofa", "train", "tvmonitor"]

# 加载模型
print("模型加载中...")
net = cv2.dnn.readNetFromCaffe(args["prototxt"], args["model"])


# 设置想要监控的类别,根据自己的需求添加,我这里只监控一类:人
CONSIDER = set(["person"])
objCount = {obj: 0 for obj in CONSIDER}
frameDict = {}


# 初始化一个空字典,存储相关信息
lastActive = {}
lastActiveCheck = datetime.now()

# 存储设备数量等信息
ESTIMATED_NUM_PIS = 4
ACTIVE_CHECK_PERIOD = 10
ACTIVE_CHECK_SECONDS = ESTIMATED_NUM_PIS * ACTIVE_CHECK_PERIOD

#将所有设备传过来的视频帧,做成类似九宫格的监控画面
mW = args["montageW"]
mH = args["montageH"]
print("正在监控: {}...".format(", ".join(obj for obj in
	CONSIDER)))

# 处理所有图像帧
while True:

	#接受树莓派名字和其传过来的图像,并回复消息
	(rpiName, frame) = imageHub.recv_image()
	imageHub.send_reply(b'OK')

	if rpiName not in lastActive.keys():
		print("正在从{}接收数据...".format(rpiName))

	# 记录检测时间
	lastActive[rpiName] = datetime.now()

	# 处理图像大小,构造blob
	frame = imutils.resize(frame, width=400)
	(h, w) = frame.shape[:2]
	blob = cv2.dnn.blobFromImage(cv2.resize(frame, (300, 300)),
		0.007843, (300, 300), 127.5)

	# 检测和预测
	net.setInput(blob)
	detections = net.forward()

	# 目标数量
	objCount = {obj: 0 for obj in CONSIDER}

	# 循环检测
	for i in np.arange(0, detections.shape[2]):

		#提取相关概率预测
		confidence = detections[0, 0, i, 2]

		# 过虑
		if confidence > args["confidence"]:
			# 类别标签索引
			idx = int(detections[0, 0, i, 1])

			# 计算数量
			if CLASSES[idx] in CONSIDER:
				# increment the count of the particular object
				# detected in the frame
				objCount[CLASSES[idx]] += 1

				# 计算目标的bounding box 坐标
				box = detections[0, 0, i, 3:7] * np.array([w, h, w, h])
				(startX, startY, endX, endY) = box.astype("int")

				# 绘制图框
				cv2.rectangle(frame, (startX, startY), (endX, endY),
					(255, 0, 0), 2)

	# 显示在帧上
	cv2.putText(frame, rpiName, (10, 25),
		cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2)

	# 目标数量显示在帧上
	label = ", ".join("{}: {}".format(obj, count) for (obj, count) in
		objCount.items())
	cv2.putText(frame, label, (10, h - 20),
		cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255,0), 2)

	# 更新帧
	frameDict[rpiName] = frame

	# 用在帧字典中的图像构建一个蒙太奇图像
	montages = build_montages(frameDict.values(), (w, h), (mW, mH))

	# 显示
	for (i, montage) in enumerate(montages):
		cv2.imshow("Home monitor ({})".format(i), montage)

	# 按任意键退出
	key = cv2.waitKey(1) & 0xFF

	# 当前时间减去上次活动设备检查的时间
	# 大于设置的阈值,然后进行检查
	if (datetime.now() - lastActiveCheck).seconds > ACTIVE_CHECK_SECONDS:
		# 遍历所有先前活动的设备
		for (rpiName, ts) in list(lastActive.items()):
			# 从最后一个活动帧中删除Pi
			# 字典(如果该设备最近未激活)
			if (datetime.now() - ts).seconds > ACTIVE_CHECK_SECONDS:
				print("最后连接到{}".format(rpiName))
				lastActive.pop(rpiName)
				frameDict.pop(rpiName)

		# 将上次活动检查时间设置为当前时间
		lastActiveCheck = datetime.now()

	# 退出
	if key == ord("q"):
		break
# 清理
cv2.destroyAllWindows()
3.2 客户端(树莓派)部署

首先给树莓派创建个虚拟环境,可参考另一篇:https://blog.youkuaiyun.com/y459541195/article/details/102055866
安装必要的包:

pip install opencv-contrib-python
pip install zmq
pip install imutils

在这里插入图片描述
记得下载imagezmq:

git clone https://github.com/jeffbass/imagezmq.git

imagezmq.py文件放到同意文件夹下面。

主要代码如下:

# 执行命令,SERVER_IP为服务端ip,替换为自己的
# python client.py --server-ip 192.168.1.4

from imutils.video import VideoStream
import imagezmq
import argparse
import socket
import time

# 构造参数
ap = argparse.ArgumentParser()
ap.add_argument("-s", "--server-ip", required=True,
	help="客户端连接服务器的IP地址")
args = vars(ap.parse_args())

# 初始化服务器通讯地址
sender = imagezmq.ImageSender(connect_to="tcp://{}:5555".format(
	args["server_ip"]))

# 获取主机名,打开相机
rpiName = socket.gethostname()
vs = VideoStream(usePiCamera=True).start()
#vs = VideoStream(src=0).start()
time.sleep(2.0)
while True:
	# 读取视频发送给服务器
	frame = vs.read()
	sender.send_image(rpiName, frame)

4.测试

文件结构:
在这里插入图片描述
先开启服务端:

python server.py --prototxt MobileNetSSD_deploy.prototxt --model MobileNetSSD_deploy.caffemodel --montageW 2 --montageH 1

分别在树莓派pi-3和pi-4上开启客户端:

python client.py --server-ip 192.168.1.4

上面的192.168.1.4替换为自己的ip。

效果如下:
在这里插入图片描述
在这里插入图片描述
完整项目代码地址:https://download.youkuaiyun.com/download/y459541195/11995013
有兴趣的也可以做个小程序,从小程序里远程查看监控。

Reference:
http://zguide.zeromq.org/page:all
https://github.com/jeffbass/imagezmq
https://www.pyimagesearch.com/2017/09/18/real-time-object-detection-with-deep-learning-and-opencv/
https://arxiv.org/abs/1704.04861
https://github.com/chuanqi305/MobileNet-SSD

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

圆滚熊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值