-
对于每个帧,通过 CNN 传递帧
-
单独和_独立**地_对每个帧进行分类
-
选择具有最大相应概率的标签
-
标记帧并将输出帧写入磁盘
不过,这种方法存在问题 - 如果您曾经尝试将简单的图像分类应用于视频分类,您可能会遇到某种**“预测闪烁”,**如本节顶部视频中所示。请注意,在这个可视化中,我们看到我们的 CNN 在两个预测之间移动:"足球"和正确的标签"weight_lifting"。
视频显然是举重,我们希望我们的整个视频被贴上这样的标签 - 但我们怎样才能防止CNN在这两个标签之间"闪烁"?
一个简单而优雅的解决方案是利用滚动预测平均值。
我们的算法现在变成:
-
在视频文件中的所有帧上循环
-
对于每个帧,通过 CNN 传递帧
-
从 CNN 获取预测
-
保留最后_K_预测的列表
-
计算最后_K_预测的平均值,并选择具有最大相应概率的标签
-
标记帧并将输出帧写入磁盘
此算法的结果可以在这篇文章的顶部的视频中看到 - 注意预测闪烁是如何消失,整个视频剪辑被正确标记!
在本教程的其余部分,您将学习如何实现此算法的视频分类与 Keras。
体育分类数据集
**图1:**由GitHub 用户使用Google 图片搜索策划的体育数据集"无足小视"。我们将使用此图像数据集与 Keras 进行视频分类。(图片来源)
我们今天在这里使用的数据集用于体育/活动分类。数据集由阿努巴夫·迈蒂策划,从谷歌图片下载照片(您也可以使用必应)为以下类别:
-
游泳
-
羽毛球
-
摔跤
-
奥运射击
-
蟋蟀
-
足球
-
网球
-
曲棍球
-
冰球
-
卡巴迪
-
WWE
-
体育馆
-
举重
-
排球
-
乒乓球
-
棒球
-
一级方程式
-
摩托 GP
-
棋
-
拳击
-
击剑
-
篮球
为了节省时间、计算资源,并演示实际视频分类算法(本教程的实际点),我们将对运动类型数据集的子集进行培训:
-
足球(即足球):799张图片
-
网球: 718 图片
-
举重: 577 图像
让我们继续下载我们的数据集!
项目结构
项目结构如下:
$ tree --dirsfirst --filelimit 50
.
├── Sports-Type-Classifier
│ ├── data
│ │ ├── football [799 entries]
│ │ ├── tennis [718 entries]
│ │ └── weight_lifting [577 entries]
├── example_clips
│ ├── lifting.mp4
│ ├── soccer.mp4
│ └── tennis.mp4
├── model
│ ├── activity.model
│ └── lb.pickle
├── output
├── plot.png
├── predict_video.py
└── train.py
我们的训练图像数据位于 Sports-Type-Classifier/data/ 目录中,按类别组织。
我从 YouTube 中为我们提取了三个 example_clips/ 来测试我们的模型。三个剪辑的积分位于“Keras 视频分类结果”部分的底部。
我们的分类器文件位于 model/ 目录中。包括 activity.model(经过训练的 Keras 模型)和 lb.pickle(我们的标签二值化器)。
一个空的 output/ 文件夹是我们将存储视频分类结果的位置。
我们将在今天的教程中介绍两个 Python 脚本:
-
train.py :一个 Keras 训练脚本,它抓取我们关心的数据集类图像,加载 ResNet50 CNN,并应用 ImageNet 权重的转移学习/微调来训练我们的模型。训练脚本生成/输出三个文件:
-
model/activity.model :基于 ResNet50 的微调分类器,用于识别运动。
-
model/lb.pickle :包含我们独特的类标签的序列化标签二值化器。
-
plot.png :准确率/损失训练历史图。
-
predict_video.py :从 example_clips/ 加载输入视频,然后使用今天的滚动平均方法对视频进行理想的分类。
实施我们的 Keras 培训脚本
让我们继续实施我们的训练脚本,用于训练Keras CNN来识别每一项体育活动。
打开train.py文件并插入以下代码:
set the matplotlib backend so figures can be saved in the background
import matplotlib
matplotlib.use(“Agg”)
import the necessary packages
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras.layers import AveragePooling2D
from tensorflow.keras.applications import ResNet50
from tensorflow.keras.layers import Drop