5 分钟教你搭建「视频动作分类」系统

news2025/4/16 21:51:48

写在前面

在之前的文章中,我们已经搭建过「以文搜图」、「以图搜图」等搜索服务,而今天这篇文章,将要教会你如何搭建一个「视频动作分类」的 AI 系统!

例如,我们只需放上一张“婴儿吃胡萝卜”的视频,这个系统就能分析和判断出这个视频最有可能的动作类别是 “eating carrots”。

「视频动作分类」系统展示图

怎么样,是不是很神奇呢?快跟着我们往下看吧!

准备工作

安装依赖包

在搭建「视频动作分类」系统之前,我们需要创建系统依赖的环境。我们用到了以下工具:

  • Towhee:用于构建模型推理流水线的框架,对于新手非常友好。

  • Milvus:用于存储向量并创建索引的数据库,简单好上手。

  • Gradio:轻量级的机器学习 Demo 构建工具。

  • Pillow:图像处理常用的 Python 库。

python -m pip install -q pymilvus towhee towhee.models pillow ipython gradio

数据准备

我们从 Kinetics400 的验证集中选取了 200 个视频,作为本次示例所用的数据。

首先,下载数据集并解压:

curl -L https://github.com/towhee-io/examples/releases/download/data/reverse_video_search.zip -O
unzip -q -o reverse_video_search.zip

这个数据集的包含了两个主文件:

  1. train:视频所在文件夹,包含 20 个类别(每个类别为一个子文件夹),每个类别包含了 10 个视频,总计有 200 个视频。

  2. reverse_video_search.csv:一个 csv 文件,其中包含视频文件夹中每个视频的 id、path 和 label。 接着,我们输入以下代码便可查看数据集内的详细信息:

import pandas as pd
df = pd.read_csv('./reverse_video_search.csv')print(df.head(3))print(df.label.value_counts())

同时,我们在这里定义一个ground_truth函数,这个函数可以通过视频文件路径就能找到它真实的分类标签。

def ground_truth(path):
    label = df.set_index('path').at[path, 'label']
    return [label.replace('_', ' ')]

到这里,我们就完成了所有的准备工作啦!

系统搭建

首先,我们使用 X3D_M 视频分类模型来预测视频所属的类别,利用 Towhee 提供的一系列简单又好用的 API 就可以对输入的视频进行批处理。

预测类别

舞蹈视频是最适合进行动作分类的例子了!我们在这里以目标类别为“tap_dancing”的视频为例,观察 X3D_M 模型预测的结果。在默认情况下,模型将会返回得分(可能性)最高的前 5 个分类,我们可以通过自行更改topk来控制返回的类别数量。

import towhee
(
    towhee.glob['path']('./train/tap_dancing/*.mp4')
          .video_decode.ffmpeg['path', 'frames'](sample_type='uniform_temporal_subsample', args={'num_samples': 16})
          .action_classification['frames', ('predicts', 'scores', 'features')]
          .pytorchvideo(model_name='x3d_m', skip_preprocess=True, topk=5).select['path', 'predicts', 'scores']()
          .show()
)

这里对用到的 Towhee API 做一些说明:

  • towhee.read_csv():从 CSV 文件中读取数据。

  • .video_decode.ffmpeg():一个 Towhee 的算子,能通过文件路径读取视频,并通过指定的采样方法得到一定数量的视频帧。了解更多

  • .action_classification.pytorchvideo():一个 Towhee 的算子,可以提取视频特征并预测视频所属的动作分类。了解更多

输入以上代码后,模型返回的结果示例如下:

可以看到,path 一栏是预测对象(视频)的文件路径,predicts(topk=5)一栏是预测的前五个结果,scores 一栏则是五个类别对应的得分。上图展示了5个视频的预测结果,top1 (第一个预测类别)的预测结果有 4/5 判断正确,而 top2 (前两个预测类别)则全部准确预测。

评估和优化

我们刚刚展示了如何识别一个动作视频的类别,但这套系统的整体性能表现如何呢?接下来,我们借助 Towhee 批量处理和评估接口,使用 mHR(recall@K)来衡量预测结果。

import time

start = time.time()
dc = (
      towhee.read_csv('reverse_video_search.csv').unstream()
            .video_decode.ffmpeg['path', 'frames'](sample_type='uniform_temporal_subsample', args={'num_samples': 16})
            .action_classification['frames', ('predicts', 'scores', 'features')].pytorchvideo(
                 model_name='x3d_m', skip_preprocess=True, topk=5)
)
end = time.time()
print(f'Total time: {end-start}')
    
