Adrian Rosebrock作者赵春光、林亦霖校对王菁编辑吴振东翻译

利用OpenCV和深度学习来实现人类活动识别(附链接)

这篇教程会告诉你如何利用OpenCV和深度学习来实现人类动作识别。

通过阅读这篇教程,你可以学到如何利用OpenCV深度学习来实现人类动作识别。

我们实现的人类活动识别模型可以识别超过400类活动,其中准确率在78.4-94.5%之间(取决于任务类别)。 比如,活动类别的可包括:

1. Archery 射箭
2. arm wrestling 掰手腕
3. baking cookies 烤饼干
4. counting money 数钱
5. driving tractor 开拖拉机
6. eating hotdog 吃热狗
7. flying kite 放风筝
8. getting a tattoo 刺纹身
9. grooming horse 给马梳毛
10. hugging 拥抱
11. ice skating 溜冰
12. juggling fire 火焰杂耍
13. kissing 亲吻
14. laughing 大笑
15. motorcycling 骑摩托车
16. news anchoring 播报新闻
17. opening present 拆礼物
18. playing guitar 弹吉他
19. playing tennis 打网球
20. robot dancing机械人跳舞
21. sailing 开帆船
22. scuba diving 潜水
23. snowboarding 单板滑雪
24. tasting beer 喝啤酒
25. trimming beard 修剪胡子
26. using computer使用电脑
27. washing dishes 洗盘子
28. welding 焊接
29. yoga 练瑜伽
30. …and more! 其他

人类活动识别可用于的实践应用包括:
  • 给硬盘中的视频数据集自动分类/分组。

  • 训练或监察新员工准确地完成任务(例如做披萨时的步骤和流程是否合适,其中包括揉面团、上烤炉加热、加盐、加芝士、加馅料等等)。

  • 验证食品的服务生从洗手间出来或手工处理食物时有没有洗手,以免出现交叉污染(比如说鸡肉上的沙门氏菌)。

  • 检查酒吧或饭店里的顾客没有被过度服务(灌酒)。

想要学习如何利用OpenCV深度学习来实现人类动作检测,请继续阅读本教程。

在这篇教程的第一部分,我们先来讨论下Kinetics数据集,该数据集用来训练人类活动识别模型。

在那之后我们可以聊聊如何来扩展ResNet, 该网络通常使用2D核函数,而我们将采用3D核函数,这样就引入了活动识别模型可利用的时空维度成分。

接下来我们将会实现两种版本的人类活动识别,使用的都是OpenCV库和Python编程语言。

最后,我们应用人类活动识别模型到几个视频样例上,并看一下验证结果。

Kinetics数据集

图1:教程中所采用的人类活动识别深度学习模型是利用Kinetics 400数据集来完成预训练的
 
我们的人类活动识别模型是利用Kinetics 400数据集来完成训练的。

该数据集包括:
  • 400种人类活动识别分类。

  • 每个类别至少400个视频片段(下载自YouTube)。

  • 一共有300,000个视频。

你可以点击这一链接来查询该模型可以识别的类型名单:

https://github.com/opencv/opencv/blob/master/samples/data/dnn/action_recongnition_kinetics.txt

想要了解关于该数据集的更多信息,包括是如何去整合数据,请参考Kay 等人在2017年发表的论文《The Kinetics Human Action Video Dataset》。

《The Kinetics Human Action Video Dataset》
https://arxiv.org/abs/1705.06950

用于人类动作识别的3D ResNet

图2:深度神经网络利用ImageNet在图像识别上的进度已经使深度学习活动识别方面趋于成功(在视频方向),在这篇教程中,我们会利用OpenCV进行深度学习活动识别(照片源自Hara等人的论文) 

我们用于人类活动识别的模型来自于Hara 等人在2018年发表于CVPR的论文《Can Spatiotemporal 3D CNNs Retrace the History of 2D CNNs and ImageNet》

该论文作者对现有的最先进的2D结构(比如说ResNet,ResNeXt,DenseNet等)进行了探索,将它们扩展为3D核函数从而用于视频分类。

《Can Spatiotemporal 3D CNNs Retrace the History of 2D CNNs and ImageNet》

