本博客将重点关注光流,这将通过从标准的sintel数据和自定义舞蹈视频生成光流文件来完成。
NVIDIA flownet2-pytorch
https://github.com/NVIDIA/flownet2-pytorch
Dancelogue linked repo
https://github.com/dancelogue/flownet2-pytorch
这篇博客的目标是:
系统要求
flownet2-pytorch实现设计用于GPU。不幸的是这意味着如果无法访问其中一个,则无法完全关注此博客。为了减轻这个问题,由模型生成的样本的数据被提供,并且允许读者与博客的其余遵循通过。
本教程的其余部分使用ubuntu 18.04和NVIDIA GEFORCE GTX 1080 Ti GPU进行。Docker是必需的,必须启用GPU,这可以使用nvidia-docker软件包完成。
https://github.com/NVIDIA/nvidia-docker
下载代码库和数据集
以下列出了所有需要的代码和数据,以便跟进博客(下载数据已经自动化,因此读者无需手动完成,请参阅“入门”部分):
https://github.com/dancelogue/flownet2-pytorch
http://files.is.tue.mpg.de/sintel/MPI-Sintel-complete.zip
https://dancelogue.s3.amazonaws.com/open_source/datasets/generating-optical-flow-using-flownet-for-human-action-deep-learning-algorithms/000835.flo
https://dancelogue.s3.amazonaws.com/open_source/datasets/generating-optical-flow-using-flownet-for-human-action-deep-learning-algorithms/000835.flo.png
https://dancelogue.s3.amazonaws.com/open_source/datasets/generating-optical-flow-using-flownet-for-human-action-deep-learning-algorithms/sample-video.mp4
https://dancelogue.s3.amazonaws.com/open_source/datasets/generating-optical-flow-using-flownet-for-human-action-deep-learning-algorithms/sample-optical-flow-video.mp4
完成此博客所需的内存空间要求约为32 GB。其原因将在后面解释。
叉子的差异
如上所述,创建了原始flownet2-pytorch的一个分支,这是因为在撰写此博客时,原始存储库在构建和运行docker映像时遇到问题,例如python包版本问题,c库编译问题等。另外,进行了增强,以便更轻松地下载数据集。所做的更改旨在解决这些问题,可以在以下拉取请求中看到
https://github.com/dancelogue/flownet2-pytorch/pull/1/files。
https://github.com/NVIDIA/vid2vid
入门
考虑到这一点,第一件事是从克隆原始存储库的dancelogue分支。然后使用以下命令运行docker脚本:
https://github.com/dancelogue/flownet2-pytorch
bash launch_docker.sh
设置应该花费几分钟之后,它应该将终端上下文更改为docker会话。
接下来是下载相关数据集,可以通过在docker上下文中运行以下命令来实现初始设置所需的所有数据:
bash scripts/download.sh
这会将FlowNet2_checkpoint.pth.tar模型权重下载到模型文件夹,以及将MPI-Sintel数据下载到数据集文件夹。这是必需的,以便按照flownet2-pytorch入门指南中所示的推理示例的说明进行操作。还下载了自定义舞蹈视频以及示例光学流.flo文件。
此博客的其余部分已自动执行,可以通过以下命令运行:
bash scripts/run.sh
运行推理示例
原始推理示例的命令如下:
python main.py --inference --model FlowNet2 --save_flow \
--inference_dataset MpiSintelClean \
--inference_dataset_root /path/to/mpi-sintel/clean/dataset \
--resume /path/to/checkpoints
但是基于fork,这已修改为:
python main.py --inference --model FlowNet2 --save_flow \
--inference_dataset MpiSintelClean \
--inference_dataset_root datasets/sintel/training \
--resume checkpoints/FlowNet2_checkpoint.pth.tar \
--save datasets/sintel/output
分解一下:
https://github.com/dancelogue/flownet2-pytorch/blob/master/datasets.py
运行上述命令会将生成的光流文件保存到datasets/sintel/output/inference/run.epoch-0-flow-field文件夹中。生成的光流文件具有扩展.flo,它们是流场表示。
分析和可视化光流文件
现在已经生成了光流文件,现在是时候分析结构,以便更好地理解结果,并将它们转换为流场颜色编码方案。可以从以下链接下载本节中使用的示例流文件。
https://dancelogue.s3.amazonaws.com/open_source/datasets/generating-optical-flow-using-flownet-for-human-action-deep-learning-algorithms/000835.flo
分析流文件
将光流文件加载到numpy是一个相当简单的过程,可以按如下方式进行:
path = Path('path/to/flow/file/<filename>.flo')
with path.open(mode='r') as flo:
np_flow = np.fromfile(flo, np.float32)
print(np_flow.shape)
上面的语法基于python3,其中文件被加载到缓冲区然后被送入numpy。接下来是尝试理解print语句实现的流文件的基本功能。假设您正在使用提供的示例流文件,这将给出以下结果(786435,)。这意味着对于每个流文件,它包含一个数组中包含786453个元素的数组。单个流文件的内存占用大约为15 MB,即使看起来微不足道,也会非常快速地增加,尤其是在查看具有数千帧的视频时。
在继续之前,需要查看链接中定义的光流规范。关心的是以下内容:
http://vision.middlebury.edu/flow/code/flow-code/README.txt
".flo" file format used for optical flow evaluation
Stores 2-band float image for horizontal (u) and vertical (v) flow components.
Floats are stored in little-endian order.
A flow value is considered "unknown" if either |u| or |v| is greater than 1e9.
bytes contents
0-3 tag: "PIEH" in ASCII, which in little endian happens to be the float 202021.25
(just a sanity check that floats are represented correctly)
4-7 width as an integer
8-11 height as an integer
12-end data (width*height*2*4 bytes total)
the float values for u and v, interleaved, in row order, i.e.,
u[row0,col0], v[row0,col0], u[row0,col1], v[row0,col1], ...
根据以上规范,以下代码将允许正确读取流文件(借用)。
https://github.com/georgegach/flow2image/blob/master/f2i.py
with path.open(mode='r') as flo:
tag = np.fromfile(flo, np.float32, count=1)[0]
width = np.fromfile(flo, np.int32, count=1)[0]
height = np.fromfile(flo, np.int32, count=1)[0]
print('tag', tag, 'width', width, 'height', height)
nbands = 2
tmp = np.fromfile(flo, np.float32, count= nbands * width * height)
flow = np.resize(tmp, (int(height), int(width), int(nbands)))
基于光流格式规范,希望上面的代码应该更好地了解发生了什么,即得到标签,然后是宽度,然后是高度。print语句的输出是tag 202021.25 width 1024 height 384。根据给定的规范,可以看到标签与健全性检查值匹配,流文件的宽度为1024,高度为384.注意,正确读取文件缓冲区并将其加载到numpy中的顺序非常重要。由于在python中读取文件的方式(字节按顺序读取),否则标签,高度和宽度可能会混淆。现在有宽度和高度,可以读取剩余的光流数据并调整为更熟悉的形状,这是使用该np.resize方法完成的。
了解如何调整流向量大小的快速方法是将它们打印到终端,这可以通过运行以下代码来完成:
>> print(flow.shape)
(384, 1024, 2)
>> print(flow[0][0])
[-1.2117167 -1.557275]
正如所期望的那样,新表示的形状意味着高度为384,宽度为1024,并且具有由2个值组成的位移向量。关注位置处的像素,0, 0可以看到该点处的位移矢量似乎指向左侧和底部,即x,y图的左下象限,这意味着期望该位置的颜色代码为基于下面给出的颜色编码方案,浅蓝色或甚至绿色。
可视化流文件
编写了很多开源代码库来可视化光流文件。为此目的选择的那个可以在github存储库中找到。其原因在于它允许从颜色编码方案生成视频剪辑,这将在稍后阶段有用。假设使用了本教程开头提供的docker上下文,可以使用以下命令生成光流的彩色编码图像文件。
https://github.com/georgegach/flow2image
python /flow2image/f2i.py \
datasets/sintel/output/inference/run.epoch-0-flow-field/*.flo \
-o datasets/sintel/output/color_coding
这将获取光流文件并生成图像文件,其中位移矢量被颜色编码,如下所示。
在位置0,0,即图像的右下部分,确实可以看到浅蓝色并且是从位移矢量所期望的,即它是指向左侧和底部的矢量的颜色。
将光流应用于舞蹈视频
在本节中,将使用舞蹈视频,并从中生成光流文件。舞蹈视频是:
它由现实世界环境中的舞蹈编排课程组成。
生成帧
由于流网代码库接收图像,首先需要做的是将视频转换为帧,这可以通过使用ffmpeg的以下命令来完成。
ffmpeg -i datasets/dancelogue/sample-video.mp4 \
datasets/dancelogue/frames/output_%02d.png
它将在帧文件夹内以有序序列输出帧,顺序很重要,因为流网算法使用相邻图像来计算图像之间的光流。生成的帧占用1.7 GB内存,而视频仅占11.7 MB,每帧大约2 MB。
生成光流
可以通过运行以下命令来生成光流表示。
python main.py --inference --model FlowNet2 --save_flow \
--inference_dataset ImagesFromFolder \
--inference_dataset_root datasets/dancelogue/frames/ \
--resume checkpoints/FlowNet2_checkpoint.pth.tar \
--save datasets/dancelogue/output
这与使用sintel数据集运行的推理模型类似,其中差异在--inference_dataset参数中变化,ImagesFromFolder并且在代码库中定义。这--inference_dataset_root是生成的视频帧的路径。生成的光流文件占用14.6 GB的内存,这是因为对于此示例,每个光流文件大约为15.7 MB。
生成颜色代码方案
生成颜色编码方案的命令是:
python /flow2image/f2i.py \
datasets/dancelogue/output/inference/run.epoch-0-flow-field/*.flo \
-o datasets/dancelogue/output/color_coding -v -r 30
这使用了flow2image存储库以及ffmpeg。它不仅生成光流颜色编码作为.png文件,而且-v -r 30参数从图像文件生成视频30 fps。生成的颜色编码帧占用422 MB的内存,其中包含一个8.7 MB的视频文件,000000.flo.mp4如果通过此博客,则该文件具有该名称。
https://github.com/georgegach/flow2image
结果
生成的光流视频表示如下:
从生成的视频中可以看出编排的要点,不同的颜色表示运动的方向。然而可以看出,尽管视频中没有明显的运动,但在中央舞者周围仍存在很多背景噪音。不幸的是,目前尚不清楚为什么会这样。
尺寸含义
在运行流网算法时,需要了解大小含义,例如11.7 MB视频,在提取时会生成1.7 GB的单个帧文件。然而当产生光流时,这变成包含所有光流表示的14.6GB文件。这是因为每个光流文件在存储器中占据大约15.7MB,但是每个图像帧占用2MB的存储器(对于所提供的示例的情况)。因此当运行光流算法时,需要了解计算要求与空间权衡。在构建视频深度学习系统时,这种折衷将影响架构,这意味着要么根据需要生成光流文件。
结论
已经看到了如何使用NVIDIA的flownet2-pytorch实现的分支生成光流文件,以及对光流文件的概述。
参考
https://blog.dancelogue.com/what-is-optical-flow-and-why-does-it-matter/
https://blogs.nvidia.com/blog/2016/08/22/difference-deep-learning-training-inference-ai/
https://stackoverflow.com/questions/28013200/reading-middlebury-flow-files-with-python-bytes-array-numpy