【英特尔杯】人群距离检测

使用单目摄像头,通过相似三角形原理进行测距,部分代码如下,使用yolov3做人体识别。可以完成对在场所有人是否小于预设的社交距离的判断以及是否佩戴口罩

口罩佩戴的判断使用的是百度飞桨的paddlehub模型,具体可以在官网查到相关资料
部分代码如下


from TheLazyCoder import social_distancing_config as config
from TheLazyCoder.detection import detect_people
from scipy.spatial import distance as dist
import numpy as np
import argparse
import imutils
import cv2
import os
import paddlehub as hub
# construct the argument parse and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--input", type=str, default="",
	help="path to (optional) input video file")
ap.add_argument("-o", "--output", type=str, default="",
	help="path to (optional) output video file")
ap.add_argument("-d", "--display", type=int, default=1,
	help="whether or not output frame should be displayed")
args = vars(ap.parse_args())
#导入口罩模型
mask_detector = hub.Module(name="pyramidbox_lite_server_mask")
#载入yolo的模型和标签
labelsPath = os.path.sep.join([config.MODEL_PATH, "coco.names"])
LABELS = open(labelsPath).read().strip().split("\n")

# 导入权重
weightsPath = os.path.sep.join([config.MODEL_PATH, "yolov3.weights"])
configPath = os.path.sep.join([config.MODEL_PATH, "yolov3.cfg"])

# 加载在coco训练集上的对象检测器
print("[INFO] loading YOLO from disk...")
net = cv2.dnn.readNetFromDarknet(configPath, weightsPath)

# check if we are going to use GPU
if config.USE_GPU:
	# set CUDA as the preferable backend and target
	print("[INFO] setting preferable backend and target to CUDA...")
	net.setPreferableBackend(cv2.dnn.DNN_BACKEND_CUDA)
	net.setPreferableTarget(cv2.dnn.DNN_TARGET_CUDA)

#  仅确定我们需要YOLO提供的*输出*图层名称
ln = net.getLayerNames()
ln = [ln[i[0] - 1] for i in net.getUnconnectedOutLayers()]

# 初始化视频流和指向输出视频文件的指针
print("[INFO] accessing video stream...")
vs = cv2.VideoCapture(args["input"] if args["input"] else 0)
writer = None

# 循环播放视频帧
while True:
	# read the next frame from the file
	(grabbed, frame) = vs.read()
	cv2.imwrite("1.jpg",frame)
	result = mask_detector.face_detection(images=[cv2.imread('1.jpg')])
	print(result[0]['data'][0]['label'])
	#如果没框架了,说明视频已经到末尾
	if not grabbed:
		break

	# 调整框架大小,仅检测画面中的人
	frame = imutils.resize(frame, width=700)
	results = detect_people(frame, net, ln,
		personIdx=LABELS.index("person"))

	# 初始化违反社交距离的最小距离
	violate = set()

	#确保画面至少两人,以计算所有成对对象间的距离
	if len(results) >= 2:
		# 从结果中提取所有质心并计算所有质心对之间的欧氏距离
		centroids = np.array([r[2] for r in results])
		D = dist.cdist(centroids, centroids, metric="euclidean")

		#距离矩阵上三角的计算
		for i in range(0, D.shape[0]):
			for j in range(i + 1, D.shape[1]):
			#检查任意两个质心间的距离是否小于配置的像素点
				if D[i, j] < config.MIN_DISTANCE:
					# 更新质心对
					violate.add(i)
					violate.add(j)

	# 循环查看结果
	for (i, (prob, bbox, centroid)) in enumerate(results):
		# 画框
		(startX, startY, endX, endY) = bbox
		(cX, cY) = centroid
		color = (0, 255, 0)

		# 如果索引对象存在于冲突集,则更新边框颜色
		if i in violate:
			color = (0, 0, 255)

		# 人周围画框,质心画圆圈
		cv2.rectangle(frame, (startX, startY), (endX, endY), color, 2)
		cv2.circle(frame, (cX, cY), 5, color, 1)

	# 显示违反社交距离的人员总数
	text = "Social Distancing Violations: {}".format(len(violate))
	cv2.putText(frame, text, (10, frame.shape[0] - 25),
		cv2.FONT_HERSHEY_SIMPLEX, 0.85, (0, 0, 255), 3)

	# 检查输出帧是否显示到屏幕
	if args["display"] > 0:
		# show the output frame
		cv2.imshow("Frame", frame)
		key = cv2.waitKey(1) & 0xFF

		# if the `q` key was pressed, break from the loop
		if key == ord("q"):
			break

	# 视频初始化
	if args["output"] != "" and writer is None:
		# initialize our video writer
		fourcc = cv2.VideoWriter_fourcc(*"MJPG")
		writer = cv2.VideoWriter(args["output"], fourcc, 25,
			(frame.shape[1], frame.shape[0]), True)

	if writer is not None:
		writer.write(frame)