https://arxiv.org/abs/1711.09577

上述文章的作者认为:
  • 这些网络架构都成功地应用到了图像分类中。

  • 经过大规模数据集ImageNet的训练,这些模型都达到了非常高的准确率

  • Kinetics数据集的规范同样足够大。

…,因此这些网络架构也应该可以适用于视频分类,通过:1.改变输入集的维度来引入时空维度上的信息;2.在这些网络架构中使用3D核函数

事实证明上述文章的作者的观点是正确的!

通过改变输出集的维度和卷积核的维度,上述作者获得了如下效果:
  • 在Kinetics测试数据集上的准确率是78.4%。

  • 在UCF-101测试数据集上的准确率是94.5%。

  • 在HMDB-51测试数据集上的准确率是70.2%。

这些结果与利用ImageNet训练的最先进的模型所发布的R1准确率近似,因此这证明了这些模型架构可以用于视频分类,只需要简单地加上时空信息以及用3D核函数来代替2D核函数

下载OpenCV人类活动识别模型

图3:利用OpenCV深度学习实现人类活动识别所需文件

对于接下来的教程,你所需要下载的有:
  • 人类活动模型

  • Python + OpenCV源代码

  • 用于视频分类的样例

你可以在公众号中下载含有全部内容的压缩文件。一旦完成下载,你可以继续阅读本教程。

项目结构

让我们来检查一下项目文件:

我们的项目包含三个附属文件:
  • action_recognition_kinetics.txt : Kinetics数据集的类别标签。

  • resnet-34_kinetics.onx : Hara 等人提出的人类活动识别卷积神经网络,并已利用Kinetics数据集完成预训练和序列化。

  • example_activities.mp4 :一段用于测试人类活动识别的剪辑片段合集。

我们将会回顾一下两个Python脚本,每一个都会接收上面三个文件作为输入:
  • human_activity_reco.py :我们的人类活动识别脚本每次将N帧图像作为取样,用于活动分类预测。

  • human_activity_reco_deque.py :一个类似的人类活动识别脚本,使用了一个移动平均数队列。这个脚本跑起来要更慢,不管怎样,我在这里提供这个实现方式,这样你就可以对其进行试验并从中学到一些东西。

利用OpenCV的人类活动识别实现

让我们开始使用OpenCV来完成人类活动识别实现。这一实现是基于OpenCV的官方样例,而我又进行了一些调整(都位于这个和下个样例中),并新增了一些注释(对代码的作用进行了详细的解释)。

打开human_activity_reco.py文件,来看一下下面这段代码:

2-6行是引入包。对于今天这份教程,你需要安装OpenCV4和imutils。如果你没有安装OpenCV的话,利用pip install opencv指令来进行安装。

pip install opencv

https://www.pyimagesearch.com/2018/09/19/pip-install-opencv/

10-16行来解析指令行参数
  • --model :训练人类活动识别模型的路径。

  • --classes :活动识别类别标签文档的路径。

  • --input 一个用于存放输入视频文件的可选路径。这个参数并没有包括在命令行之内,你的网络是想头也可以在这里被调用。

从这里开始我们来执行初始化:

第21行是加载文本文件中的类别标签。

第22和23行定义采样持续时长(用于分类的帧数)和采样尺寸(每一帧的空间维度大小)。

接下来,我们将会加载并初始化人类活动识别模型:

第27行利用OpenCV的DNN模块来读取PyTorch中预训练的人类活动识别模型。

第31行是对我们的视频流进行实例化,或者是选择一个视频文件,或者是使用网络摄像头。

我们现在准备开始对帧图像进行循环,并执行人类活动识别

第34行开始循环我们的帧图像,其中帧的批处理将会经过神经网络(第37行)。

第40-53行用于从我们的视频流中构建帧的批处理。第52行将对每一帧图像调整尺寸至400像素宽,而且保持原长宽比不变。

让我们创建自己的输入帧的二进制对象blob,我们此后把它交给人类活动识别卷积网络来处理:

第56-60行是从输入帧列表中创建二进制blob对象。

