{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 第15章 动作识别"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 15.1 简介"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<!-- 向量 小写黑体\n",
    "矩阵 大写黑体\n",
    "标量变量 小写\n",
    "常量 大写\n",
    "集合 mathcal\n",
    "转置 \\mathsf\n",
    "空间 mathbb -->\n",
    "在之前的章节中，我们已经学习了针对图像的\\\"十八般武艺\\\"，能够检测目标、分割物体甚至估计人体姿态。但是真实世界中，万事万物都是在运动的，因此就需要掌握对视频流的\\\"武技\\\"。在这一章中我们将尝试理解这个运动的世界，具体来说，我们将学习人体动作识别（human action recognition）。人体动作识别，顾名思义，是指识别视频中人类的动作，从而可以推断人物的意图和状态，为视频内容的理解提供重要信息。\n",
    "例如，在视频监控领域，人体动作识别可用于检测犯罪和安全事件；在体育赛事领域，人体动作识别可以用来分析运动员的技术和战术；在娱乐和广告领域，人体动作识别可以用来分析观众的反应和参与度。\n",
    "\n",
    "用数学语言描述人体动作识别任务就是：预定义$N$个动作标签$\\mathcal{L} = \\{l_1, l_2, ..., l_N\\}$，定义序列空间$\\mathbb{S}$，给定数据集$\\mathcal{D} = \\{(\\boldsymbol{S}^{(n)},l^{(n)})\\}_{n=1}^N$，其中$\\boldsymbol{S}^{(n)}\\in \\mathbb{S}$是数据集中的第$n$个序列，$l^{(n)}$是这个序列对应的动作标签。人体动作识别任务是从$\\mathcal{D}$中学习得到一个从序列空间到人体动作标签空间的映射$f$，从而给定任意一段测试序列$\\boldsymbol{S}$，可以用学习得到的映射函数$f$预测其标签：$l=f(\\boldsymbol{S})$。从数学定义中可以发现，人体动作识别本质上是一个分类任务，如图 15-1 所示。\n",
    "\n",
    "<center>\n",
    "    <img style=\"border-radius: 0.3125em;\" \n",
    "    src=\"https://pic4.zhimg.com/80/v2-8d21a0d705c5736bcf65b95e519ef347_720w.webp\n",
    "\" width=600>\n",
    "    <br>\n",
    "    <div style=\"color:orange; \n",
    "    display: inline-block;\n",
    "    color: #999;\n",
    "    padding: 2px;\">图15-1 动作识别是一个对视频的分类任务（插图来自参考文献[1]）</div>\n",
    "</center>\n",
    "\n",
    "在这一章中我们将首先介绍数据集与评测指标，然后再动手学一些常用的动作识别方法。\n",
    "<!-- \n",
    "随着近年来互联网的发展，特别是移动互联网技术的发展，内容的主流形式已经从纯文本时代逐渐发展到了图文时代，再到现在的视频和直播时代。与简单的文字和图像内容相比，视频内容更加丰富，更具吸引力。根据中国互联网络信息中心（CNNIC）第 47 次《中国互联网络发展状况统计报告》，截至 2020 年 12 月，中国网民规模已达 9.89 亿人，其中网络视频（包括短视频）用户规模达到 9.27 亿人，占网民总数的 93.7%，而短视频用户规模则为 8.73 亿人，占网民总数的 88.3%。由于人们使用视频的需求越来越多，传输视频的速度也越来越快，存储视频的空间也越来越大，视频数据也日益增长。人体动作识别技术可以帮助我们快速浏览和筛选视频中的内容，为视频的管理、分析和处理提供有效的工具。例如，在视频监控领域，人体动作识别可用于检测犯罪和安全事件；在体育赛事领域，人体动作识别可以用来分析运动员的技术和战术；在娱乐和广告领域，人体动作识别可以用来分析观众的反应和参与度。\n",
    "\n",
    "人体动作识别存在许多挑战，比如：\n",
    "* 视频本质上是一个连续的序列（而不是静态图像），因此需要考虑如何表示在图像序列中编码的运动。\n",
    "* 人体动作的多样性很大，包括人物的大小、位置、角度、视角、姿势等，因此需要考虑如何处理人体动作的多样性。\n",
    "* 人体动作常常受到遮挡、模糊、噪声等因素的影响，因此需要考虑如何处理视频中的干扰。\n",
    "* 人体动作的时间和空间信息也是非常重要的，因此需要考虑如何处理时间和空间信息。\n",
    "\n",
    "尽管存在这些挑战，但人体动作识别仍是一个活跃的研究领域，并且有望在未来取得更大的进展。 -->"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 15.2 数据集和度量"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "本节将介绍动作识别常用的数据集以及度量。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 15.2.1 数据集"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "目前常用的人体动作估计的数据集包括：\n",
    "1. HMDB51 $^{[2]}$：HMDB51数据集于2011年发布。它主要由电影中收集的视频片段组成，其中也包括来自Prelinger档案、YouTube和谷歌视频的一小部分公共数据集。数据集中包含6766个片段，分为51个动作类别，每个动作类别至少包含101个片段。该数据集有3个正式的拆分版本。\n",
    "1. Sports1M $^{[3]}$：Sports1M于2014年发布，是第一个规模较大的视频动作数据集，由超过100万个YouTube视频组成，其中注明了487种运动类别。由于类别的粒度较小，其类别间的差异较小。\n",
    "1. YouTube-8M $^{[4]}$：YouTube-8M数据集于2016年发布，是迄今为止规模最大的视频数据集。它包含约800万个YouTube视频，总计超过50万小时的视频，并用4800个动作类进行注释。每个视频都由YouTube视频注释系统使用一个或多个标签进行注释。该数据集按70：20：10的比例分为训练、验证和测试三部分。该数据集的验证集还扩展了人工验证的片段标注，以提供时间定位信息。\n",
    "1. DeepMind Kinetics human action dataset：Kinetics家族是目前应用最广泛的基准数据集。2017年推出的Kinetics-400 $^{[5]}$ 包含约24万个训练和2万个验证视频，由400个人类动作类别中片段而成，每个视频长度约为10秒。随着时间的推移，Kinetics家族一直在不断扩大，2018年推出的Kinetics-600 $^{[6]}$ 包含49万多个视频，2019年推出的Kinetics-700 $^{[7]}$ 包含65万多个视频。\n",
    "1. AVA $^{[8]}$：AVA是于2017年推出的首个大规模时空行为检测数据集。它包含430个15分钟的视频片段，每个关键帧都提供了标注，共有80个原子动作标签。原子动作是指基本的、不可再分的视觉动作或行为。与复合或更复杂的行为相反，原子动作是构成这些复合行为的基本组件。为了在更多样化的视觉场景中提供具有空间定位的动作标签，研究人员在Kinetics-700视频上提供了AVA动作标签，构建了AVA-Kinetics $^{[9]}$数据集。这导致整体标注数量几乎增加了一倍，而独特的视频数量增加了超过500倍。\n",
    "1. AViD $^{[10]}$：AViD数据集于2020年发布，用于匿名动作识别。它包含41万个训练视频和4万个的测试视频。每个视频片段的持续时间在3-15秒之间，总共有887个动作类。在数据收集过程中，作者尝试从不同国家和地区收集数据，以解决数据偏差的问题。此外，他们还删除了面部身份信息，以保护视频制作者的隐私。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 15.2.2 评测指标"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "在人体动作识别任务中，常用的评测指标包括：\n",
    "\n",
    "1. 精度（accuracy）：表示预测正确的样本数占所有样本数的比例，是评测分类器性能的常用指标之一。\n",
    "    $$Accuracy = \\frac{TP + TN}{TP + TN + FP + FN}$$\n",
    "\n",
    "    其中，真阳性（TP）表示预测正确的正样本数，真阴性（TN）表示预测正确的负样本数，假阳性（FP）表示预测错误的正样本数，假阴性（FN）表示预测错误的负样本数。\n",
    "1. 命中率（Hit@ $k$）：表示在前k个预测结果中有多少个正确的。命中率越高，说明模型的预测效果越好。\n",
    "1. 平均精度（mAP）：表示所有类别的精度的平均值，我们在第12章介绍过，这里不再赘述。平均精度越高，说明模型的整体预测效果越好。\n",
    "1. 分段 F1 得分（F1@$k$）：表示在前$k$个预测结果中的 F1 得分。F1 得分是精确率和召回率的调和平均值，反映了模型的精度和召回能力。\n",
    "    $$F1@k = \\frac{2 \\cdot precision@k \\cdot recall@k}{precision@k + recall@k}$$\n",
    "\n",
    "    其中，precision@$k$ 表示在前$k$个预测结果中的查准率，recall@$k$ 表示在前$k$个预测结果中的查全率。\n",
    "<!-- \n",
    "    精确率（Precision）的公式如下：\n",
    "\n",
    "    $$Precision = \\frac{TP}{TP + FP}$$\n",
    "\n",
    "    召回率（Recall）的公式如下：\n",
    "\n",
    "    $$Recall = \\frac{TP}{TP + FN}$$\n",
    "\n",
    "    其中，TP（True Positive）表示预测正确的正样本数，TN（True Negative）表示预测正确的负样本数，FP（False Positive）表示预测错误的正样本数，FN（False Negative）表示预测错误的负样本数。 -->"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 15.3 人体动作识别的发展"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "接下来我们将学习人体动作识别的发展历程，以及如何使用深度学习来提升人体动作识别的精度。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 15.3.1 传统方法\n",
    "为了从序列中识别出人体动作，人们进行了大量的研究。早在2013年，Heng Wang等人提出了密集轨迹（Dense Trajectories, DT）$^{[11]}$ 和改进密集轨迹（improved Dense Trajectories, iDT）$^{[12]}$ 方法。如图15-2所示，密集轨迹方法通过利用光流（也就是图像中像素的运动，将在第18章进行介绍）在视频中检测运动轨迹，并在此基础上提取特征。而改进密集轨迹方法则在密集轨迹的基础上进行改进，通过补偿相机运动并使用额外的检测器检测人来减少人对相邻帧之间投影矩阵估计的影响。改进密集轨迹是在深度学习方法之前效果最佳的经典方法之一。然而，这种方法的缺陷在于特征维度高（特征比原始视频更大），速度较慢。在实际应用中，虽然早期深度学习方法与改进密集轨迹结合仍能取得一定的效果提升，但随着深度学习方法性能的提升，改进密集轨迹已经逐渐淡出视野。\n",
    "<center>\n",
    "    <img style=\"border-radius: 0.3125em;\" \n",
    "    src=\"https://pic4.zhimg.com/v2-8fc91c9c7e34f33ab22b39e795fcbda3_r.jpg\" width=700>\n",
    "    <br>\n",
    "    <div style=\"color:orange; \n",
    "    display: inline-block;\n",
    "    color: #999;\n",
    "    padding: 2px;\">图15-2 密集轨迹方法的流程图（插图源自参考文献[11]）</div>\n",
    "</center>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 15.3.2 逐帧处理融合方法\n",
    "随着深度学习的兴起，人们拥有了更强的特征提取手段，从而也涌现了一大批基于深度学习的人体动作识别算法。Andrej Karpathy等人 $^{[3]}$ 提出把视频看作一系列图像的集合，每帧图像单独提取特征，再融合它们的深度特征。具体来讲，他们将视频划分成很多固定长度的片段（clip， 一般每16帧为一个片段），并设计了多种融合方法。\n",
    "<center>\n",
    "    <img style=\"border-radius: 0.3125em;\" \n",
    "    src=\"https://pic4.zhimg.com/80/v2-be51d2293cdcd7711818d93dfbe44dcf_720w.jpg\" width=600>\n",
    "    <br>\n",
    "    <div style=\"color:orange; \n",
    "    display: inline-block;\n",
    "    color: #999;\n",
    "    padding: 2px;\">图15-3 不同的融合方法（插图源自参考文献[3]）</div>\n",
    "</center>\n",
    "如图 15-3 所示，Andrej Karpathy等人尝试了多种融合方法:\n",
    "\n",
    "1. 单帧（single frame）：主要用于理解静态图像对动作识别准确度的贡献。随机地从视频中任意选取一帧，将视频分类转换成图像分类。\n",
    "1. 晚融合（late fusion）：视频前后相隔 15 帧的两帧会先经过同一个卷积神经网络进行特征提取，然后再在最后的全连接层进行融合。这种方法被称为晚融合，因为在进行卷积之前不会考虑时序信息，只有在全连接层进行融合时才能够接收到时序信息。因此，此方法通过比较两帧的输出来计算整体运动特性。\n",
    "1. 早融合（early fusion）：使用连续的 $T$ 帧进行预测，在第一个卷积层前对其进行融合。由于在卷积之前进行融合，因此称为早融合。在实现中，第一个卷积层上的滤波器被扩展为11×11×3×$T$像素。 $T$ 代表融合的帧数，在较高分辨率的位置进行融合。由于在较高分辨率位置进行融合，卷积层可以更清晰地捕捉动作的方向和速度，但语义信息较弱。\n",
    "1. 慢融合（slow fusion）：将时间信息逐步融合到整个网络中的平衡混合方法。在这种方法中，使用连续的10帧，将这些帧分为4个部分，每部分使用前融合式卷积进行处理。之后将这4部分按时序分为两组进行类似的卷积处理，最终将这两组输出进行融合。这个过程逐渐扩大了网络的感知范围，从4帧到8帧，再到10帧。\n",
    "\n",
    "经过最终的评估，作者发现慢融合方法的表现显著优于其他方法。这是因为它通过融合更多的帧来保留更丰富的时空特征。然而，作者也在文中提及，当输入变为单帧时，由单个视频帧提供的网络的性能同样良好（59.3% VS 60.9%）。这一观察可能表明，网络所学习到的特征并不能很好地表征运动。\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 15.3.3 时序融合\n",
    "这类方法先使用卷积网络提取每帧图像的特征，之后用循环序列模型等挖掘它们之间的时序关系。Jeff Donahue等人 $^{[13]}$ 提出了如图 15-4 的网络结构。这个架构首先利用卷积神经网络逐帧提取特征，然后将按时序排列的逐帧特征输入一系列递归神经网络，如图中所示的长短期记忆（long short-term memory, LSTM）神经网络，最终得到一个可变长度的预测结果。\n",
    "<center>\n",
    "    <img style=\"border-radius: 0.3125em;\" \n",
    "    src=\"https://pic2.zhimg.com/v2-c741a642b798086965bde9e692883e05_r.jpg\" width=400>\n",
    "    <br>\n",
    "    <div style=\"color:orange; \n",
    "    display: inline-block;\n",
    "    color: #999;\n",
    "    padding: 2px;\">图15-4 时序融合方法（插图源自参考文献[13]）</div>\n",
    "</center>\n",
    "这类方法考虑了帧与帧之间的时序关系，能够更好地学习时间序列与卷积特征表示之间的联系。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 15.3.4 三维卷积\n",
    "在 15.3.1 节中我们提到慢融合方法的表现显著优于其他方法。\n",
    "这里让我们回顾一下慢融合方法。慢融合通过融合多个时间段内的二维图像特征作为这段时间的时空特征，而这一操作可以通过三维卷积的方式进行替代，因此很快三维卷积就在人体动作识别领域风靡了起来。\n",
    "三维卷积的工作原理类似于二维卷积，其输入是一个视频序列，输出是一个特征图，但是它在空间维度和时间维度上都有卷积核进行卷积操作。具体来说，三维卷积会使用一个三维的卷积核（包含长、宽、时间三维）在视频序列上进行卷积操作，从而提取视频中的时空特征，如图15-5所示。在传统的二维卷积中，网络只能识别图像中的局部特征，而三维卷积则能够捕捉视频序列中的时间上变化，从而更好地识别人体动作。\n",
    "<center>\n",
    "    <img style=\"border-radius: 0.3125em;\" \n",
    "    src=\"https://pic4.zhimg.com/80/v2-ae0f6e91808a90c71f5721b31b1a4a4b_1440w.webp\" width=900>\n",
    "    <br>\n",
    "    <div style=\"color:orange; \n",
    "    display: inline-block;\n",
    "    color: #999;\n",
    "    padding: 2px;\">图15-5 三维卷积示意图</div>\n",
    "</center>\n",
    "\n",
    "Du Tran等人 $^{[14]}$ 将视频序列分成固定长度的片段，将每个片段看作是包含时间与空间维度的三维图像，然后使用三维卷积核在时空维度上进行卷积操作，通过多层三维卷积网络对视频序列进行特征提取。\n",
    "除此之外，为了提高网络性能，作者还使用了一些额外的技巧，例如使用预训练卷积网络来进行特征提取，使用了可调节的三维卷积核来提高网络的鲁棒性，并在这些层之间连接全连接层进行最终的分类。\n",
    "\n",
    "由于三维卷积能更好地捕捉动作变化，因此在识别人体动作上能够取得较好的效果。此外，也有许多人沿着这个思路将池化的融合替换成了循环序列模型 $^{[15]}$，但本文不再对此进行详细讨论。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "这里展示一个标准的三维卷积："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2023-04-11T07:31:04.787604Z",
     "iopub.status.busy": "2023-04-11T07:31:04.787213Z",
     "iopub.status.idle": "2023-04-11T07:31:04.950726Z",
     "shell.execute_reply": "2023-04-11T07:31:04.949574Z",
     "shell.execute_reply.started": "2023-04-11T07:31:04.787563Z"
    }
   },
   "outputs": [],
   "source": [
    "import torch.nn as nn\n",
    "\n",
    "class C3D(nn.Module):\n",
    "    \"\"\"\n",
    "    C3D，Convolution 3D，即三维卷积\n",
    "    \"\"\"\n",
    "\n",
    "    def __init__(self):\n",
    "        super(C3D, self).__init__()\n",
    "        # 注意到核函数为三维，符合三维卷积的要求\n",
    "        self.conv1 = nn.Conv3d(3, 64, kernel_size=(3, 3, 3), \n",
    "                               padding=(1, 1, 1))\n",
    "        self.pool1 = nn.MaxPool3d(kernel_size=(1, 2, 2), \n",
    "                                  stride=(1, 2, 2))\n",
    "\n",
    "        self.conv2 = nn.Conv3d(64, 128, kernel_size=(3, 3, 3), \n",
    "                               padding=(1, 1, 1))\n",
    "        self.pool2 = nn.MaxPool3d(kernel_size=(2, 2, 2), \n",
    "                                  stride=(2, 2, 2))\n",
    "\n",
    "        self.conv3a = nn.Conv3d(128, 256, kernel_size=(3, 3, 3), \n",
    "                                padding=(1, 1, 1))\n",
    "        self.conv3b = nn.Conv3d(256, 256, kernel_size=(3, 3, 3), \n",
    "                                padding=(1, 1, 1))\n",
    "        self.pool3 = nn.MaxPool3d(kernel_size=(2, 2, 2), \n",
    "                                  stride=(2, 2, 2))\n",
    "\n",
    "        self.conv4a = nn.Conv3d(256, 512, kernel_size=(3, 3, 3), \n",
    "                                padding=(1, 1, 1))\n",
    "        self.conv4b = nn.Conv3d(512, 512, kernel_size=(3, 3, 3), \n",
    "                                padding=(1, 1, 1))\n",
    "        self.pool4 = nn.MaxPool3d(kernel_size=(2, 2, 2), \n",
    "                                  stride=(2, 2, 2))\n",
    "\n",
    "        self.conv5a = nn.Conv3d(512, 512, kernel_size=(3, 3, 3), \n",
    "                                padding=(1, 1, 1))\n",
    "        self.conv5b = nn.Conv3d(512, 512, kernel_size=(3, 3, 3), \n",
    "                                padding=(1, 1, 1))\n",
    "        self.pool5 = nn.MaxPool3d(kernel_size=(2, 2, 2), \n",
    "                              stride=(2, 2, 2), padding=(0, 1, 1))\n",
    "\n",
    "        self.fc6 = nn.Linear(8192, 4096)\n",
    "        self.fc7 = nn.Linear(4096, 4096)\n",
    "        self.fc8 = nn.Linear(4096, 487)\n",
    "\n",
    "        self.dropout = nn.Dropout(p=0.5)\n",
    "\n",
    "        self.relu = nn.ReLU()\n",
    "        self.softmax = nn.Softmax()\n",
    "\n",
    "    def forward(self, x):\n",
    "\n",
    "        h = self.relu(self.conv1(x))\n",
    "        h = self.pool1(h)\n",
    "\n",
    "        h = self.relu(self.conv2(h))\n",
    "        h = self.pool2(h)\n",
    "\n",
    "        h = self.relu(self.conv3a(h))\n",
    "        h = self.relu(self.conv3b(h))\n",
    "        h = self.pool3(h)\n",
    "\n",
    "        h = self.relu(self.conv4a(h))\n",
    "        h = self.relu(self.conv4b(h))\n",
    "        h = self.pool4(h)\n",
    "\n",
    "        h = self.relu(self.conv5a(h))\n",
    "        h = self.relu(self.conv5b(h))\n",
    "        h = self.pool5(h)\n",
    "\n",
    "        h = h.view(-1, 8192)\n",
    "        h = self.relu(self.fc6(h))\n",
    "        h = self.dropout(h)\n",
    "        h = self.relu(self.fc7(h))\n",
    "        h = self.dropout(h)\n",
    "\n",
    "        logits = self.fc8(h)\n",
    "        probs = self.softmax(logits)\n",
    "\n",
    "        return probs"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "我们将基于C3D实现手势识别。这里我们将直接调用已经完成的代码，你可以在GitHub链接中查看详细的项目，数据来自参考文献[16]。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2023-04-11T07:31:04.953100Z",
     "iopub.status.busy": "2023-04-11T07:31:04.952673Z",
     "iopub.status.idle": "2023-04-11T07:31:05.229727Z",
     "shell.execute_reply": "2023-04-11T07:31:05.228024Z",
     "shell.execute_reply.started": "2023-04-11T07:31:04.953056Z"
    }
   },
   "outputs": [],
   "source": [
    "!git clone https://github.com/GibranBenitez/IPN-hand"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "将链接中提供的预训练模型导入至./report_ipn/模块下，并基于C3D模块对手势进行识别与测试。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2023-04-11T07:31:05.231676Z",
     "iopub.status.busy": "2023-04-11T07:31:05.231267Z",
     "iopub.status.idle": "2023-04-11T07:31:05.497611Z",
     "shell.execute_reply": "2023-04-11T07:31:05.495635Z",
     "shell.execute_reply.started": "2023-04-11T07:31:05.231630Z"
    }
   },
   "outputs": [],
   "source": [
    "!bash run_online_ipn_Clf.sh"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "由于是视频实时监测，在这里我们不展示结果，请感兴趣的同学自行移步至GitHub链接查看。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 15.3.5 双流法\n",
    "在视频理解中，找到合适的方式描述连续帧间的运动关系对于提高视频动作识别性能至关重要。光流恰好是描述物体、场景运动的有效运动表示方法。与RGB图像相比，使用光流的优点在于提供了额外的信息，例如去除静止背景，使学习问题更简单。因此，双流（two-stream）法应运而生。\n",
    "\n",
    "双流法通过使用两个独立的网络，分别提取视频中的空间特征和运动特征，然后将这两种特征融合起来进行动作识别。其中，一个流用来提取视频中的空间特征，通常使用二维卷积网络。它接收视频中的每一帧作为输入，通过卷积层和池化层提取出视频中的空间特征。另一个流则用来提取视频中的运动特征，通常使用光流或三维卷积网络。它接收视频中连续帧间的光流或三维卷积网络，以提取出视频中的运动特征。\n",
    "\n",
    "图 15-6 总结了一些经典方法，图15-6（a）至图15-6（c）分别代表了单帧提取特征并进行融合，三维卷积神经网络和双流网络这几种方法。图15-6（d）代表了融合的方法，将图15-6（c）中加权平均的操作变成了一个三维卷积神经网络来表示。图15-6（e）代表I3D $^{[17]}$ 提出的方案，在每一个分支都采用了三维卷积神经网络，最后进行加权平均。\n",
    "<center>\n",
    "    <img style=\"border-radius: 0.3125em;\" \n",
    "    src=\"https://pic3.zhimg.com/v2-e578b15f647d54c8d8d6aea5e8d6e2de_r.jpg\" width=700>\n",
    "    <br>\n",
    "    <div style=\"color:orange; \n",
    "    display: inline-block;\n",
    "    color: #999;\n",
    "    padding: 2px;\">图15-6 动作识别网络架构图（插图源自参考文献[17]）</div>\n",
    "</center>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<!-- |     | 大臂  |   小臂  | 大腿  | 小腿  |\n",
    "|  :----:  | :----:  | :----:  | :----:  | :----:  |\n",
    "| **LSP**  | 0.56 | 0.38 | 0.78 | 0.71 |\n",
    "| **FLIC**  | 0.8 | 0.75 | 0.71 | 0.5 | -->"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 15.4 小结\n",
    "\n",
    "本章讲解了几种常用的动作识别方法，包括逐帧处理融合方法、时序融合方法、三维卷积、双流法，并学习了三维卷积的原理与构成。回顾我们的动手学旅程，从图像的基础处理到图像以及视频的语义理解，我们都在不停地贴近真实世界，而真实的世界是三维的，因此我们接下来将学习三维视觉，探索计算机视觉算法在三维世界中的应用。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 15.5 习题"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 习题 15.1：C3D的网络结构是怎样的？它是如何从视频中提取特征的？\n",
    "\n",
    "#### 习题 15.2：C3D中的三维卷积操作和二维卷积操作有何不同？三维卷积在处理视频数据时有哪些优势？\n",
    "\n",
    "#### 习题 15.3：C3D在动作识别方面的应用效果如何？它相比于其他动作识别算法有什么优势？\n",
    "\n",
    "#### 习题 15.4：双流法的网络结构是怎样的？两个流分别用于提取什么样的特征？\n",
    "\n",
    "#### 习题 15.5：双流法相比于其他行为识别算法有什么优势？"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 15.6 参考文献\n",
    "\n",
    "[1] ZHU Y, LI X, LIU C, et al. A comprehensive study of deep video action recognition[J]. arXiv preprint arXiv:2012.06567, 2020.\n",
    "\n",
    "[2] KUEHNE H, JHUANG H, GARROTE E, et al. HMDB: a large video database for human motion recognition[C]//2011 International conference on computer vision. IEEE, 2011: 2556-2563.\n",
    "\n",
    "[3] KARPATHY A, TODERICI G, SHETTY S, et al. Large-scale video classification with convolutional neural networks[C]//Proceedings of the IEEE conference on Computer Vision and Pattern Recognition. 2014: 1725-1732.\n",
    "\n",
    "[4] ABU-EL-HAIJA S, KOTHARI N, LEE J, et al. YouTube-8M: A large-scale video classification benchmark[J]. arXiv preprint arXiv:1609.08675, 2016.\n",
    "\n",
    "[5] KAY W, CARREIRA J, SIMONYAN K, et al. The Kinetics human action video dataset[J]. arXiv preprint arXiv:1705.06950, 2017.\n",
    "\n",
    "[6] CARREIRA J, NOLAND E, BANKI-HORVATH A, et al. A short note about Kinetics-600[J]. arXiv preprint arXiv:1808.01340, 2018.\n",
    "\n",
    "[7] CARREIRA J, NOLAND E, HILLIER C, et al. A short note on the Kinetics-700 human action dataset[J]. arXiv preprint arXiv:1907.06987, 2019.\n",
    "\n",
    "[8] GU C, SUN C, ROSS D A, et al. AVA: A video dataset of spatio-temporally localized atomic visual actions[C]//Proceedings of the IEEE conference on Computer Vision and Pattern Recognition. 2018: 6047-6056.\n",
    "\n",
    "[9] LI A, THOTAKURI M, ROSS D A, et al. The AVA-Kinetics localized human actions video dataset[J]. arXiv preprint arXiv:2005.00214, 2020.\n",
    "\n",
    "[10] PIERGIOVANNI A J, RYOO M. AVID dataset: Anonymized videos from diverse countries[J]. Advances in Neural Information Processing Systems, 2020, 33: 16711-16721.\n",
    "\n",
    "[11] WANG H, KLÄSER A, SCHMID C, et al. Dense trajectories and motion boundary descriptors for action recognition[J]. International journal of computer vision, 2013, 103: 60-79.\n",
    "\n",
    "[12] WANG H, SCHMID C. Action recognition with improved trajectories[C]//Proceedings of the IEEE international conference on Computer Vision. 2013: 3551-3558.\n",
    "\n",
    "[13] DONAHUE J, ANNE HENDRICKS L, GUADARRAMA S, et al. Long-term recurrent convolutional networks for visual recognition and description[C]//Proceedings of the IEEE conference on Computer Vision and Pattern Recognition. 2015: 2625-2634.\n",
    "\n",
    "[14] TRAN D, BOURDEV L, FERGUS R, et al. Learning spatiotemporal features with 3D convolutional networks[C]//Proceedings of the IEEE international conference on Computer Vision. 2015: 4489-4497.\n",
    "\n",
    "[15] MONTES A, SALVADOR A, PASCUAL S, et al. Temporal activity detection in untrimmed videos with recurrent neural networks[J]. arXiv preprint arXiv:1608.08128, 2016.\n",
    "\n",
    "[16] BENITEZ-GARCIA G, OLIVARES-MERCADO J, SANCHEZ-PEREZ G, et al. IPN hand: A video dataset and benchmark for real-time continuous hand gesture recognition[C]//2020 25th international conference on pattern recognition (ICPR). IEEE, 2021: 4340-4347.\n",
    "\n",
    "[17] CARREIRA J, ZISSERMAN A. Quo vadis, action recognition? A new model and the Kinetics dataset[C]//Proceedings of the IEEE Conference on Computer Vision and Pattern Recognition. 2017: 6299-6308."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<!-- 目前的困难：\n",
    "1. 姿态估计的精确度问题：由于人体姿态估计系统使用的是多种视觉信息，如果它们不能够准确地追踪到人体的每个部位，那么估计出来的结果也会不准确。\n",
    "1. 尺度不变性问题：尽管现有的人体姿态估计算法可以处理不同尺度的图像，但它们仍然存在尺度不变性问题，即当姿态发生变化时，估计的结果可能会受到影响。\n",
    "1. 光照变化问题：由于光照变化会对视觉信息产生影响，因此人体姿态估计系统可能无法准确地识别不同光照环境下的人体部位。\n",
    "1. 复杂背景问题：复杂的背景可能会干扰人体姿态估计系统的性能，使得它无法准确地识别人体部位。 -->"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