MODEL_PATH = "yolo-coco"

# initialize minimum probability to filter weak detections along with
# the threshold when applying non-maxima suppression
#初始化最小概率以过滤弱检测以及
#应用非最大值抑制时的阈值
MIN_CONF = 0.3
NMS_THRESH = 0.3

# boolean indicating if NVIDIA CUDA GPU should be used
USE_GPU = False

# define the minimum safe distance (in pixels) that two people can be
# from each other
MIN_DISTANCE = 195
from TheLazyCoder import social_distancing_config as config
from TheLazyCoder.detection import detect_people
from scipy.spatial import distance as dist
import numpy as np
import argparse
import imutils
import cv2
import os
import paddlehub as hub
import requests
import time
import base64
def peoplenum(pics,nums):
	login_url = "https://xiyoulvma.xyz/weixin/flow"  # 请求地址
	url = login_url  # 拼接地址
	# 参数
	body1 = {'pic': pics,
		 'num': nums,

			 }
	# 发送请求
	r = requests.post(url=url, json=body1)
	print(r)
def wechat(num):  #向微信发送东西
	url = ' https://api.bemfa.com/api/wechat/v1/weget.php'
	data = {
		'uid': 'dde0bd25d9e142acaf7a126aadcf906a',
		'type': '1',
		'device': '邮电大学0号车',
		'msg': '此处有违法社交距离及未佩戴口罩情况发生,人数为:'+ str(num)
	}
	response = requests.get(url, data)
	print(response.text)
def live_get():
	login_url = "https://open.ys7.com/api/lapp/token/get"  # 请求地址
	url = login_url  # 拼接地址
	# 参数
	body1 = {'appKey': '394a0e460c504daab84d71079b59adcc',
			 'appSecret': '14f3dcbba15c3fccc2a218b55cc420d2',

			 }
	# 发送请求
	r = requests.post(url=url, params=body1).json()
	# 输出返回
	live_url = "https://open.ys7.com/api/lapp/v2/live/address/get"  # 请求地址
	body2 = {'accessToken': r['data']['accessToken'],
			 'deviceSerial': 'J22672477',
			 'protocol': 2,
			 }
	r = requests.post(url=live_url, params=body2).json()
	# 输出返回
	return r['data']['url']
# construct the argument parse and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--input", type=str, default="",
	help="path to (optional) input video file")
ap.add_argument("-o", "--output", type=str, default="",
	help="path to (optional) output video file")
ap.add_argument("-d", "--display", type=int, default=1,
	help="whether or not output frame should be displayed")
args = vars(ap.parse_args())
#导入口罩模型
mask_detector = hub.Module(name="pyramidbox_lite_server_mask")
#载入yolo的模型和标签
labelsPath = os.path.sep.join([config.MODEL_PATH, "coco.names"])
LABELS = open(labelsPath).read().strip().split("\n")

# 导入权重
weightsPath = os.path.sep.join([config.MODEL_PATH, "yolov3.weights"])
configPath = os.path.sep.join([config.MODEL_PATH, "yolov3.cfg"])

# 加载在coco训练集上的对象检测器
print("[INFO] loading YOLO from disk...")
net = cv2.dnn.readNetFromDarknet(configPath, weightsPath)

# check if we are going to use GPU
if config.USE_GPU:
	# set CUDA as the preferable backend and target
	print("[INFO] setting preferable backend and target to CUDA...")
	net.setPreferableBackend(cv2.dnn.DNN_BACKEND_CUDA)
	net.setPreferableTarget(cv2.dnn.DNN_TARGET_CUDA)