请注意我们用了blobFromImages (复数形式),而不是blobFromImage (单数形式)作为函数——原因是我们构建了一个多幅图片的批次来进入人类活动识别网络,从而获取了时空信息。

如果你在代码中插入一行 print(blob.shape)的指令,你会注意到这个blob的维度是这样的:

(1, 3, 16, 112, 112)

让我们对这组维度有一个更清楚的了解:
  • 1:批次维度。我们只有单个数据点经过网络(“单个数据点”在这里代表着N帧图像经过网络只为了获得单个类别)。

  • 3:输入帧图像的通道数。

  • 16: 每一个blob中帧图像的总数量。

  • 112(第一个):帧图像的高度。

  • 112(第二个):帧图像的宽度。

至此,我们已经做好了执行人类活动识别推断的准备,然后在给每一帧图像标注上预测的标签,并将预测结果展示在屏幕上:

第64和65行将blob通过网络,获得输出列表(预测结果)。

随后我们选取最高的预测结果作为这个blob的标签(第66行)。

利用这个标签,我们可以抽取出帧图像列表中每个帧图像的预测结果(69-73行),显示输出帧图像,直到按下q键时就打破循环并退出。

一个利用双队列(Deque)数据结构的人类活动实现的替代品

在上一章节关于的人类活动识别中,你从会注意到这几行代码:

这一实现意味着:
  • 程序会去从我们的输入视频中读取全部SAMPLE_DURATION帧数的图像。

  • 程序会将所有帧图像输入到人类活动识别模型中来获得输出。

  • 接着程序会读取另外一部分SAMPLE_DURATION帧数的图像,然后继续重复这个过程。

因此,我们的程序实现并不是一个移动的预测。

与之相反,它只是简单地抓取一个样本的帧图像,然后进行分类,然后再去处理下一批次。上一批次的任意一帧图像都是被丢弃的。

我们之所以这样做是为了提高处理速度。

如果我们给每一帧单独分类的话,那我们执行脚步的时间就会被拉长。

这说明,通过deque数据结构来进行移动帧图像预测可以获得更好的结果,因为它不会放弃前面全部的帧图像——移动帧图像预测只会丢弃列表中最早进入的帧图像,为那新到的帧图像腾出空间。

为了更好的展示为什么这个问题会与推断速度相关,让我们设想一个含有N帧图像的视频文件:
  • 如果我们用移动帧图像预测,我们进行N次分类,即每1帧图像都进行1次(当然是等deque数据结构被填满时)。

  • 如果我们不用移动图像预测,我们只需要进行 N /SAMPLE_DURATION次分类,这会显著地缩短程序执行一个视频流的总时间。

图4:移动预测(蓝色)利用一个完全填充的FIFO队列窗口来进行预测

批次预测(红色)不需要一帧一帧地移动。移动预测需要更多的计算力,但对于利用OpenCV深度学习的人类活动识别来说会有更好的效果。

OpenCV的这一dnn模块并不被大多数GPU(包括英伟达的GPU)所支持,我建议你不要对于大多数应用来说还是不要使用移动帧预测。

在今天这篇教程的.zip文件中,你会找到一个名为human_activity_reco_deque.py的文件,这一文件包括一个利用移动帧预测的人类活动识别实现。

这一个脚本与上一个非常相似,我把它放在这里是让你去尝试一下:

引入的库与之前是完全相同的,除了需要再加上Python中collections 模块的deque 实现(第二行)。

在第28行,我们初始化了一个FIFO帧队列,其中最大的长度等于我们的采样时长。我们的“先进先出”(FIFO)队列将会自动弹出最先进入的帧并接收新的帧。我们针对帧队列进行移动推断。

其余所有的代码都是相同的,接下来让我们来检查一下处理帧图像的循环:

第41-57行与我们之前的脚本是不一样的。

在上一个版本的脚本中,我们抽取了一个带有SAMPLE_DURATION数量帧的一个批次,然后再在这个批次上进行推断。

