前言
最近需要用到视频的光流文件,所以决定跟随前辈们的步伐,自行使用 Flownet2 提取视频光流,但是由于 Flownet2 太老了,网上的攻略也都是几年前的了,我安装的时候遇到了很多攻略里没提到的问题,被困扰了许久才解决,所以中间就打算边做边记,方便后面换新服务器的时候重新安装 Flownet2 不会太麻烦。
2025.03.24 更新
指南参考1:手把手安装flownet2-pytorch_resample2d-CSDN博客
指南参考2:Flownet2-PyTorch 安装使用流程-CSDN博客
服务器的环境:
Ubuntu 16.04,Cuda 10.2
1) 创建环境:
conda create -n flownet2 python=3.7
这里我用过 python 3.6 和 3.8,但后面均出现了问题无法解决,尤其是 3.6,跟着攻略走也不行,太老了不要用!
2) 进入环境
conda activate flownet2
3) 安装 gcc 7, g++ 7
sudo add-apt-repository ppa:ubuntu-toolchain-r/test
sudo apt-get update
sudo apt-get install gcc-7
sudo apt-get install g++-7
这里我在安装的时候会提示“您的网络需要认证吗?”,需要手动上服务器进行网页认证。(非常想吐槽的一点就是以前校园网支持2台PC设备登录,但最近只能1台设备登录了,需要来回在服务器和自己电脑上认证校园网,就很不方便)
4) 将gcc7,g++7作为默认选项
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-7 100 sudo update-alternatives --config gcc sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-7 100 sudo update-alternatives --config g++ sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-7 50
这里如果之前配置过一遍后面就不用再配置了,和环境无关
5) 安装 Pytorch
# 失败指令
conda install pytorch==1.9.0 torchvision==0.6.1 cudatoolkit=10.2 -c pytorch
pip install https://download.pytorch.org/whl/cu102/torch-1.12.0%2Bcu102-cp37-cp37m-linux_x86_64.whl#sha256=6cdaf3bba2733cabdb96d39d5ca5f733d5e1be9f4e27afc7dabed349dc86
在下面的网站中找到符合自己 python 版本、torchvision 版本的包,然后右键保存链接,粘贴到 pip install 后面,各个网站的连接如下(其中的 cu102 要替换成自己对应的 cuda 版本,torch 版本和 torchvision 版本也要对应上,对应关系可以看这个博客:点击跳转):
- Pytorch 的网站:download.pytorch.org/whl/cu102/torch/
- torchvision 的网站:download.pytorch.org/whl/cu102/torchvision
这里我安装了 pytorch-1.12.0+cu102-cp37
和 torchvision-0.13.0+cu102-cp37
6) 下载 flownet2 代码
git clone https://github.com/NVIDIA/flownet2-pytorch.git
cd flownet2-pytorch
7)对代码进行修改
在以下三个文件
- networks/channelnorm_package/setup.py
- networks/resample2d_package/setup.py
- networks/correlation_package/setup.py
作如下修改
# 原代码
cxx_args = ['-std=c++11']
# 修改后
cxx_args = ['-std=c++14']
在 flownet2-pytorch/utils/frame_utils.py 作如下修改
# 原代码
from scipy.misc import imread
# 修改后
from imageio import imread
在 flownet2-pytorch/datasets.py 作如下修改
# 原代码
from scipy.misc import imread, imresize
# 修改后
from imageio import imread
在 flownet2-pytorch/networks/channelnorm_package/channelnorm.py 中作如下修改
# 原代码 class ChannelNormFunction(Function): @staticmethod def forward(ctx, input1, norm_deg=2): assert input1.is_contiguous() # 在上方插入
# 修改后 class ChannelNormFunction(Function): @staticmethod def forward(ctx, input1, norm_deg=2): input1 = input1.contiguous() # 新添加的代码 assert input1.is_contiguous()
8) 进入 install.sh 所在文件夹后输入如下命令
./install.sh
9) 输入如下指令测试一下
python main.py -h
接下来就是缺啥装啥的阶段了
缺失的依赖(opencv-python 和 numpy 我没安装过不知道为何也测试成功了):
pip install tensorboardX pip install setproctitle pip install colorama pip install tqdm pip install imageio pip install scipy pip install matplotlib pip install pytz pip install opencv-python pip install numpy
10) 下载预训练的权重文件
我只用 Flownet2 来做光流估计,所以直接下载训练好的权重文件,由于官方 github 仓库里的链接需要申请,等不了了就直接找了这个帖子里的百度网盘:手把手安装flownet2-pytorch_resample2d-CSDN博客
11) 开始正式推理
新建一个 run.sh 文件,写入如下代码
python ./flownet2-pytorch/main.py \ --inference \ --save_flow \ --model FlowNet2 \ --inference_dataset ImagesFromFolder \ --resume /path/to/your/flownet2/checkpoint \ --inference_dataset_root /path/to/your/dataset/root/ \ --save /path/to/your/saved/folder/ \ --number_gpus 1
简单了解了一下,--inference
是推理模式,--save-flow
是要将光流文件保存下来,--model
就是要使用的模型,--inference_dataset ImagesFromFolder
表示从文件夹里读取图片,--resume
是下载的权重文件路径,--inference_dataset_root
是要处理的数据集路径,里面包含图片,--save
就是光流文件保存的路径,--number_gpus
不明,有人说确保输出的光流文件数量为图片数量减1,这里没有动它。要修改的地方就是 --resume
、--inference_dataset_root
、--save
这三个路径
在准备运行 run.sh
时发现权限不够,又搜了一下如何修改权限。后面发现直接运行 run.sh
不显示报错细节。。。
12) 运行中出现的其他问题
①一开始运行出现了这个问题:
ValueError: Function has keyword-only parameters or annotations, use getfullargspec() API which can support them
网上各说各的,去问了 GPT,说 python 3.7 已经弃用了 getargspec
,得到的解决方法是找到 utils/tools.py,定位到第 64 行,进行如下修改:
# 源代码 argspec = inspect.getargspec(class_obj.__init__)
# 修改后 argspec = inspect.getfullargspec(class_obj.__init__)
② 又遇到问题了
File "/home/zlab-3/xxx/flownet_work/flownet2-pytorch/datasets.py", line 66, in __init__ self.frame_size = frame_utils.read_gen(self.image_list[0][0]).shape IndexError: list index out of range
GPT 的说法是 self.image_list
为空,看了源代码后发现它默认读取 MPI Sintel
,这意味着如果要想让 flownet2
在我的数据集上推理,就需要添加 --inference_dataset ImagesFromFolder
。(好在后面查到解决方法了,差点打算自己搓一个 Dataset
类)
改了之后还是报错,就跑去看 ImagesFromFolder
类,发现 iext
形参(321行左右)默认是 png
,手动改成了适配ped2数据集的 tif
格式,这个问题就解决了。
③ 又又遇到问题了
File "/home/zlab-3/xxx/flownet_work/flownet2-pytorch/datasets.py", line 337, in __init__ self.frame_size = frame_utils.read_gen(self.image_list[0][0]).shape AttributeError: 'list' object has no attribute 'shape'
列表当然没有 shape
属性,那为什么是列表?噢,read_gen
返回了列表。
read_gen
是干嘛的?看了下,第 8 行应该是判断图片类型后缀是不是[png, jpeg, ppm, jpg]
,但是 tif
文件不在里面,后面直接就返回一个空列表。按照如下修改:
# 修改前 if ext == '.png' or ext == '.jpeg' or ext == '.ppm' or ext == '.jpg':
# 修改后 if ext in ['.png', '.jpeg', '.ppm', '.jpg', '.tif', '.tiff']
这个文件里还有一个地方需要注意,如果安装的 imageio
版本比较高,需要将 from imageio import imread
改为 from imageio.v2 import imread
。
④又又又出问题了
还是这个 read_gen
函数
if im.shape[2] > 3: IndexError: tuple index out of range
我的 tif
图片是灰度图,只有两个维度,得先将其复制为三个通道:
if ext in ['.png', '.jpeg', '.ppm', '.jpg', '.tif', '.tiff']: im = imread(file_name) if im.ndim == 2: # 添加 im = np.stack((im, im, im), axis=-1) # 添加 if im.shape[2] > 3: return im[:,:,:3]
不清楚这样对光流的提取是否有影响。
成功运行
然后 Flownet2 终于成功提取出第一个视频的光流!至此模型已经跑通。接下来就是修改 run.sh 让模型开始批量处理视频:
#!/bin/bash # 设置通用参数 CHECKPOINT="/home/zlab-3/xxx/flownet_work/checkpoints/FlowNet2_checkpoint.pth.tar" SAVE_ROOT="/home/zlab-3/xxx/dataset/UCSD_Anomaly_Dataset.v1p2/UCSDped2/Train_Flow" BASE_DATASET="/home/zlab-3/xxx/dataset/UCSD_Anomaly_Dataset.v1p2/UCSDped2/Train" # 遍历 BASE_DATASET 下的所有视频文件夹(假设文件夹命名为 Train001, Train002, ...) for folder in ${BASE_DATASET}/Train*; do folder_name=$(basename "$folder") output_dir="${SAVE_ROOT}/${folder_name}" mkdir -p "$output_dir" echo "Processing $folder, saving flow to $output_dir" python ./flownet2-pytorch/main.py \ --inference \ --save_flow \ --model FlowNet2 \ --inference_dataset ImagesFromFolder \ --resume ${CHECKPOINT} \ --inference_dataset_root ${folder} \ --save ${output_dir} \ --number_gpus 1 done
做完查看了一下光流图片所占空间大小,UCSDped2
+ 总共的光流 .flo 文件大约占 2G,如果我直接找现成的光流文件下载会不会更快一些呢……
至少下次再需要光流文件的时候我就不用再重新走一遍 Flownet2 的“苦痛之路” 了吧😭
其他情况
如果遇到类似的错误:
The detected CUDA version (10.2) mismatches the version that was used to compile PyTorch (12.1). Please make sure to use the same CUDA versions.
说明系统的 CUDA 版本和 Pytorch 的不一样,需要更新 CUDA 版本或 降级 Pytorch 的 CUDA。(尝试过升级 cuda,但是遇到 服务器 ubuntu 版本 16.04 太老,升级 ubuntu 又要花时间,又尝试降级 pytorch,但 conda 又太慢,卡了太久索性删环境从头又配了一个)
其他用到的指令
查看当前 ubuntu 版本
lsb_release -a
查看当前 cuda 版本
nvcc -V
为某一个 .sh 文件授予可执行权限
chmod u+x run.sh
查看当前文件夹大小
df -h