在视频处理的时候遇到一个要求,将视频循环切割成多个小视频,但不能直接将视频裁成各个小段,需要采用划窗的方法进行实现。
这里对划窗的方法进行一下介绍
对一个20秒的视频进行划窗分割,设窗长为10秒,窗取样间隔两秒。结果就是将20秒的视频分成0-10秒,2-12秒,4-14秒。。。。。10-20秒这6个视频。
在网上没有找到实现的代码,所以自己学了一下Python的opencv模块,完成了这些功能,对目标路径的所有视频进行划窗拆分,输出到指定路径,同时也可以调整输出视屏的宽高,划窗的长度和划窗的间隔时间。在完成后将所有代码附在这里:
import cv2
import configparser
import os
from tqdm import tqdm
class VideoProcessing:
def __init__(self):
#读入配置文件
self.__configer()
def __configer(self):
conf = configparser.ConfigParser()
conf.read('configer.ini')
self.inputdir = conf['video_information']['inputdir']
self.output_dir = conf['video_information']['output_dir']
self.window_spacing = int(conf['video_information']['window_spacing'])
self.window_long = int(conf['video_information']['window_long'])
def video_processing(self):
#获取目录的所有需要处理视频
videodirlist = os.listdir(self.inputdir)
for i,video_name in enumerate(tqdm(videodirlist)):
#获取视频信息
cap = cv2.VideoCapture(os.path.join(self.inputdir, video_name))
fps = cap.get(cv2.CAP_PROP_FPS)
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
all_frame_count = int(cap.get(7))
print(video_name,':',fps,height,width,all_frame_count)
outsize = (width//2,height//2)
# 用列表装储存视频的类,方便划窗储存多个视频
outlist = []
frameidx = 0
capidx = 0
while True:
#对一个原始视频进行处理
success,frame = cap.read()
if success == False:
outlist.clear()
break
frameidx += 1
if frameidx%(int(fps*self.window_spacing)) == 1:
#定义输出视频的位置和名字
if not os.path.exists(os.path.join(self.output_dir,video_name.replace('.MP4','')+'_cut')):
os.makedirs(os.path.join(self.output_dir,video_name.replace('.MP4','')+'_cut'))
if frameidx <= all_frame_count-fps*self.window_long:
outlist.append(Save_video(os.path.join(self.output_dir,video_name.replace('.MP4','')+'_cut',video_name.replace('.MP4','__')+str(capidx*self.window_spacing).zfill(5)+'s_to_'+str(capidx*self.window_spacing+self.window_long).zfill(5)+'s.mp4'),
['X','V','I','D'],
fps,
outsize,
vidlong=self.window_long))
capidx +=1
frame = cv2.resize(frame,outsize, interpolation=cv2.INTER_CUBIC)
frame = frame[0:outsize[1], 0:outsize[0]]
cv2.imshow('cut video', frame)
for outclass in outlist:
outclass.save(frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
def run(self):
self.video_processing()
class Save_video:
#为了同时储存多个视频,定义保存视频的类
def __init__(self,outname,writeway,fps,outsize,vidlong):
self.outname = outname
self.vidlong = vidlong
self.fps = fps
self.writeway = writeway
self.outsize = outsize
self.__out = cv2.VideoWriter(self.outname,
cv2.VideoWriter_fourcc('M', 'P', '4', 'V'),
self.fps,
self.outsize)
self.frameidx = 0
def save(self,frame):
self.frameidx +=1
if not self.frameidx >= self.fps * self.vidlong:
self.__out.write(frame)
else:
try :
self.__out.release()
except:
pass
if __name__ == '__main__':
VP = VideoProcessing()
VP.run()
其中视频的路径,读取方法使用的是配置文件,包括输入输出路径,划窗长度,划窗间隔和输出宽高内容如下:
[video_information]
inputdir = ./input_dir
output_dir = ./output_dir
window_spacing = 2
window_long = 10
output_wight = 960
output_height = 540
配置文件名称为configer.ini放在Python文件旁边就可以直接运行了
注:运行代码的时候缺少的模块直接一路pip安装,记得安装Python的opencv库用的是pip install opencv-python而不是pip install cv2