Python在windows下使用ffmpeg进行视频截取帧照片并保存到相应文件夹
ffmpeg的一些命令行是在终端使用的并且大多数是以sh文件作为脚本文件运行,在windows下运行linux脚本较为麻烦,所以我写了一个可以遍历文件夹的py脚本文件在windows下使用ffmpeg进行视频帧的截取图片,并创建在有完全相同的数据集目录。实际上也可以利用ffmpeg做其他操作包括录屏等等,可以自己去查询ffmpeg的使用方法。
起因是我在跑C3D项目代码的时候需要对UCF-101数据集进行视频到帧图片的transform,但是项目中给的视频转帧的脚本是sh文件,如果下git倒也是可以直接在windows下运行,但我运行的时候还是有错且我想做一个文件遍历并创建相同目录的数据集,所以我想不如我自己也写一个py脚本以后处理视频数据集更为方便(在虚拟机上跑也行但是怕电脑配置跟不上,数据集较大)下面先贴出sh文件的源码:
原sh文件代码
原C3D项目地址:
https://github.com/hx173149/C3D-tensorflow/blob/master/README.md;
所做的事是把每个动作(此数据集为人体行为数据集作为例子,包括101个动作)的每个训练视频进行image转换并创建相应训练视频同名的文件夹存入
#!/bin/bash
# convert the avi video to images
# Usage (sudo for the remove priviledge):
# sudo ./convert_video_to_images.sh path/to/video fps
# Example Usage:
# sudo ./convert_video_to_images.sh ~/document/videofile/ 5
# Example Output:
# ~/document/videofile/walk/video1.avi
# #=>
# ~/document/videofile/walk/video1/00001.jpg
# ~/document/videofile/walk/video1/00002.jpg
# ~/document/videofile/walk/video1/00003.jpg
# ~/document/videofile/walk/video1/00004.jpg
# ~/document/videofile/walk/video1/00005.jpg
# ...
for folder in $1/*
do
for file in "$folder"/*.avi
do
if [[ ! -d "${file[@]%.avi}" ]]; then
mkdir -p "${file[@]%.avi}"
fi
ffmpeg -i "$file" -vf fps=$2 "${file[@]%.avi}"/%05d.jpg
rm "$file"
done
done
例子:原数据集目录
- root
- UCF-101
- ApplyEyeMakeup
- ApplyLipstick
- Archery
- BabyCrawling
- …
- UCF-101
文章最后有完整py代码:)
import os
from ffmpy import FFmpeg
先创建三个列表用来存储视频文件名称以及视频地址
#创建三个列表用来存储视频文件名以及视频地址
file_list = []
file_list_path=[]
filelist = []
定义输入输出目录
# 源文件目录
dir_path = 'root\\UCF101'
# 输出截取之后的文件目录
put_path = 'D:\\output\\'
三个遍历方法
#利用递归获取该目录下所有文件的path并且存入列表
def get_all_file_path(dir_path):
for file in os.listdir(dir_path):
#print(file)
filepath = os.path.join(dir_path, file)
#print(filepath)
if os.path.isdir(filepath):
get_all_file_path(filepath)
else:
file_list_path.append(filepath)
return file_list_path
#利用递归获取该目录下所有文件的名称并存入列表
def get_file_name(dir_path):
for file in os.listdir(dir_path):
filepath = os.path.join(dir_path, file)
if os.path.isdir(filepath):
get_file_name(filepath)
else:
file_list.append(file)
return file_list
#获取该path目录下文件名称并存入列表
def get_file(dir_path):
for file in os.listdir(dir_path):
#print(file)
filelist.append(file)
return filelist
重写mkdir函数创建文件夹
#重写创建文件夹方法,用来检测是否重复建立文件夹
def mkdir(path):
import os
# 去除首位空格
path = path.strip()
path = path.rstrip("\\")
# 判断路径是否存在
# 存在 True
# 不存在 False
isExists = os.path.exists(path)
# 判断结果
if not isExists:
# 如果不存在则创建目录
# 创建目录操作函数
os.makedirs(path)
return True
else:
# 如果目录存在则不创建,并提示目录已存在
return False
先把数据集遍历到列表中
#file_list先存入数据集中所有的文件名
file_list = get_file_name(dir_path)
#file_list_path先存入数据集中所有文件的path
file_list_path = get_all_file_path(dir_path)
#filelist中存入该输入目录的文件名
filelist = get_file(dir_path)
#分别计算三个列表中元素的个数
lenn = len(file_list)
lenn2 = len(filelist)
lenn3 = len(file_list_path)
# print(lenn3)
# print(lenn)
# print(filelist)
# print(file_list)
# print(file_list_path)
定义cmd命令字符串
第一个路径是ffmpeg.exe的路径,或者在系统环境变量中添加了ffmpeg也可直接写ffmpeg,
5可以换其他数字,代表每秒多少帧,5s的视频就会生成25张图片。输出的图片以‘00001.jpg’命名,两个{}的填充后面会提到
#cmd命令存入str字符串
str = 'F:\\ffmpeg-20200826-8f2c1f2-win64-static\\bin\\ffmpeg.exe ' + '-i {} -r 5 -f image2 {}%05d.jpg'
创建文件夹
#创建filelist空文件夹
for i in range(lenn2):
mkdir(put_path+"".join(filelist[i]))
两个for循环遍历所有相应文件夹并在相应文件夹中创建与训练视频同名的文件夹,把ffmpeg转换好的图片放入
'''
循环遍历把每个文件的视频截取图片存入相应的文件夹
外循环遍历不同动作类别,内循环遍历每个动作不同的训练数据并创建文件夹存入
'''
for j in range(lenn2):
#parent存储当前动作名
parent = "".join(filelist[j])
#print(parent)
#对文件名和路径列表清空
file_list.clear()
file_list_path.clear()
#根据当前动作子路径查找其目录下文件名更新file_list
file_list = get_file_name(dir_path + "\\" + parent + "\\")
#更新file_list_path
file_list_path = get_all_file_path(dir_path+"\\"+parent+"\\")
#print(file_list_path)
#内循环遍历该动作
for i in range(len(file_list)):
a = "".join(file_list[i])
a, _ = a.split(".")
#创建不同训练数据文件夹
mkdir(put_path + parent + "\\" + a)
# # print(filelist[j])
# print(put_path+parent+"\\"+a+"\\")
#填充ffmpeg命令的输入输出信息并运行
str_cmd = str.format(file_list_path[i], put_path + parent + "\\" + a + "\\")
os.popen(str_cmd)
# print(str_cmd)
#清空两个列表
file_list.clear()
file_list_path.clear()
print("\n\n")
完整代码
import os
from ffmpy import FFmpeg
# 创建三个列表用来存储视频文件以及视频地址
file_list = []
file_list_path=[]
filelist = []
# 源文件目录
dir_path = 'root\\UCF-101'
# 输出截取之后的文件目录
put_path = 'D:\\output\\'
#利用递归获取该目录下所有文件的path并且存入列表
def get_all_file_path(dir_path):
for file in os.listdir(dir_path):
#print(file)
filepath = os.path.join(dir_path, file)
#print(filepath)
if os.path.isdir(filepath):
get_all_file_path(filepath)
else:
file_list_path.append(filepath)
return file_list_path
#利用递归获取该目录下所有文件的名称并存入列表
def get_file_name(dir_path):
for file in os.listdir(dir_path):
filepath = os.path.join(dir_path, file)
if os.path.isdir(filepath):
get_file_name(filepath)
else:
file_list.append(file)
return file_list
#获取该path目录下文件名称
def get_file(dir_path):
for file in os.listdir(dir_path):
#print(file)
filelist.append(file)
return filelist
#重写创建文件夹方法,用来检测是否重复建立文件夹
def mkdir(path):
import os
# 去除首位空格
path = path.strip()
path = path.rstrip("\\")
# 判断路径是否存在
# 存在 True
# 不存在 False
isExists = os.path.exists(path)
# 判断结果
if not isExists:
# 如果不存在则创建目录
# 创建目录操作函数
os.makedirs(path)
return True
else:
# 如果目录存在则不创建,并提示目录已存在
return False
#file_list先存入数据集中所有的文件名
file_list = get_file_name(dir_path)
#file_list_path先存入数据集中所有文件的path
file_list_path = get_all_file_path(dir_path)
#filelist中存入该输入目录的文件名
filelist = get_file(dir_path)
#分别计算三个列表中元素的个数
lenn = len(file_list)
lenn2 = len(filelist)
lenn3 = len(file_list_path)
# print(lenn3)
# print(lenn)
# print(filelist)
# print(file_list)
# print(file_list_path)
#cmd命令存入str字符串
str = 'F:\\ffmpeg-20200826-8f2c1f2-win64-static\\bin\\ffmpeg.exe ' + '-i {} -r 5 -f image2 {}%05d.jpg'
#创建filelist空文件夹
for i in range(lenn2):
mkdir(put_path+"".join(filelist[i]))
'''
循环遍历把每个文件的视频截取图片存入相应的文件夹
外循环遍历不同动作类别,内循环遍历每个动作不同的训练数据并创建文件夹存入
'''
for j in range(lenn2):
#parent存储当前动作名
parent = "".join(filelist[j])
#print(parent)
#对文件名和路径列表清空
file_list.clear()
file_list_path.clear()
#根据当前动作子路径查找其目录下文件名更新file_list
file_list = get_file_name(dir_path + "\\" + parent + "\\")
#更新file_list_path
file_list_path = get_all_file_path(dir_path+"\\"+parent+"\\")
#print(file_list_path)
#内循环遍历该动作
for i in range(len(file_list)):
a = "".join(file_list[i])
a, _ = a.split(".")
#创建不同训练数据文件夹
mkdir(put_path + parent + "\\" + a)
# # print(filelist[j])
# print(put_path+parent+"\\"+a+"\\")
#填充ffmpeg命令的输入输出信息并运行
str_cmd = str.format(file_list_path[i], put_path + parent + "\\" + a + "\\")
os.popen(str_cmd)
# print(str_cmd)
#清空两个列表
file_list.clear()
file_list_path.clear()
print("\n\n")