benchmark = (
      dc.runas_op['path', 'ground_truth'](func=ground_truth)
        .runas_op['predicts', 'top1'](func=lambda x: x[:1])
        .runas_op['predicts', 'top3'](func=lambda x: x[:3])
        .with_metrics(['mean_hit_ratio'])
        .evaluate['ground_truth', 'top1'](name='top1')
        .evaluate['ground_truth', 'top3'](name='top3')
        .evaluate['ground_truth', 'predicts'](name='top5')
        .report()
)

运行以上代码后,会返回处理和预测所有样本数据的时间和不同 topk 对应的命中率。

Total time: 39.41930913925171

可以看到,X3D_M 模型预测 200 个示例视频所需要花费的时间约为 39 s(平均每个视频消耗约0.2s),预测结果 top1 的准确率为 70%,而 top5 的准确率高达 90%!

虽然 90% 的命中率是一个不错的结果,但我们使用的 X3D_M 轻量模型其实已经牺牲了部分精度。如果换成更复杂的深度学习模型,比如 MViT,理论上能够使准确率更上一层楼。

我们只需将上面代码中的 model_name 指定为 'mvit_base_32x3' 即可:

import time

start = time.time()
dc = (
towhee.read_csv('reverse_video_search.csv').unstream()
      .video_decode.ffmpeg['path', 'frames'](sample_type='uniform_temporal_subsample', args={'num_samples': 32})
      .action_classification['frames', ('predicts', 'scores', 'features')].pytorchvideo(
           model_name='mvit_base_32x3', skip_preprocess=True, topk=5)
)
end = time.time()
print(f'Total time: {end-start}')

benchmark = (
    dc.runas_op['path', 'ground_truth'](func=ground_truth)
      .runas_op['predicts', 'top1'](func=lambda x: x[:1])
      .runas_op['predicts', 'top3'](func=lambda x: x[:3])
      .with_metrics(['mean_hit_ratio'])
      .evaluate['ground_truth', 'top1'](name='top1')
      .evaluate['ground_truth', 'top3'](name='top3')
      .evaluate['ground_truth', 'predicts'](name='top5')
      .report()
)

Total time: 79.16032028198242

不难发现,我们使用了同样的样本数据,然而将模型替换成 MViT 后,所需时间大约是之前的 2 倍,而准确率的确有所提升:

那有什么办法可以既高效快速地运行模型,又能保持较高的准确率呢? 有!Towhee 允许并行执行,能够减少处理批量数据的时间。我们只需在代码中加入 set_parallel()

start = time.time()
dc =(
    towhee.read_csv('reverse_video_search.csv').unstream()
          .set_parallel(5)
          .video_decode.ffmpeg['path', 'frames'](sample_type='uniform_temporal_subsample', args={'num_samples': 16})
          .action_classification.pytorchvideo['frames', ('predicts', 'scores', 'features')](
               model_name='x3d_m', skip_preprocess=True, topk=5)
)
end = time.time()
print(f'Total time: {end-start}')

这一次花费的时间几乎是之前的一半:Total time: 22.97886061668396,明显比之前更快了!

异常处理

如果我们一次处理多条数据,其中一个数据异常就会使整个程序报错并中断,这对于大规模测试或者生产环境无疑是致命的。而这些异常数据并不会影响整个「视频动作分类」系统,所以,我们需要让系统在遇到异常值时生成报告,然后继续处理其余的视频。

Towhee 支持异常处理的执行模式,允许流水线继续处理并用 Empty 值表示异常。 用户可以选择如何处理流水线末端的空值。

(
    towhee.glob['path']('./exception/*')
          .exception_safe()
          .video_decode.ffmpeg['path', 'frames'](sample_type='uniform_temporal_subsample', args={'num_samples': 16})
          .action_classification['frames', ('labels', 'scores', 'vec')].pytorchvideo(
               model_name='x3d_m', skip_preprocess=True)
          .drop_empty()
          .select['path', 'labels']()
          .show()
)

在上面的查询过程中,exception文件夹下共有 4 个文件,其中 1 个文件损坏。 使用exception_safe()后,我们最终成功获得了 3 个视频文件的预测结果。从结果中可以看出,drop_empty()删除了失败的预测结果(空数据)。

 

Gradio 部署 demo

Towhee 提供的 towhee.api()可以将流水线包装成一个函数,以便使用。 我们可以在 Gradio 中使用这个 action_classification_function 轻而易举地构建一个简单可交互的在线演示 demo。

import gradio

