视频实时行为检测——基于yolov5+deepsort+slowfast算法

news2025/7/8 2:43:08

文章目录

  • 前言
  • 一、核心功能设计
  • 二、核心实现步骤
    • 1.yolov5实现目标检测
    • 2.deepsort实现目标跟踪
    • 3.slowfast动作识别
  • 三、核心代码解析
    • 1.参数
    • 2.主函数
    • 3.将结果保存成视频
  • 总结


前言

前段时间打算做一个目标行为检测的项目,翻阅了大量资料,也借鉴了不少项目,于是打算通过yolov5实现目标检测,deepsort实现目标跟踪以及slowfast实现动作识别,最终实现端到端的目标行为检测模型。

一、核心功能设计

总的来说,我们需要能够实现实时检测视频中的人物,并且能够识别目标的动作,所以我们拆解需求后,整理核心功能如下所示:

  1. yolov5实现目标检测,确定目标坐标
  2. deepsort实现目标跟踪,持续标注目标坐标
  3. slowfast实现动作识别,并给出置信率
  4. 用框持续框住目标,并将动作类别以及置信度显示在框上

最终效果如下所示:

视频AI行为检测

二、核心实现步骤

1.yolov5实现目标检测

“YOLO”是一种运行速度很快的目标检测AI模型,YOLO将对象检测重新定义为一个回归问题。它将单个卷积神经网络(CNN)应用于整个图像,将图像分成网格,并预测每个网格的类概率和边界框。YOLO非常快,它比“R-CNN”快1000倍,比“Fast R-CNN”快100倍。YOLOv5是YOLO比较新的一个版本。
所以我们把视频分解成多幅图像,并利用yolov5算法进行目标检测并逐帧执行时,可以看到目标跟踪框随目标移动。

效果如下所示:
在这里插入图片描述

2.deepsort实现目标跟踪

但是,如果视频帧中有多个目标,如何知道一帧中的目标和上一帧是同一个对象?这就是目标跟踪的工作,应用多个检测来识别特定目标随时间的变化,实现目标跟踪。
Deepsort是实现目标跟踪的算法,从sort(simple online and realtime tracking)演变而来,其使用卡尔曼滤波器预测所检测对象的运动轨迹,匈牙利算法将它们与新的检测目标相匹配。Deepsort易于使用且运行速度快,成为AI目标检测跟踪之热门算法。

首先来看一下DeepSORT的核心流程:
预测(track)——>观测(detection+数据关联)——>更新

  • 预测:预测下一帧的目标的bbox,即后文中的tracks
  • 观测:对当前帧进行目标检测,仅仅检测出目标并不能与上一帧的目标对应起来,所以还要进行数据关联
  • 更新:预测Bbox和检测Bbox都会有误差,所以进行更新,更新后的跟踪结果通常比单纯预测或者单纯检测的误差小很多。
    在这里插入图片描述

3.slowfast动作识别

我们将视频序列和检测框信息输入行为分类模型,输出每个检测框的行为类别,达到行为检测的目的。
而行为分类模型我们采用的是slowfast算法,其包括一个Slow路径,以低帧速率操作,以捕捉空间语义,以及一个Fast路径,以高帧速率操作,以精细的时间分辨率捕捉运动。快速路径可以通过减少信道容量而变得非常轻量级,同时还可以学习有用的时间信息用于视频识别。
在这里插入图片描述

三、核心代码解析

1.参数

if __name__=="__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument('--input', type=str, default="test/test1.mp4", help='test imgs folder or video or camera')
    parser.add_argument('--output', type=str, default="output/out1.mp4", help='folder to save result imgs, can not use input folder')
    # object detect config
    parser.add_argument('--imsize', type=int, default=640, help='inference size (pixels)')
    parser.add_argument('--conf', type=float, default=0.4, help='object confidence threshold')
    parser.add_argument('--iou', type=float, default=0.4, help='IOU threshold for NMS')
    parser.add_argument('--device', default=0, help='cuda device, i.e. 0 or 0,1,2,3 or cpu')
    parser.add_argument('--classes', default=0,nargs='+', type=int, help='filter by class: --class 0, or --class 0 2 3')
    config = parser.parse_args()
    
    print(config)
    main(config)

从__main__开始分析,设置了输入输出参数以及目标检测的一些参数,包括输入路径、输出路径、尺寸大小、置信度、iou值、以及目标检测的类别,其中0是人。

2.主函数

