首页 > 其他分享 >项目实践 | 行人跟踪与摔倒检测报警

项目实践 | 行人跟踪与摔倒检测报警

时间:2023-04-22 10:33:02浏览次数:41  
标签:pose track cv2 frame 报警 摔倒 卷积 inp 行人

小白学视觉 7月7日


1.简介

本项目的目的是为了给大家提供跟多的实战思路,抛砖引玉为大家提供一个案例,也希望读者可以根据该方法实现更多的思想与想法,也希望读者可以改进该项目种提到的方法,比如改进其中的行人检测器、跟踪方法、行为识别算法等等。

本项目主要检测识别的行为有7类:Standing, Walking, Sitting, Lying Down, Stand up, Sit down, Fall Down

2.项目方法简介

本文涉及的方法与算法包括:YOLO V3 Tiny、Deepsort、ST-GCN方法,其中YOLO V3 Tiny用于行人检测、DeepSort用于跟踪、而ST-GCN则是用于行为检测。

这里由于YOLO与DeepSort大家都已经比较了解,因此这里只简单说明一下ST-GCN 的流程,这里ST-GCN 的方法结构图如下:

项目实践 | 行人跟踪与摔倒检测报警_ide

给出一个动作视频的骨架序列信息,首先构造出表示该骨架序列信息的图结构,ST-GCN的输入就是图节点上的关节坐标向量,然后是一系列时空图卷积操作来提取高层的特征,最后用SofMax分类器得到对应的动作分类。整个过程实现了端到端的训练。

GCN 帮助我们学习了到空间中相邻关节的局部特征。在此基础上,我们需要学习时间中关节变化的局部特征。如何为 Graph 叠加时序特征,是图卷积网络面临的问题之一。这方面的研究主要有两个思路:时间卷积(TCN)和序列模型(LSTM)。

ST-GCN 使用的是 TCN,由于形状固定,可以使用传统的卷积层完成时间卷积操作。为了便于理解,可以类比图像的卷积操作。st-gcn 的 feature map 最后三个维度的形状为(C,V,T),与图像 feature map 的形状(C,W,H)相对应。

  • 图像的通道数C对应关节的特征数C。
  • 图像的宽W对应关键帧数V。
  • 图像的高H对应关节数T。

在图像卷积中,卷积核的大小为『w』×『1』,则每次完成w行像素,1列像素的卷积。『stride』为s,则每次移动s像素,完成1行后进行下1行像素的卷积。

在时间卷积中,卷积核的大小为『temporal_kernel_size』×『1』,则每次完成1个节点,temporal_kernel_size 个关键帧的卷积。『stride』为1,则每次移动1帧,完成1个节点后进行下1个节点的卷积。

训练如下:

项目实践 | 行人跟踪与摔倒检测报警_ide_02

输入的数据首先进行batch normalization,然后在经过9个ST-GCN单元,接着是一个global pooling得到每个序列的256维特征向量,最后用SoftMax函数进行分类,得到最后的标签。

每一个ST-GCN采用Resnet的结构,前三层的输出有64个通道,中间三层有128个通道,最后三层有256个通道,在每次经过ST-CGN结构后,以0.5的概率随机将特征dropout,第4和第7个时域卷积层的strides设置为2。用SGD训练,学习率为0.01,每10个epochs学习率下降0.1。

ST-GCN 最末卷积层的响应可视化结果图如下:

项目实践 | 行人跟踪与摔倒检测报警_ide_03

本文项目主函数代码如下:


import os
import cv2
import time
import torch
import argparse
import numpy as np

from Detection.Utils import ResizePadding
from CameraLoader import CamLoader, CamLoader_Q
from DetectorLoader import TinyYOLOv3_onecls

from PoseEstimateLoader import SPPE_FastPose
from fn import draw_single

from Track.Tracker import Detection, Tracker
from ActionsEstLoader import TSSTG

# source = '../Data/test_video/test7.mp4'
# source = '../Data/falldata/Home/Videos/video (2).avi' # hard detect
source = './output/test3.mp4'
# source = 2
def preproc(image):
"""preprocess function for CameraLoader.
"""
image = resize_fn(image)
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
return image


def kpt2bbox(kpt, ex=20):
"""Get bbox that hold on all of the keypoints (x,y)
kpt: array of shape `(N, 2)`,
ex: (int) expand bounding box,
"""
return np.array((kpt[:, 0].min() - ex, kpt[:, 1].min() - ex,
kpt[:, 0].max() + ex, kpt[:, 1].max() + ex))


