行人实时动作识别

news2024/9/23 9:35:49
  • 详细资料和代码请加微信:17324069443

一、项目介绍

基于PyTorchVideo的实时动作识别框架:
我们选择了yolov5作为目标检测器,而不是Faster R-CNN,它速度更快、更方便。
我们使用一个跟踪器(deepsort)来为不同帧中所有具有相同ID的对象分配动作标签。
行为识别使用 slowfast算法,根据前后帧的图片,分析这个序列,来判断是做了什么动作
我们在单个RTX 2080Ti GPU上以30个推理批处理大小达到了24.2 FPS的处理速度。
在这里插入图片描述

二、算法介绍

2.1 yolov5目标检测

YOLOv5是一种基于深度学习的目标检测算法,它在目标检测和图像识别领域具有很高的性能。YOLOv5建立在先前版本(如YOLOv3和YOLOv4)的基础上,通过引入一系列改进来提高检测准确性和速度。
YOLOv5的核心架构是基于单阶段目标检测器(one-stage detector)。与传统的两阶段方法不同,YOLOv5通过单个神经网络模型直接从图像中预测目标的类别和边界框位置。这使得YOLOv5在速度和准确性之间取得了良好的平衡,适用于许多实时应用场景。
YOLOv5的主要特点和优势包括:

  • 轻量化设计
  • 多尺度检测
  • 自动数据增强
  • 简单易用

YOLOv5在许多基准数据集上取得了优秀的检测性能,并且被广泛应用于实际场景中,包括智能监控、自动驾驶、工业检测等领域。其高性能和灵活性使得YOLOv5成为目标检测领域的热门选择之一。

2.2 DeepSort目标跟踪

DeepSort是一种基于深度学习的目标跟踪算法,旨在解决多目标跟踪问题。它结合了目标检测和目标跟踪两个关键任务,能够在视频序列中准确地追踪多个目标并分配唯一的ID。
DeepSort算法的核心思想是将卷积神经网络(CNN)用于目标检测,以便识别视频帧中的目标,并结合深度学习技术来进行目标特征提取和关联。具体来说,DeepSort首先使用一个预训练的目标检测器(如YOLO或Faster R-CNN)来检测视频帧中的目标,并提取目标的特征表示。
接着,DeepSort利用深度学习模型(通常是基于Siamese网络或类似的架构)来计算不同目标之间的相似度,并根据目标之间的特征相似性来进行目标关联。通过在时间序列中跟踪目标的位置,并根据目标的外观和运动特征来更新目标的状态,DeepSort能够有效地处理目标在视频中的出现、消失和遮挡等情况,实现稳健的多目标跟踪。
DeepSort算法在目标跟踪领域取得了显著的成果,特别是在具有复杂背景和目标重叠的场景下表现突出。它在许多跟踪竞赛和实际应用中都取得了优异的性能,成为目标跟踪领域的重要算法之一。深度学习方法的引入使得DeepSort在目标跟踪任务中更加准确、高效,并且具有良好的通用性和可扩展性。

2.3 slowfast动作识别

SlowFast是一种用于视频动作识别的深度学习算法。它是在Facebook AI研究团队提出的基础上发展而来的,旨在解决传统的单帧或连续帧方法在动作识别任务中存在的困难。
SlowFast算法的核心思想是引入两个不同速度的流来处理视频数据:慢速流(Slow)和快速流(Fast)。慢速流用于捕捉视频中的空间细节,它对每个帧进行较高的时间采样,以更好地理解运动的细节。快速流则用于捕捉动作的快速变化,它对每个帧进行较低的时间采样,以更好地捕捉动作的整体动态。
具体实现上,SlowFast网络由两个并行的卷积神经网络流组成:慢速流和快速流。慢速流通常包含较多的卷积层和较大的时间步长,以便对空间细节进行更深入的分析。而快速流则包含较少的卷积层和较小的时间步长,以便对动作的快速变化进行快速响应。
在训练过程中,SlowFast网络通过使用慢速流和快速流来学习视频的空间和时间特征,以及它们之间的关系。通过在大规模视频数据集上进行训练,SlowFast网络能够学习到通用的动作表示,从而在动作识别任务中取得良好的性能。
SlowFast算法在视频动作识别领域表现出色,其能够有效地捕捉视频中的空间和时间信息,并且在处理速度和准确率之间取得了良好的平衡。它在许多视频动作识别的挑战中取得了领先的结果,并被广泛应用于视频分析、智能监控等领域。