对输入的config参数解析并使用,模型使用yolov5l6,权重下载到本地

    model = torch.hub.load('ultralytics/yolov5', 'yolov5l6') #加载yolov5模型
    model.conf = config.conf
    model.iou = config.iou
    model.max_det = 200
    model.classes = config.classes
    device = config.device
    imsize = config.imsize
    video_model = slowfast_r50_detection(True).eval().to(device) #加载slowfast_r50_detection模型
    # video_model = slowfast_r50_detection(False).eval().to(device)
    # video_model.load_state_dict(torch.load("SLOWFAST_8x8_R50_DETECTION.pyth")['model_state'])

加载Slowfast、Deepsort模型,使用的Slowfast是在AVA2.2上训练的,通过AvaLabeledVideoFramePaths函数获得id到动作的mapping

    deepsort_tracker = DeepSort("deep_sort/deep_sort/deep/checkpoint/ckpt.t7") #加载DeepSort模型
    ava_labelnames,_ = AvaLabeledVideoFramePaths.read_label_map("selfutils/temp.pbtxt") #加载类别标签
    ava_labelnames_abnormal,_ = AvaLabeledVideoFramePaths.read_label_map("selfutils/ava_action_abnormal.pbtxt") #加载类别标签

    coco_color_map = [[random.randint(0, 255) for _ in range(3)] for _ in range(80)]

读取视频和载入视频

    vide_save_path = config.output
    video=cv2.VideoCapture(config.input) #读取视频
    width,height = int(video.get(3)),int(video.get(4))
    video.release() #释放资源
    outputvideo = cv2.VideoWriter(vide_save_path,cv2.VideoWriter_fourcc(*'mp4v'), 25, (width,height))
    print("processing...")
    
    video = pytorchvideo.data.encoded_video.EncodedVideo.from_path(config.input) # 载入视频

首先对视频进行抽帧处理,通过get_clip()对一秒内的视频进行抽帧,只保留视频图片,将tensor转numpy数组,BGR格式

    a=time.time()
    for i in range(0,math.ceil(video.duration),1): #截视频
        video_clips=video.get_clip(i, i+1-0.04)
        video_clips=video_clips['video']
        if video_clips is None:
            continue
        img_num=video_clips.shape[1]
        imgs=[]
        for j in range(img_num):
            imgs.append(tensor_to_numpy(video_clips[:,j,:,:]))
            # "video": A tensor of the clip's RGB frames with shape: (channel, time, height, width).
        	# 将tensor转为numpy数组,BGR格式

通过yolov5网络进行目标检测

        yolo_preds=model(imgs, size=imsize)
        # 每25帧后插入1帧作为预测图像
        yolo_preds.files=[f"img_{i*25+k}.jpg" for k in range(img_num)]
        print(i,video_clips.shape,img_num)

使用预训练的Deepsort权重,以yolo预测结果作为输入,用Deepsort的结果代替yolo预测的结果,这里Deepsort是用来给相同id的目标分配动作label的。

        deepsort_outputs=[]
        for j in range(len(yolo_preds.pred)):
            temp=deepsort_update(deepsort_tracker,yolo_preds.pred[j].cpu(),yolo_preds.xywh[j][:,0:4].cpu(),yolo_preds.imgs[j])
            if len(temp)==0:
                temp=np.ones((0,8))
            deepsort_outputs.append(temp.astype(np.float32))
        yolo_preds.pred=deepsort_outputs