topk = 3
with towhee.api() as api:
    action_classification_function = (
        api.video_decode.ffmpeg(
            sample_type='uniform_temporal_subsample', args={'num_samples': 32})
        .action_classification.pytorchvideo(model_name='mvit_base_32x3', skip_preprocess=True, topk=topk)
        .runas_op(func=lambda res: {res[0][i]: res[1][i] for i in range(len(res[0]))})
        .as_function()
    )
    
        interface = gradio.Interface(action_classification_function, 
                                      inputs=gradio.Video(source='upload'),
                                      outputs=[gradio.Label(num_top_classes=topk)]
                                      )
        interface.launch(inline=True, share=True)

Gradio 为我们提供了一个 Web UI,点击 URL 进行访问(或直接与 notebook 下方出现的界面进行交互):

点击这个 URL 链接,就会跳转到我们「视频分类」的交互界面,输入你想要分类的视频,即可呈现出视频所对应的分类标签。例如,我们上传一个“婴儿吃胡萝卜” 的视频即可得到系统识别的动作标签:

可以看到,我们的「视频分类」系统是十分精确的,能准确地识别并给出视频所属的分类标签。

总结

在今天的文章中,我们通过 Towhee 利用 X3D 以及 MViT 两种不同量级的视频动作分类模型搭建了一个简单的「视频分类」系统,并使用 Gradio 创建了一个可交互的程序界面。

在之前的文章中,我们在 Towhee 的帮助下搭建了「以文搜图」、「以图搜图」等搜索服务,参考本文的实现,我们也可以利用 Towhee (以及 Milvus)实现更多种更通用的视频分类和识别业务,大家可以动起手来搭建一套属于自己的 AI 业务系统!

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

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

相关文章

代码随想录57——动态规划:647回文子串、516最长回文子序列

文章目录1.647回文子串1.1.题目1.2.解答2.516最长回文子序列2.1.题目2.2.解答1.647回文子串 参考:代码随想录,647回文子串;力扣题目链接 1.1.题目 1.2.解答 动规五部曲: 1.确定dp数组(dp table)以及下标…

如何优雅的使用 IDEA Debug 进行调试

如何优雅的使用 IDEA Debug 进行调试 Debug 是我们在开发过程中经常会使用到的一种排查问题的手段,我们用它来定位分析异常的出现,以及程序在运行中参数的变化。 IDEA 本身具有很强的调试功能,掌握 IDEA 的一些 Debug 技巧,对我们…

【JS】原生js实现矩形框的绘制/拖动/拉伸

1、要点及功能描述 通过js监听mouse事件来实现矩形框的绘制,再通过区分点击的是边角还是其他位置来实现矩形框的拉伸和拖动,并且在拖动和拉伸时,都做了边界限制,当拉伸或拖动 到边界时,就不能继续拉伸拖动了。当然在相…

7个实用有效的shopify运营策略,跨境电商卖家必知

关键词:shopify运营、跨境电商卖家 您的Shopify 在线商店是使用当今最好的平台之一构建的。2022 年第二季度,Shopify 在美国电子商务平台中占据最大市场份额,约占美国所有在线业务的 32%。 这也意味着电子商务品牌之间的竞争比以往任何时候都…

【图像融合】基于matlab DSIFT多聚焦图像融合【含Matlab源码 2224期】

⛄一、SIFT配准简介 1 算法概述 在实时系统中,算法的输入为相机数据流,当前输入的图像与上一张相似度很高时应不参与融合,由于在体视显微镜下序列图像存在较大程度的偏移,所以融合前还需要进行图像配准,配准完成后再进…

安杰思提交注册:预计2022年度收入不低于3.5亿元,同比增长15%

11月16日,杭州安杰思医学科技股份有限公司(下称“安杰思”)在上海证券交易所科创板提交招股书(注册稿)。据贝多财经了解,安杰思于2022年6月24日在科创板递交上市申请材料,2022年11月7日获得上市…

面试--线程池的执行流程和拒绝策略有哪些?

一. 执行流程 聊到线程池就一定会聊到线程池的执行流程, 也就是当有一个任务进入线程池之后, 线程池是如何执行的? 想要真正的了解线程池的执行流程,就得先从线程池的执行方法 execute() 说起, execute() 实现源码如下: public void execute(Runnable command)…

2.10.2版本的青龙升级2.10.13及2.11.3版本的教程