if __name__ == '__main__':
par = argparse.ArgumentParser(description='Human Fall Detection Demo.')
par.add_argument('-C', '--camera', default=source, # required=True, # default=2,
help='Source of camera or video file path.')
par.add_argument('--detection_input_size', type=int, default=384,
help='Size of input in detection model in square must be divisible by 32 (int).')
par.add_argument('--pose_input_size', type=str, default='224x160',
help='Size of input in pose model must be divisible by 32 (h, w)')
par.add_argument('--pose_backbone', type=str, default='resnet50', help='Backbone model for SPPE FastPose model.')
par.add_argument('--show_detected', default=False, action='store_true', help='Show all bounding box from detection.')
par.add_argument('--show_skeleton', default=True, action='store_true', help='Show skeleton pose.')
par.add_argument('--save_out', type=str, default='./output/output3.mp4', help='Save display to video file.')
par.add_argument('--device', type=str, default='cuda', help='Device to run model on cpu or cuda.')
args = par.parse_args()

device = args.device

# DETECTION MODEL.
inp_dets = args.detection_input_size
detect_model = TinyYOLOv3_onecls(inp_dets, device=device)

# POSE MODEL.
inp_pose = args.pose_input_size.split('x')
inp_pose = (int(inp_pose[0]), int(inp_pose[1]))
pose_model = SPPE_FastPose(args.pose_backbone, inp_pose[0], inp_pose[1], device=device)

# Tracker.
max_age = 30
tracker = Tracker(max_age=max_age, n_init=3)

# Actions Estimate.
action_model = TSSTG()

resize_fn = ResizePadding(inp_dets, inp_dets)

cam_source = args.camera
if type(cam_source) is str and os.path.isfile(cam_source):
# Use loader thread with Q for video file.
cam = CamLoader_Q(cam_source, queue_size=1000, preprocess=preproc).start()
else:
# Use normal thread loader for webcam.
cam = CamLoader(int(cam_source) if cam_source.isdigit() else cam_source,
preprocess=preproc).start()

# frame_size = cam.frame_size
# scf = torch.min(inp_size / torch.FloatTensor([frame_size]), 1)[0]
outvid = False
if args.save_out != '':
outvid = True
codec = cv2.VideoWriter_fourcc(*'mp4v')
print((inp_dets * 2, inp_dets * 2))
writer = cv2.VideoWriter(args.save_out, codec, 25, (inp_dets * 2, inp_dets * 2))

fps_time = 0
f = 0
while cam.grabbed():
f += 1
frame = cam.getitem()
image = frame.copy()

# Detect humans bbox in the frame with detector model.
detected = detect_model.detect(frame, need_resize=False, expand_bb=10)

# Predict each tracks bbox of current frame from previous frames information with Kalman filter.
tracker.predict()
# Merge two source of predicted bbox together.
for track in tracker.tracks:
det = torch.tensor([track.to_tlbr().tolist() + [0.5, 1.0, 0.0]], dtype=torch.float32)
detected = torch.cat([detected, det], dim=0) if detected is not None else det

detections = [] # List of Detections object for tracking.
if detected is not None:
# detected = non_max_suppression(detected[None, :], 0.45, 0.2)[0]
# Predict skeleton pose of each bboxs.
poses = pose_model.predict(frame, detected[:, 0:4], detected[:, 4])

# Create Detections object.
detections = [Detection(kpt2bbox(ps['keypoints'].numpy()),
np.concatenate((ps['keypoints'].numpy(),
ps['kp_score'].numpy()), axis=1),
ps['kp_score'].mean().numpy()) for ps in poses]

# VISUALIZE.
if args.show_detected:
for bb in detected[:, 0:5]:
frame = cv2.rectangle(frame, (bb[0], bb[1]), (bb[2], bb[3]), (0, 0, 255), 1)

# Update tracks by matching each track information of current and previous frame or
# create a new track if no matched.
tracker.update(detections)

# Predict Actions of each track.
for i, track in enumerate(tracker.tracks):
if not track.is_confirmed():
continue
track_id = track.track_id
bbox = track.to_tlbr().astype(int)
center = track.get_center().astype(int)

action = 'pending..'
clr = (0, 255, 0)
# Use 30 frames time-steps to prediction.
if len(track.keypoints_list) == 30:
pts = np.array(track.keypoints_list, dtype=np.float32)
out = action_model.predict(pts, frame.shape[:2])
action_name = action_model.class_names[out[0].argmax()]
action = '{}: {:.2f}%'.format(action_name, out[0].max() * 100)
if action_name == 'Fall Down':
clr = (255, 0, 0)
elif action_name == 'Lying Down':
clr = (255, 200, 0)

# VISUALIZE.
if track.time_since_update == 0:
if args.show_skeleton:
frame = draw_single(frame, track.keypoints_list[-1])
frame = cv2.rectangle(frame, (bbox[0], bbox[1]), (bbox[2], bbox[3]), (0, 255, 0), 1)
frame = cv2.putText(frame, str(track_id), (center[0], center[1]), cv2.FONT_HERSHEY_COMPLEX, 0.4, (255, 0, 0), 2)
frame = cv2.putText(frame, action, (bbox[0] + 5, bbox[1] + 15), cv2.FONT_HERSHEY_COMPLEX, 0.4, clr, 1)