通过ava_inference_transform()函数对预测输入进行预处理,然后通过调用Slowfast模型进行预测,最后为每个id分配动作类别

        id_to_ava_labels={}
        if yolo_preds.pred[img_num//2].shape[0]:
            inputs,inp_boxes,_=ava_inference_transform(video_clips,yolo_preds.pred[img_num//2][:,0:4],crop_size=imsize)
            inp_boxes = torch.cat([torch.zeros(inp_boxes.shape[0],1), inp_boxes], dim=1)
            if isinstance(inputs, list): #判断类型
                inputs = [inp.unsqueeze(0).to(device) for inp in inputs]
            else:
                inputs = inputs.unsqueeze(0).to(device)
            with torch.no_grad():
                slowfaster_preds = video_model(inputs, inp_boxes.to(device)) #预测动作
                slowfaster_preds = slowfaster_preds.cpu()
            for tid,avalabel,avapred in zip(yolo_preds.pred[img_num//2][:,5].tolist(),np.argmax(slowfaster_preds,axis=1).tolist(),torch.max(slowfaster_preds,axis=1).values.tolist()):
                # if(avalabel in ava_labelnames_abnormal):
                    # id_to_ava_labels[tid]=ava_labelnames[avalabel+1]+'_abnormal'
                id_to_ava_labels[tid]=[ava_labelnames[avalabel+1],avapred]            # print(avalabel)

        # print(avalabel)
        # print(ava_labelnames[avalabel+1])
        if((avalabel+1) in ava_labelnames_abnormal):
            isnormal=False
        else:
            isnormal=True
        save_yolopreds_tovideo(yolo_preds,id_to_ava_labels,coco_color_map,outputvideo,isnormal)
    print("total cost: {:.3f}s, video clips length: {}s".format(time.time()-a,video.duration))
        
    outputvideo.release()
    print('saved video to:', vide_save_path)

3.将结果保存成视频

def save_yolopreds_tovideo(yolo_preds,id_to_ava_labels,color_map,output_video,isnormal):
    for i, (im, pred) in enumerate(zip(yolo_preds.imgs, yolo_preds.pred)):
        im=cv2.cvtColor(im,cv2.COLOR_BGR2RGB)
        if pred.shape[0]:
            for j, (*box, cls, trackid, vx, vy) in enumerate(pred):
                if int(cls) != 0:
                    ava_label = ''
                    ava_pred=0.0

                elif trackid in id_to_ava_labels.keys():
                    ava_label = id_to_ava_labels[trackid][0].split(' ')[0]
                    ava_pred=id_to_ava_labels[trackid][1]
                else:
                    ava_label = 'Unknow'
                    ava_pred=0.0

                if(isnormal):
                    text = '{:.4f} {} {}'.format(ava_pred,yolo_preds.names[int(cls)],ava_label)
                    color = [40,113,62]
                else:
                    text = '{:.4f} {} {} {}'.format(ava_pred,yolo_preds.names[int(cls)],ava_label,'abnormal')
                    color = [43,44,124]

                # print(cls)
                im = plot_one_box(box,im,color,text)
        output_video.write(im.astype(np.uint8))

总结

基于yolov5+deepsort+slowfast算法的视频实时行为检测就介绍到这里了!!!
如果该文章对您有所帮助,麻烦点赞,关注,收藏三连支持下!
创作不易,白嫖不好,各位的支持和认可,是我创作的最大动力!
如果本篇博客有任何错误,请批评指教,不胜感激 !!!


参考
Yolov5+SlowFast: 基于PytorchVideo的实时行为检测算法
YOLOv5算法详解
pytorch yolo5+Deepsort实现目标检测和跟踪
Yolov5+Deepsort+Slowfast实现实时动作检测

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/405890.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Java】运算符

我不去想是否能够成功 既然选择了远方 便只顾风雨兼程 —— 汪国真 目录 1. 认识运算符 1.1 认识运算符 1.2 运算符的分类 2. 算术运算符 2.1 四则运算符 2.2 复合赋值运算符 2.3 自增 / 自减 运算符 3.关系运算符 4.逻辑运算符 4.1 逻辑与 && 4.2 逻…

什么是异步

文章目录 前言一、异步是什么?二、举个例子来理解异步 1.异步最典型的例子就是“回调函数”总结前言 在vue的过程中,我们一定会遇到诸如: function(参数).then(res>{}) 形式的代码。到底怎么编译执行的呢 &#xf…

【Jetpack】ViewModel 架构组件 ( 视图 View 和 数据模型 Model | ViewModel 作用 | ViewModel 生命周期 | 代码示例 | 使用注意事项 )

文章目录一、Activity 遇到的问题二、视图 View 和 数据模型 Model三、ViewModel 架构组件作用四、ViewModel 代码示例1、ViewModel 视图模型2、Activity 组件3、UI 布局文件4、运行效果五、ViewModel 生命周期六、ViewModel 使用注意事项一、Activity 遇到的问题 Activity 遇到…

宝塔部署nodejs项目

前言 部署操作很简单,网上也有很多教程,不过我还是踩坑了,这里记录一下,给其他人也避避坑吧。 步骤 首先你已经有了服务器,并且打开了宝塔面板,其次准备好你的nodejs项目。 在宝塔安装pm2管理器&#xf…

Nginx 调整文件上传大小限制

使用3A服务器做了网页,感觉挺不错的,使用LNMP环境 用Nginx部署了前端,发现上传附件大一点就会报错,查看配置文件,发现spring的附件配置已经配置了。那么就看下Nginx的body设置。nginx文件上传默认是1MB。 在 server 模…

VUE3TS: Vue3+TS的项目搭建

简介 通过 Vue-cli4 创建的 Vue3TS 的项目,并进行一些基础使用的举例。 此例是以 VSCode编辑器 进行的编码。 一、项目搭建 1. 进入命令提示符窗口 在要搭建项目的文件夹中,点击路径,输入CMD并按回车 2. 查看node版本、Vue-cli版本 2…

Android 架构之长连接技术

上文中我们提到了HttpDNS,虽然它比系统DNS更优,但终归还是要做DNS操作。而长连接都是IP直接连接,因此没有DNS相关的开销和耗时。 3. 如果有大量网络请求,可以明显减少网络延时,节省带宽 对于大型App而言,…

npm——安装、卸载与更新

npm 官方文档:https://docs.npmjs.com/ 什么是npm npm(“Node 包管理器”)是 JavaScript 运行时 Node.js 的默认程序包管理器。 它也被称为“Ninja Pumpkin Mutants”,“Nonprofit Pizza Makers”,以及许多其他随机…

Vue通知提醒框(Notification)

项目相关依赖版本信息 可自定义设置以下属性: 自动关闭的延时时长(duration),单位ms,默认4500ms消息从顶部弹出时,距离顶部的位置(top),单位像素px,默认24p…

WebSocket开发(心跳监测)功能

前言 在之前的文章中完成了客服对话的Demo功能,但是现在的连接是无限制的长时间连接没有做心跳、失活、超时断连等功能,心跳的实现方法有很多种,并且WebSocket就提供了ping/pong类型的消息。 心跳的触发方式也分两种: 客户端触…

微信小程序实现图片上传

前言 手机上传图片的功能大家一定都用过吧,今天教你用微信小程序实现这个小功能。 实现效果如下: 实现思路: 首先我们需要定义一个存放图片的数组,通过方法拿取图片的详细信息,然后调用微信小程序的 wx.uploadFile 方…

element ui datepicker时间控件实现范围选择周,季,年。

因项目要求,需日,周,月,季,年五种日期范围选择器,故参考文章(在末尾)后分享 一.效果图 二、版本及下载 1.实现需要修改源码,目前修改的版本为2.15.3,所以想要…

Vue3路由配置createRouter、createWebHistory、useRouter,useRoute

目录 手动配置Vue-router环境: 组件内部跳转路由、传参useRouter,useRoute Vue3和Vue2基本差不多,只不过需要将createRouter、createWebHistory从vue-router中引入,再进行使用。 手动配置Vue-router环境: 1、下载包&#xff1a…

Uncaught (in promise) TypeError: Cannot read properties of undefined (reading ‘result‘)

Uncaught (in promise) TypeError: Cannot read properties of undefined (reading result) 如题所示问题,耽误三天寻找bug,终于在我睡意朦胧之际发现了一道光,发现 await 出现的三个点: 于是打开 findAllCategory()这个函数 对应…

电商后台管理系统简介

项目介绍 黑马后台管理系统是一个电商后台管理系统的前端项目,基于VueElement实现。 主要包括商品管理、订单管理、会员管理、促销管理、运营管理、内容管理、统计报表、财务管理、权限管理、设置等功能 开发技术 此项目开发我用到的技术有:vue2node.…

Vant 2 - 移动端 Vue 组件库 _ 问题记录

目录 Popup 弹出层 DatetimePicker 时间选择 Field 输入框 Picker 选择器 List 列表 Tab 标签页 发布初衷 : 记录在移动端项目中使用 Vant 2 组件库时遇到的各种问题 , 方便以后再次遇到类似问题 , 能够快时查阅解决 , …

Vue3+TypeScript+Vite如何使用require动态引入类似于图片等静态资源

问题:Vue3TypeScriptVite的项目中如何使用require动态引入类似于图片等静态资源! 描述:今天在开发项目时(项目框架为Vue3TypeScriptVite)需要 动态引入静态资源,也就是img标签的src属性值为动态获取&#…

Lodash 使用及常用方法

简介 Lodash 是一个一致性、模块化、高性能的 JavaScript 实用工具库。它内部封装了诸多对字符串、数组、对象等常见数据类型的处理函数,Lodash 通过降低 array、number、objects、string 等等的使用难度从而让 JavaScript 变得更简单。 官网 Lodash 简介 | Lodash 中文文档…

TypeScript详解十六:类型声明(declare)

目录前言一、类型声明的作用?1.1 declare 关键字1.2 示例二、常见的几种类型声明2.1 普通类型声明2.2 外部枚举2.3 命名空间三、类型声明文件3.1 模拟类型声明文件,以 jquery 为例3.2 使用手动实现的jquery.d.ts声明文件3.3 第三方声明文件(以…

Django web 开发(三) - Django的使用

文章目录Django安装Django安装Pythonpip加速安装Django创建项目文件介绍简单访问APP添加新的app注册app创建blog的页面templates模板templates模板语法单一变量列表循环(列表)字典循环(字典)列表套字典条件判断请求和响应案例: 用户登录数据库操作安装第三方模块ORM创建数据库D…