重要提醒: 这个教程仅限使用我下面这个命令搭建的青龙面板使用 docker run -dit \--name QL \--hostname QL \--restart always \-p 5700:5700 \-v $PWD/QL/config:/ql/config \-v $PWD/QL/log:/ql/log \-v $PWD/QL/db:/ql/db \-v $PWD/QL/scripts:/ql/scripts \-…

【消息队列笔记】chp3-如何确保消息不丢失

一、检测消息是否丢失 我们要保证消息的可靠交付,首先就要知道消息是否丢失了。如何做到这一点呢? 对于IT基础设施比较完善的公司,可以使用分布式链路追踪系统来追踪每一条消息。如果没有这样的系统,可以使用消息的有序性来验证…

圆角矩形不是圆:圆角的画法和二阶连续性

本文中的所有重要图片都会给出基于Matplotlib的Python绘制代码以供参考 引言 如果在百度搜索圆角矩形的画法,那么多数结果都会告诉你,就是把一个普通矩形的拐角换成相切的 14\frac{1}{4}41​ 圆弧,就像 引文1 和 引文2 说的那样。然而&#x…

网络规划设计与综合布线技术详解

一、网络工程概述 1、计算机网络及其组成 计算机网络是现代通信技术与计算机技术相结合的产物。 随着计算机网络本身的发展,人们认为:计算机网络是把地理位置不同、功能独立自治的计算机系统及数据设备通过通信设备和线路连接起来,在功能完善的网络软件运行支持下,以实现…

springboot+vue实现excel的导出

首先是springboot对数据的处理 依赖的导入 <dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>4.1.2</version></dependency>RequestMapping("/exportExcel") public R exportR…

【SpringBoot项目】SpringBoot项目-瑞吉外卖【day01】

文章目录前言软件开发整体介绍软件开发流程瑞吉外卖项目介绍项目介绍产品原型展示技术选型功能架构角色开发环境搭建数据库环境搭建maven项目搭建设置静态资源映射后台登录需求分析代码开发功能测试后台退出需求分析代码开发功能测试&#x1f315;博客x主页&#xff1a;己不由心…

JVS低代码如何实现复杂物料编码?

日常业务过程中&#xff0c;存在大量的编码&#xff0c;例如订单的流水号&#xff0c;复杂的物料编码&#xff0c;学生证号等等场景&#xff0c;那么通过JVS如何去实现各种编码&#xff1f; 为了让使用者使用尽量简单&#xff0c;我们编码分为简单配置的编码和复杂配置的编码。…

[附源码]java毕业设计家校通信息管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

docker stats查询容器状态显示异常有模线

docker stats 命令用来显示容器使用的系统资源。 默认情况下&#xff0c;stats 命令会每隔 1 秒钟刷新一次输出的内容直到你按下 ctrl c。 输出详情介绍&#xff1a; CONTAINER ID 与 NAME: 容器 ID 与名称。 CPU % 与 MEM %: 容器使用的 CPU 和内存的百分比。 MEM USAGE…

Java基础之《netty(1)—netty介绍》

一、介绍 1、netty是由JBOSS提供的一个java开源框架&#xff0c;现为github上的独立项目。 2、netty是一个异步的、基于事件驱动的网络应用框架&#xff0c;可以快速开发高性能、高可靠的网络IO程序。 3、netty主要针对在TCP协议下&#xff0c;面向clients端的高并发应用&…

【python3】4.文件管理

2022.11.16 本学习内容总结于莫烦python:4.文件管理 https://mofanpy.com/tutorials/python-basic/interactive-python/read-write-file4 文件管理 4.1 读写文件 均是用特殊字符open 4.1.1 创建文件 f open("new_file.txt", "w") # 创建并打开 f.wr…

进入数字化供应链高潮期,与IBM咨询共创无边界竞争力

供应链领域的国际专家马丁克里斯托弗在30年前就提出“未来的竞争不再是企业和企业之间的竞争&#xff0c;而是供应链之间的竞争。”近几年来&#xff0c;基于工业4.0技术的供应链4.0开始进入业界的视野&#xff0c;2020年开始的疫情让全球供应链结束了长期稳定状态而进入VUCA&a…

针对谷氨酰胺运输体的小分子抑制剂

精准癌症治疗手段 在运输体水平靶向谷氨酰胺代谢 ACST2 蛋白是谷氨酰胺进入癌细胞的主要转运蛋白。在肺癌、乳腺癌、结肠癌等癌症中&#xff0c;ACST2 蛋白水平的上调与患者存活率有关。当抑制 ACST2 基因表达时&#xff0c;会显著抑制癌细胞生长。ASCT2 水平升高与多种癌症的…