# Show Frame.
frame = cv2.resize(frame, (0, 0), fx=2., fy=2.)
frame = cv2.putText(frame, '%d, FPS: %f' % (f, 1.0 / (time.time() - fps_time)), (10, 20), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 1)
frame = frame[:, :, ::-1]
fps_time = time.time()

if outvid:
writer.write(frame)

cv2.imshow('frame', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# Clear resource.
cam.stop()
if outvid:
writer.release()
cv2.destroyAllWindows()


参考

[1].https://arxiv.org/abs/1801.07455


https://github.com/yysijie/st-gcn

标签:pose,track,cv2,frame,报警,摔倒,卷积,inp,行人
From: https://blog.51cto.com/oliverHuang/6215063

相关文章

  • 股票量比实时筛选报警
    一.什么是股票的量比量比是短线投资一个参考指标,是衡量相对成交量的一个数值和指标,用于反映股票交易相对于以往的活跃程度;是指在股市开盘以后,平均每一分钟的成交量与过去五个交易日平均每分钟交易量的比。反映股票相对最近5个交易日的交易热度,也表明了主力的资金动向,我们可以根据......
  • 火山引擎 DataLeap 推出全链路智能监控报警平台
     更多技术交流、求职机会,欢迎关注字节跳动数据平台微信公众号,回复【1】进入官方交流群随着大数据开发场景下需要运维管理的任务越来越多,在日常运维中开发者经常会面临以下几个问题:任务多,依赖关系复杂:很难查找到重要任务的所有上游任务并进行监控。如果监控所有任务,又会产生很多无......
  • m基于形态学处理和SVM的视频行人密集度分析matlab仿真
    1.算法描述       行人检测技术已经成为计算机视觉领域的关键研究方向。行人检测的最重要的任务就是对行人目标进行准确定位。行人检测技术有很强的使用价值,可以与多人跟踪、行人重识别等技术结合,应用于汽车无人驾驶系统、智能机器人、智能视频监控、人体行为分析、人流量......
  • 报警监测管理解决方案
    方案简介本系统主要是由智能终端节点,感知传感器,执行控制单元,云服务器,手机APP远程管理,WEB远程管理平台等构成的物联网解决方案,适用于环境监测、畜牧养殖、水产养殖、温室大棚、电力监测等应用领域,可实现无人值守,实时监测,异常报警,现场自动控制,视频监控,远程调控管理及数据分析等功能......
  • PrometheusAlert微信报警模板示例
    配置入口如下: 代码配置:{{$var:=.externalURL}}{{range$k,$v:=.alerts}}{{ifeq$v.status"resolved"}}[PROMETHEUS-恢复信息]({{$v.generatorURL}})>**[{{$v.labels.alertname}}]({{$var}})**><fontcolor="info">开......
  • Grafana 安装启用和钉钉报警
    Grafana钉钉报警的小卡片点击时无法跳转到Grafana的界面在Grafana的配置文件.ini里root_url='xxxx'配置上地址重启即可一、grafana安装与启用我这里使用的docker方式官方文档:https://grafana.com/docs/grafana/latest/installation/docker/1.数据接入、仪表盘配置展示、各指标......
  • Zabbix利用脚本方式实现邮件报警
    一、安装mailx并配置好能够通过第三方发送邮件yum-yinstallmailxvimmail.rc#在末尾添加如下内容(以163邮箱为例):#setforzabbixsetsendcharsets=iso-8859-1,utf-8#发件人[email protected]#smtp服务器地址setsmtp=smtp.163.com#需要登录认证setsmtp-auth=lo......
  • zabbix配置触发器。。。。即设置监控项报警的分界值!!
              {192.168.8.101:system.users.num.last()}>6            报警声音设置    测试触发器报警:   问题来了,触发器提醒运维人员,需要及时处理一般问题!! ......
  • SHELL创建钉钉群接入机器人推送报警信息(text消息类型)
    步骤一:获取自定义机器人Webhook选择需要添加机器人的群聊,然后依次单击群设置 > 智能群助手。在机器人管理页面选择自定义机器人,输入机器人名字并选择要发送消息的群,同时可以为机器人设置机器人头像。 完成必要的安全设置,勾选我已阅读并同意《自定义机器人服务......
  • Zabbix监控使用ping判断主机是否存活并发邮件报警
    一、在Zabbix服务器安装gcc和fpingyum-yinstallgccwgethttp://www.fping.org/dist/fping-3.10.tar.gztar-xffping-3.10.tar.gzcdfping-3.10./configure--prefix......