最近需要做点实验,用的是VQA-ODV数据集(目前最大的全景视频数据集),该数据及中有540个受损视频和参考视频以及标签,但是博主只需要用到受损视频(因为想做无参考视频质量评价),所以想办法把视频的每一帧都提取出来放在命名为0-540的文件夹中,文件夹中的帧数也是按数字排列的。最后,在python中把他们放入一个大列表,比如list(17)(1)就表示“17”文件夹下(也就是第17个视频)的第“1”帧。
博主的水平很一般,刚学python,写的代码就像老奶奶的裹脚布(又臭又长),写这篇博客纯属想祭奠一下这个星期为智慧而流淌的头发。
下载解压什么的就不详说了,下载解压完原始数据集后,把受损视频全部复制粘贴到一个新的文件夹下。我的视频路径是C:/Users/LIGHT/Desktop/dataset/VQA-ODV-master。
视频重命名主要用到os.rename的函数,结合for循环遍历文件。然后创建0-539文件夹,方便后续将视频帧放入对应的视频文件夹,代码如下:
# 对视频文件重命名0-539
def rename():
count = 0
file_list = os.listdir(videopath) # 该目录下所有文件
for file in file_list: # 遍历所有文件
olddir = os.path.join(videopath,file) # 原来文件路径
filename = os.path.splitext(file)[0] # 文件名
filetype = os.path.splitext(file)[1] # 文件拓展名
newdir = os.path.join(videopath, str(count)+filetype)
os.rename(olddir, newdir)
count +=1
# 创建0-539文件夹
base = 'C:/Users/LIGHT/Desktop/demo/360VQA/data/'#0-539文件夹的目录
i = 0
for i in range(540):
file_name = base+str(i)
os.mkdir(file_name)
i = i+1
在这里,需要将每个视频的路径和每个视频文件夹(0-539)的路径放在两个列表中,这样才能用一个变量遍历这些文件和文件夹, 代码如下:
def getfile():
file_list = []
for root, dirs, files in os.walk(videopath): # 该目录下所有文件
for file in files:
file_list.append(os.path.join(root, file))
return file_list
def getdir():
dir_list = []
for root, dirs, files in os.walk(svpath):
for dir in dirs:
dir_list.append(os.path.join(root, dir))
return dir_list
# print(os.path.isdir(dir_list[0]))
def convert(file_list, dir_list):
for i in range(0, 540):
cap = cv2.VideoCapture(file_list[i])
frameCount = 0
while True:
ret,frame = cap.read()
if not ret:
break
savepath = svpath + '/' +str(i) + '/' +str(frameCount)+'.jpg'
cv2.imwrite(savepath,frame)
frameCount += 1
#在调用函数的时候
file = getfile()
dir = getdir()
convert(file, dir)
这样就OK了,是不是很简单? 一开始我也以为这么简单,但是当我print(file[0])的时候发现,文件file列表里的视频帧和dir列表里的文件夹没!有!按!顺!序!排!
因为在用os.walk遍历文件的时候,是按ASCII码的顺序来的,也就是0,1,10,100,101,…,11,110,…
于是又开始漫长的排序之旅…
注:下面的程序是另一个python文件
imgdirpath = 'C:/Users/LIGHT/Desktop/demo/360VQA/data/'
num = os.listdir(imgdirpath)
# 获取图片文件夹列表
def get_imgdir():
imgdir_list = []
for root, dirs, files in os.walk(imgdirpath):
for i in dirs:
imgdir_list.append(os.path.join(root, i))
return imgdir_list
imgdir = get_imgdir()
#先给文件夹排序
def dirpaixu():
dirs =[]
for i in num:
if os.path.isdir(imgdirpath+i):
dirs.append(i)
newDir = sorted(dirs, key=lambda d: int(d)) #按数字排序
lastDir = []
for key in newDir:
key = 'C:/Users/LIGHT/Desktop/demo/360VQA/data/'+key
lastDir.append(key)
return lastDir
IMGdir = dirpaixu()
# print(IMGdir[0]) # 确认结果
#再给每个文件夹的视频帧排序
allfile = []
for j in range(0, len(IMGdir)):
file = []
for root, dirs, files in os.walk(IMGdir[j]):
for i in files:
file.append(os.path.join(root, i))
allfile.append(file) # 先获取所有视频帧
# print(allfile[0])
temp = []
temp1 =[]
temp3 = []
for k in allfile:
for g in k:
if len(g.split('\\', 2)[1]) == 5:
temp.append(g) # 数字是个位数的视频帧,即0.jpg到9.jpg
elif len(g.split('\\', 2)[1]) == 6:
temp1.append(g) # 数字是两位数的视频帧,即10.jpg到99.jpg
# print(temp1[90])
# print(len(temp1))
else:
temp3.append(g) # 数字是三位数的视频帧,即100.jpg到XXX.jpg
# print(temp3)
# print(len(temp3))
def filelist(num): # 作用:把一个视频的所有帧按顺序放入一个序列里
n = str(num)
last = []
for a in temp:
if (a.split('\\', 2)[0]).split('/', 8)[7] == n:
last.append(a)
# print(last)
for b in temp1:
if (b.split('\\', 2)[0]).split('/', 8)[7] == n:
last.append(b)
# print(last)
for c in temp3:
if (c.split('\\', 2)[0]).split('/', 8)[7] == n:
last.append(c)
return last
# a = filelist(1) # 视频1的所有帧
# print(a)
# print(len(a))
list = []
for q in range(0, 540):
list.append(filelist(q))
print(os.path.isfile(list[539][0])) # 所有视频的帧合并到大列表里
最后得到的列表print试一下,顺序都对了,不由得留下开心的泪水。
如果想看看自己得到的是不是路径或者文件,可以用os.path.isfile()和os.path.isdir()实现。
最后,希望我能在10月前完成实验并且保持头发的厚度。