在这个脚本中,我们依旧是以批次为单位进行推断,但现在是移动批次。不同点就在我们在第52行把帧图像放入到了FIFO队列里。如上文介绍,这个队列拥有maxlen 个单位的采样时长,而且队列的头部永远是我们的视频流的当前帧。一旦这个队列被填满,旧的帧图像就会被这个FIFO双端队列实现自动弹出。 

这个移动实现的结果就是一旦当队列被填满,每一个给出的帧图像(对于第一帧图像来说例外)就会被“触碰”(被包含在移动批次里)一次以上。这个方法的效率要低一些;但是它却能获得更高的活动识别准确率,特别是当视频或现场的活动周期性改变时。

第56和57使得我们的帧队列在做出任何推断之前,把帧对列填充好。(例如在图4蓝色区域的前16帧所显示的)。

一旦这个队列被填满,我们将可以执行一个移动的人类活动识别预测:

这一段代码块包含的每一行代码与我们之前的脚本是相同的,在这里我们进行了以下操作:
  • 从我们的帧队列中创建了一个blob。

  • 进行了推断,并获得了blob中概率最高的预测。

  • 用平均移动队列所生成的人类活动识别标签对当前帧图像进行注释和显示。

  • 一旦按下q键,程序将会退出。

人类活动识别在实际应用中的结果

让我们看看人类活动识别在实际应用中的结果。

在这里,打开terminal,执行以下命令:

请注意我们的人类活动识别模型要求的OpenCV最低版本是4.1.2.

如果你使用的OpenCV版本过低,那么就会收到以下报错信息:

如果你收到以上信息,说明你需要更新你的OpenCV版本至4.1.2以上。

下面这个例子就是我们的模型正确地给这段视频打上“瑜伽”的标签。

请注意我们的模型在识别时对预测是“瑜伽”还是“拉伸腿部”犹豫不决——当你在做下犬式姿势时,这两个动作术语从技术层面来看都是正确的。从定义上来讲,你在做瑜伽的同时,也是在拉伸腿部。

在下一个样例中,人类活动识别模型正确地预测出了这是在做“滑板运动”。

你可以看到模型也会把这个活动预测为“跑酷”。滑滑板的人在栏杆上跳跃,这很像是跑酷者可能的动作。

有人饿了吗?

如果谁饿了,一定会对这个“做披萨”感兴趣:

但在你吃披萨前,请确保你已经“洗手”:

如果你沉浸于“喝啤酒”,你最好注意一下饮酒量,酒吧侍者有可能会把你灌醉:

你可以看出,我们的人类活动识别模型可能不够完美,但是考虑到本技术上的简单性(只是将ResNet的2D输入改为3D),它的表现还是不错的。

人类活动识别问题还远远没有解决,但在深度学习卷积神经网络的帮助下,我们已经朝这个方向迈出了一大步。

总结

在这篇教程中告诉你如何用OpenCV深度学习来实现人类活动识别

为了完成这一任务,我们借助了Kinetics数据集对人类活动识别模型进行了预训练,这一数据集包含400-700种人类活动(取决于你使用的数据集的版本)和超过300,000个视频剪辑。

我们使用的模型是带有变动的ResNet, 改动的方面是用3D核函数代替了原本的2D滤镜,使得模型具有了可用于活动识别的时间维度成分。

想要了解更多,你可以阅读Hara等人在2018年发表的论文《Can Spatiotemporal 3D CNNs Retrace the History of 2D CNNs and ImageNet》

最后,我们用OpenCV和Hara等人的在PyTorch上的实现OpenCV的dnn模型,生成了人类活动识别模型。

基于我们所取得的结果,我们可以看出这个模型可能不够完美,但是表现还是不错的。

原文标题:
Human Activity Recognition with OpenCV and Deep Learning
原文链接:
https://www.pyimagesearch.com/2019/11/25/human-activity-recognition-with-opencv-and-deep-learning/
THU数据派
THU数据派

THU数据派"基于清华,放眼世界",以扎实的理工功底闯荡“数据江湖”。发布全球大数据资讯,定期组织线下活动,分享前沿产业动态。了解清华大数据,敬请关注姐妹号“数据派THU”。

工程深度学习OpenCV
4
相关数据
深度学习技术

