由于项目需要,所以打算复现《StNet:Local and Global Spatial-Temporal Modeling for Human Action Recognition》这一篇论文,鉴于踩过的一些坑,特此记录下。
项目链接:https://github.com/PaddlePaddle/models/blob/develop/PaddleCV/video/models/stnet/README.md
环境:ubuntu16.04+paddlepaddle
首先来讲下数据处理,这里百度文档使用的是Kinectics-400,虽然文档中也有提供下载,但是不知道为什么,我使用官方的链接无法下载,所以我从网上找了一个链接,感谢https://blog.csdn.net/zugexiaodui/article/details/103598326这个博客的作者,大家如果有尝试官方不成功的可以尝试此方法,不过此方法下载的数据集存在一些问题,特此,写了一些脚本作出修正,如有需要,可以参考。
第一步就是作者提的有些文件的后缀名不是.mp4。在路径中以此把你的train_mp4、val_mp4所在路径填入运行即可。
import os
def read_env_mp4(file_path):
dirpaths=os.listdir(file_path)
dirpaths_=[]
for i in dirpaths:
dirpaths_.append(file_path+i)
#print(dirpaths_)
yuv_name=[]
name=[]
new_name=[]
for i in dirpaths_:
dirpaths1=os.listdir(i)
for j in dirpaths1:
yuv_name.append(j)
print(j)
portion=os.path.splitext(j)#把文件名拆分成名字和后缀
if portion[1]==".mp4":#制定里面所有非mp4的后缀的文件
newname=portion[0]+".mp4"
new_name.append(newname)
name.append(portion[0])
os.rename(i+'/'+j,i+'/'+newname)
if __name__=='__main__':
file_path='自己的路径'
#read_env_mp4(file_path)
第二步,就是我踩到的一个坑,以上脚本只能修改非.mp4后缀的文件,我发现这些数据集中还有.mp4.mp4这中后缀无法修改,因此我就使用了接下来的这个脚本
import os
path='自己的路径'
files=os.listdir(path)
for filename in files:
files1 = os.listdir(os.path.join(path+filename))
for j in files1:
po= j.split('.')
if(len(po)>2):
newname=po[0]+".mp4"
os.rename(path+filename + '/' + j, path+filename + '/' + newname)
到此步,关于后缀的修改基本完事,接下来就是要修改val集文件名的问题,我参考了其给的val的文件列表以及其转数据的video2pkl.py,将其的开始时间与结束时间拼接以后再给文件重新命名,脚本如下,运行时
python 你的脚本.py kinetics-400_val.csv $Source_dir $Target_dir 8
Source_dir = $Code_Root/data/dataset/kinetics/data_k400/val_mp4
Target_dir = $Code_Root/data/dataset/kinetics/data_k400/val_mp4
#实际运行去掉$这个符号
import os
import sys
import glob
try:
import cPickle as pickle
except:
import pickle
from multiprocessing import Pool
assert (len(sys.argv) == 5)
f = open(sys.argv[1])
source_dir = sys.argv[2]
target_dir = sys.argv[3]
num_threads = sys.argv[4]
all_video_entries = [x.strip().split(',') for x in f.readlines()]
all_video_entries = all_video_entries[1:]
f.close()
def generate_pkl(entry):
mode = entry[4]
category = entry[0].strip('"') #取类别
category_dir = category
#supossed name
video_path = os.path.join(
entry[1] + "_%06d" % int(entry[2]) + "_%06d" % int(entry[3]) +".mp4") #0wR5jVB-WPk_00_00.mp4
video_path = os.path.join(source_dir, category_dir, video_path) #val suporsed value
#reality name
video_path1 = os.path.join(
entry[1] + ".mp4") # 0wR5jVB-WPk_00_00.mp4
video_path1 = os.path.join(source_dir, category_dir, video_path1) # val suporsed value
#dict[supposed]=reality
d[video_path]=video_path1
if os.path.exists(video_path1):
os.rename(video_path1,video_path)
else:
print(video_path1)
pool = Pool(processes=int(sys.argv[4]))
pool.map(generate_pkl, all_video_entries)
pool.close()
pool.join()
接下来就可以按照原文档所说的操作了,进行mp4文件的预处理。在 data/dataset/kinetics/data_k400目录下创建目录train_pkl和val_pkl。然后使用video2pkl进行数据转换,然后这里也有一个小坑,我不知道是我自己的问题还是文件写的问题,在文件第59行我做了以下修改,否则会报错,提示我找不到文件。
vid = video_path.split('/')[-1].split('.')[0]#'./' +
经过上述后,train.pkl和val.pkl就打好了,可以经行下一步生成训练和验证集list,生成验证集list时我没什么问题,但是生成训练的list时又给我报了一个错
bash:/bin/ls:参数列表过长
上述错误我没在百度找到对应的解法,所以我就借鉴了一个类似的想法,进入train.pkl所在目录,使用下列命令,得到的是一个在上一级目录下的train.list文件,但是文件里只是包含pkl的名字,没有其路径,因此自己再写一个脚本,给每行加上它共有的路径即可。如果有大佬有其他更简单的方法,麻烦私信我说下,感谢!
find ./ -type f -name "*"|xargs ls >>../train.list
#脚本
import os
path='train.list路径'
newpath='trainnew.list的路径'
f=open(path)
lines=f.readlines()
print(lines)
f.close()
for line in lines:
new='共有路径'+line
newfile=open(newpath,'a')
newfile.write(new)
newfile.close()
至此所有数据操作完成,可以进行下一步训练了