#  仅确定我们需要YOLO提供的*输出*图层名称
ln = net.getLayerNames()
ln = [ln[i- 1] for i in net.getUnconnectedOutLayers()]

# 初始化视频流和指向输出视频文件的指针
#vs = cv2.VideoCapture(live_get())
vs = cv2.VideoCapture(0)
writer = None
tot = 1
# 循环播放视频帧
while True:
	flag=1
	# read the next frame from the file
	(grabbed, frame) = vs.read()
	if grabbed == True:
		if tot>0:
			cv2.imwrite("1.jpg", frame)
			img = cv2.imread("1.jpg")
			with open("/home/bj/socialdistance/1.jpg", "rb") as f:
				pic1 = f.read()
				pic1=str(base64.b64encode(pic1))
			#如果没框架了,说明视频已经到末尾
			if not grabbed:
					break

			# 调整框架大小,仅检测画面中的人
			frame = imutils.resize(frame, width=700)
			results = detect_people(frame, net, ln,
				personIdx=LABELS.index("person"))

			# 初始化违反社交距离的最小距离
			violate = set()
			if(len(results)>0):
				try:
					resultt = mask_detector.face_detection(images=[img])
				except:
					pass
			#确保画面至少两人,以计算所有成对对象间的距离

			if len(results) >= 2:
				# 从结果中提取所有质心并计算所有质心对之间的欧氏距离
				centroids = np.array([r[2] for r in results])
				D = dist.cdist(centroids, centroids, metric="euclidean")

				#距离矩阵上三角的计算
				for i in range(0, D.shape[0]):
					for j in range(i + 1, D.shape[1]):
					#检查任意两个质心间的距离是否小于配置的像素点
						if D[i, j] < config.MIN_DISTANCE:
							# 更新质心对
							violate.add(i)
							violate.add(j)
			# 循环查看结果
			for (i, (prob, bbox, centroid)) in enumerate(results):
				# 画框
				(startX, startY, endX, endY) = bbox
				(cX, cY) = centroid
				color = (0, 255, 0)

				# 如果索引对象存在于冲突集,则更新边框颜色
				if i in violate:
					color = (0, 0, 255)

				# 人周围画框,质心画圆圈
				cv2.rectangle(frame, (startX, startY), (endX, endY), color, 2)
				cv2.circle(frame, (cX, cY), 5, color, 1)
				if (len(resultt[0]['data']) != 0):
					for i in range(len(resultt[0]['data'])):
						if resultt[0]['data'][i]['label'] == 'NO MASK':
							cv2.putText(frame, resultt[0]['data'][i]['label'],
										(resultt[0]['data'][i]['left'] - 20, resultt[0]['data'][i]['top'] - 25),
										cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2)
						else:
							cv2.putText(frame, resultt[0]['data'][i]['label'],
										(resultt[0]['data'][i]['left'] - 20, resultt[0]['data'][i]['top'] - 25),
										cv2.FONT_HERSHEY_SIMPLEX, 0.5,
										(0, 255, 0), 2)
						cv2.rectangle(frame, (resultt[0]['data'][i]['left'] - 20, resultt[0]['data'][i]['top'] - 20),
									  (resultt[0]['data'][i]['right'] + 20, resultt[0]['data'][i]['bottom'] + 20),
									  (200, 200, 40), 2)
			# 显示违反社交距离的人员总数
			text = "Social Distancing Violations: {}".format(len(violate))
			cv2.putText(frame, text, (10, frame.shape[0] - 25),
				cv2.FONT_HERSHEY_SIMPLEX, 0.85, (0, 0, 255), 3)
			if(len(violate)>=2 and flag == 1):
				flag = 0
				wechat(len(violate))
				peoplenum(pic1, len(results))
			# 检查输出帧是否显示到屏幕
			if args["display"] > 0:
				# show the output frame
				cv2.imshow("Frame", frame)
				key = cv2.waitKey(1) & 0xFF


		else:
			time.sleep(0.03)
			frame = imutils.resize(frame, width=700)
			cv2.imshow("Frame", frame)
			flag = 1
			cv2.waitKey(1)
		tot+=1
		if tot >= 204:
			tot=0
	else:
		vs = cv2.VideoCapture(0)
		(grabbed, frame) = vs.read()
vs.release()
cv2.destroyAllWindows()

在这里插入代码片
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值