深度学习(deep learning)是机器学习的分支,是一种试图使用包含复杂结构或由多重非线性变换构成的多个处理层对数据进行高层抽象的算法。 深度学习是机器学习中一种基于对数据进行表征学习的算法,至今已有数种深度学习框架,如卷积神经网络和深度置信网络和递归神经网络等已被应用在计算机视觉、语音识别、自然语言处理、音频识别与生物信息学等领域并获取了极好的效果。

核函数技术

核函数包括线性核函数、多项式核函数、高斯核函数等,其中高斯核函数最常用,可以将数据映射到无穷维,也叫做径向基函数(Radial Basis Function 简称 RBF),是某种沿径向对称的标量函数。最常应用于SVM支持向量机中

参数技术

在数学和统计学裡,参数(英语:parameter)是使用通用变量来建立函数和变量之间关系(当这种关系很难用方程来阐述时)的一个数量。

神经网络技术

(人工)神经网络是一种起源于 20 世纪 50 年代的监督式机器学习模型,那时候研究者构想了「感知器(perceptron)」的想法。这一领域的研究者通常被称为「联结主义者(Connectionist)」,因为这种模型模拟了人脑的功能。神经网络模型通常是通过反向传播算法应用梯度下降训练的。目前神经网络有两大主要类型,它们都是前馈神经网络:卷积神经网络(CNN)和循环神经网络(RNN),其中 RNN 又包含长短期记忆(LSTM)、门控循环单元(GRU)等等。深度学习是一种主要应用于神经网络帮助其取得更好结果的技术。尽管神经网络主要用于监督学习,但也有一些为无监督学习设计的变体,比如自动编码器和生成对抗网络(GAN)。

卷积神经网络技术

卷积神经网路(Convolutional Neural Network, CNN)是一种前馈神经网络,它的人工神经元可以响应一部分覆盖范围内的周围单元,对于大型图像处理有出色表现。卷积神经网路由一个或多个卷积层和顶端的全连通层(对应经典的神经网路)组成,同时也包括关联权重和池化层(pooling layer)。这一结构使得卷积神经网路能够利用输入数据的二维结构。与其他深度学习结构相比,卷积神经网路在图像和语音识别方面能够给出更好的结果。这一模型也可以使用反向传播算法进行训练。相比较其他深度、前馈神经网路,卷积神经网路需要考量的参数更少,使之成为一种颇具吸引力的深度学习结构。 卷积网络是一种专门用于处理具有已知的、网格状拓扑的数据的神经网络。例如时间序列数据,它可以被认为是以一定时间间隔采样的一维网格,又如图像数据,其可以被认为是二维像素网格。

准确率技术

分类模型的正确预测所占的比例。在多类别分类中,准确率的定义为:正确的预测数/样本总数。 在二元分类中,准确率的定义为:(真正例数+真负例数)/样本总数

OpenCV技术

OpenCV的全称是Open Source Computer Vision Library,是一个跨平台的计算机视觉库。OpenCV是由英特尔公司发起并参与开发,以BSD许可证授权发行,可以在商业和研究领域中免费使用。OpenCV可用于开发实时的图像处理、计算机视觉以及模式识别程序。

查询技术

一般来说,查询是询问的一种形式。它在不同的学科里涵义有所不同。在信息检索领域,查询指的是数据库和信息系统对信息检索的精确要求

批次技术

模型训练的一次迭代(即一次梯度更新)中使用的样本集。

图像分类技术

图像分类,根据各自在图像信息中所反映的不同特征,把不同类别的目标区分开来的图像处理方法。它利用计算机对图像进行定量分析,把图像或图像中的每个像元或区域划归为若干个类别中的某一种,以代替人的视觉判读。

深度神经网络技术

深度神经网络(DNN)是深度学习的一种框架,它是一种具备至少一个隐层的神经网络。与浅层神经网络类似,深度神经网络也能够为复杂非线性系统提供建模,但多出的层次为模型提供了更高的抽象层次,因而提高了模型的能力。

活动识别技术

活动识别旨通过对代理人的行为和环境条件的一系列观察来识别一个或多个代理人的行为和目标。

暂无评论
暂无评论~