三、代码实现

def tensor_to_numpy(tensor):
    img = tensor.cpu().numpy().transpose((1, 2, 0))
    return img

def ava_inference_transform(clip, boxes,
    num_frames = 32, #if using slowfast_r50_detection, change this to 32, 4 for slow 
    crop_size = 640, 
    data_mean = [0.45, 0.45, 0.45], 
    data_std = [0.225, 0.225, 0.225],
    slow_fast_alpha = 4, #if using slowfast_r50_detection, change this to 4, None for slow
):
    boxes = np.array(boxes)
    roi_boxes = boxes.copy()
    clip = uniform_temporal_subsample(clip, num_frames)
    clip = clip.float()
    clip = clip / 255.0
    height, width = clip.shape[2], clip.shape[3]
    boxes = clip_boxes_to_image(boxes, height, width)
    clip, boxes = short_side_scale_with_boxes(clip,size=crop_size,boxes=boxes,)
    clip = normalize(clip,
        np.array(data_mean, dtype=np.float32),
        np.array(data_std, dtype=np.float32),) 
    boxes = clip_boxes_to_image(boxes, clip.shape[2],  clip.shape[3])
    if slow_fast_alpha is not None:
        fast_pathway = clip
        slow_pathway = torch.index_select(clip,1,
            torch.linspace(0, clip.shape[1] - 1, clip.shape[1] // slow_fast_alpha).long())
        clip = [slow_pathway, fast_pathway]
    
    return clip, torch.from_numpy(boxes), roi_boxes

def plot_one_box(x, img, color=[100,100,100], text_info="None",
                 velocity=None,thickness=1,fontsize=0.5,fontthickness=1):
    # Plots one bounding box on image img
    c1, c2 = (int(x[0]), int(x[1])), (int(x[2]), int(x[3]))
    cv2.rectangle(img, c1, c2, color, thickness, lineType=cv2.LINE_AA)
    t_size = cv2.getTextSize(text_info, cv2.FONT_HERSHEY_TRIPLEX, fontsize , fontthickness+2)[0]
    cv2.rectangle(img, c1, (c1[0] + int(t_size[0]), c1[1] + int(t_size[1]*1.45)), color, -1)
    cv2.putText(img, text_info, (c1[0], c1[1]+t_size[1]+2), 
                cv2.FONT_HERSHEY_TRIPLEX, fontsize, [255,255,255], fontthickness)
    return img

def deepsort_update(Tracker,pred,xywh,np_img):
    outputs = Tracker.update(xywh, pred[:,4:5],pred[:,5].tolist(),cv2.cvtColor(np_img,cv2.COLOR_BGR2RGB))
    return outputs

def save_yolopreds_tovideo(yolo_preds,id_to_ava_labels,color_map,output_video):
    for i, (im, pred) in enumerate(zip(yolo_preds.ims, 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 = ''
                elif trackid in id_to_ava_labels.keys():
                    ava_label = id_to_ava_labels[trackid].split(' ')[0]
                else:
                    ava_label = 'Unknow'
                text = '{} {} {}'.format(int(trackid),yolo_preds.names[int(cls)],ava_label)
                color = color_map[int(cls)]
                im = plot_one_box(box,im,color,text)
        output_video.write(im.astype(np.uint8))

def main(config):
    model = torch.hub.load('ultralytics/yolov5', 'yolov5l6')
    model.conf = config.conf
    model.iou = config.iou
    model.max_det = 200
    if config.classes:
        model.classes = config.classes
    device = config.device
    imsize = config.imsize
    video_model = slowfast_r50_detection(True).eval().to(device)
    deepsort_tracker = DeepSort("data/models/ckpt.t7")
    ava_labelnames,_ = AvaLabeledVideoFramePaths.read_label_map("selfutils/temp.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)
    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,:,:]))
        yolo_preds=model(imgs, size=imsize)
        yolo_preds.files=[f"img_{i*25+k}.jpg" for k in range(img_num)]

        print(i,video_clips.shape,img_num)
        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.ims[j])
            if len(temp)==0:
                temp=np.ones((0,8))
            deepsort_outputs.append(temp.astype(np.float32))
        yolo_preds.pred=deepsort_outputs
        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 in zip(yolo_preds.pred[img_num//2][:,5].tolist(),np.argmax(slowfaster_preds,axis=1).tolist()):
                id_to_ava_labels[tid]=ava_labelnames[avalabel+1]
        save_yolopreds_tovideo(yolo_preds,id_to_ava_labels,coco_color_map,outputvideo)
    print("total cost: {:.3f}s, video clips length: {}s".format(time.time()-a,video.duration))
    outputvideo.release()
    print('saved video to:', vide_save_path)
    
    
if __name__=="__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument('--input', type=str, default="data/1.mov", help='test imgs folder or video or camera')
    parser.add_argument('--output', type=str, default="data/output.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='cpu', help='cuda device, i.e. 0 or 0,1,2,3 or cpu')
    parser.add_argument('--classes', nargs='+', type=int, help='filter by class: --class 0, or --class 0 2 3')
    config = parser.parse_args()
    print(config)
    main(config)

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

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

相关文章

STM32(15)USART编程

使用USART实现STM32与电脑之间的通信 中介:USB转TTL模块 闭合总开关,外部时钟才会传输到分频器 c8t6手册里面写了,usart最大支持4.5MHz,所以选10 重映射时记得开启AFIO的时钟

什么是MAC地址? win10电脑查看MAC地址的多种方法

您是否知道连接到家庭网络的每件硬件都有自己的身份?正如每个设备都分配有自己的 IP 地址一样,每个硬件都有一个唯一的网络标识符。 该标识符称为MAC 地址。MAC 代表媒体访问控制。您可能需要 MAC 地址来解决网络问题或配置新设备。在 Windows 中查找您…

java常用应用程序编程接口(API)——Arrays概述

前言: 学到Arrays了,整理下心得。打好基础,daydayup! Arrays 用来操作数组的一个工具类 Arrays的常见方法 方法名说明public static String toString(类型[] arr)返回数组的内容public static int[ ] copyOfRange(类型[ ] arr,启示索引&…

机器人工具箱学习(二)

一、机械臂及运动学 1.1 机械臂构成 机械臂多采用关节式机械结构,一般具有6个自由度,其中3个用来确定末端执行器的位置,另外3个则用来确定末端执行装置的方向(姿态)。   如图所示,一个机械臂是由一组可做相对运动的关节连接的连…

[译]BNF 表示法:深入了解 Python 的语法

[译]BNF 表示法:深入了解 Python 的语法 原文:《BNF Notation: Dive Deeper Into Python’s Grammar》 https://realpython.com/python-bnf-notation/ 在阅读Python文档的时候,你可能已经遇到过BNF(Backus–Naur form)表示法: 下…

运维:记一次寻找定时任务并删除的经历

前言 我相信接手别人的服务器、或者在没有任何文档的情况去看自己原先的服务器,都或多或少会遇到莫名其妙的服务器独有规则。 比如你服务本身跑的好好的,突然啪的一下,没了! 什么原因导致的呢?其中,很大可能是定时任务在作祟。 原因分析 本次,我遇到的问题是:在Ubuntu系…

如何用Elementor创建WordPress会员网站

在下面的文章中,我们将向您展示如何使用Elementor和MemberPress在WordPress中轻松构建会员网站。这篇文章将涵盖WordPress会员网站设置过程、会员资格和受保护内容创建、重要页面和登录表单设计、电子邮件通知管理、报告等。 目录 什么是WordPress会员网站&#x…

某品零食交易平台设计与实现|基于springboot+ Mysql+Java的某品交易平台设计与实现(源码+数据库+文档+PPT)

目录 基于springboot MysqlJava的某品交易平台设计与实现 摘 要 系统详细设计 数据库设计 论文参考 源码获取 文末获取源码联系 基于springboot MysqlJava的某品交易平台设计与实现 摘 要 随着科学技术的飞速发展,社会的方方面面、各行各业都在努力与现代的…

HCIA-HarmonyOS设备开发V2.0证书

目录 一、不墨迹,上证书二、考试总结三、习题四、知识点五、坚持就有收获 HCIA-HarmonyOS Device Developer V2.0 开发者能力认证考试已通过。 一、不墨迹,上证书 一个多月的努力,验证了自己的学习成果,也认识到自己有待提升之处…

promise处理数组里面的多任务,等所有任务处理完再执行后续逻辑

业务需求,有一个数组里面的数据,需要发送异步任务验证这里面的数据是否可用,然后再将可用的数据存储到本地,原本使用的方式是使用forEach遍历数组,然后在遍历中处理每一个异步函数,等处理完异步函数之后&am…

2024最新AI大模型产品汇总

文章目录 1. 写在前面2. 效率工具3. 聊天机器人4. 应用开发工具5. Prompt工具与社区6. 通用基础大模型7. 训练框架8. 开源数据集9. 推理与部署平台及工具 【作者主页】:吴秋霖 【作者介绍】:Python领域优质创作者、阿里云博客专家、华为云享专家。长期致…

springboot+bootstrap+jsp校园二手书交易平台mlg86

考虑到实际生活中在校园二手书交易系统方面的需要以及对该系统认真的分析,将系统权限按管理员和学生这两类涉及用户划分。 (a) 管理员;管理员使用本系统涉到的功能主要有个人中心、学生管理、图书类型管理、二手图书管理、通知公告管理、管理员管理、用户留言、系统…

istio pod不启动及访问报RBAC错误问题解决

istio pod不启动问题解决 在kubernetes集群中安装istio之后,在创建的depoyment中已经使用了注入注解sidecar.istio.io/inject: true’配置,但是istio pod不创建,代码示例如下 kind: Deployment apiVersion: apps/v1 metadata:name: name-an…

【Docker】Docker:解析容器化技术的利器与在Linux中的关键作用

🍎个人博客:个人主页 🏆个人专栏:Linux ⛳️ 功不唐捐,玉汝于成 目录 前言 正文 Docker 是什么? Docker 的作用 Docker 在 Linux 中的重要性 结语 我的其他博客 前言 随着软件开发的不断发展&…

012 Linux_线程控制

前言 本文将会向你介绍线程控制(创建(请见上文),终止,等待,分离) 线程控制 线程终止 pthread_t pthread_self(void); 获取线程自身的ID 如果需要只终止某个线程而不终止整个进程,可以有三种…

鸿蒙实战应用开发:【拨打电话】功能

概述 本示例通过输入电话,进行电话拨打,及电话相关信息的显示。 样例展示 涉及OpenHarmony技术特性 网络通信 基础信息 拨打电话 介绍 本示例使用call相关接口实现了拨打电话并显示电话相关信息的功能 效果预览 使用说明 1.输入电话号码后&#…

7、Linux-防火墙和配置静态ip

一、防火墙(防火墙服务名firewalld) 防火墙配置命令:firewall-cmd firewall-cmd --help:防火墙帮助firewall-cmd --state:查看防火墙状态firewall-cmd --zonepublic --list-ports:查看所有打开的端口firew…

【独立版】表情包小程序完整版源码前后端源码

搭建要求: 1.系统要求Nginx 1.18.0PHP-7.2mysql5.6,开启 ssl,php需要安装 sg11 扩展 2.设置伪静态 location / { index index.php index.html index.htm; if (!-e $request_filename) { rewrite ^/(.*)$ /index.php?s$1; } } location /a…

【三维重建】VastGaussian:用于大场景重建的大3D Gaussian(CVPR 2024)

题目:VastGaussian: Vast 3D Gaussians for Large Scene Reconstruction 来源:清华大学;华为诺亚;中国科学院 链接:https://vastgaussian.github.io/ 总结:VastGaussian:基于3D GS的分块优化重…

栈帧、ELF

前言 大家好我是jiantaoyab,这是我所总结作为学习的笔记第四篇,在这里分享给大家,还有一些书籍《深入理解计算机系统》《计算机组成:结构化方法》《计算机体系结构:量化研究方法》《程序员的自我修养》,今天我们来了解程序栈 为什…