超詳細的視頻抽幀——利用opencv-python
直接上代碼
import os
import cv2
def extract_frames(video_path, dst_folder, png_name, index, frame_num):
video = cv2.VideoCapture()
if not video.open(video_path):
print("can not open the video")
exit(1)
count = 0
frames_num = video.get(7)
# step = int(frames_num/frame_num)
step = 4
while True:
_, frame = video.read()
if frame is None:
break
if count % step == 0:
save_path = os.path.join(str(dst_folder), str(png_name)+'-'+'{:0>4d}.png'.format(index))
cv2.imwrite(save_path, frame)
index += 1
count += 1
# if (index==frame_num):
if (index==frames_num):
break
video.release()
def main(VIDEO_PATH, EXTRACT_FLODER, PNG_NAME, FRAME_NUM):
extract_frames(VIDEO_PATH, EXTRACT_FLODER, PNG_NAME, 0, FRAME_NUM)
if __name__ == '__main__':
txt = open('./Index.txt', 'r').readlines()
for class_info in txt:
png_name = class_info.split('.')[0]
sub_id = class_info.split('-', 3)[0]
sts, seq_num = class_info.split('-', 3)[1:3]
sts_seq_num = str(sts) + '-' + str(seq_num)
view_angel = class_info.split('-', 3)[3].split('.')[0]
class_path = './video_frame/' + sub_id +'/' + sts_seq_num + '/' + view_angel +'/'
if not os.path.exists(class_path):
os.makedirs(class_path)
else:
pass
video_path = os.path.join('./video', class_info).strip()
print(video_path)
main(video_path, class_path, png_name, 16)
此代碼功能:
對於輸入的每一個視頻,我們既可以抽取指定數目的幀數(如對輸入的每個視頻抽取16幀,即代碼中main()函數中的參數16),也可以每隔幾幀抽取一幀(如代碼中extract_frames()函數中的step=4,表示每隔4幀抽出一幀並保存)
各函數詳解:
- 首先看看需要導入的包,os是python自帶的,而cv2需要大家自行安裝(即pip install opencv-python)。
- extract_frames()函數就是抽幀的核心代碼,video = cv2.VideoCapture(),video.open(video_path),_, frame = video.read() 表示讀取路徑爲video_path下的視頻,並抽幀。step表示每隔step步抽取一幀。save_path表示將抽取的frame保存的路徑,cv2.imwrite(save_path, frame)表示將抽取的frame寫到該路徑下。
- main()函數表示調用前面的extract_frames()函數。
- if name == ‘main’:函數部分表示對於每個視頻都調用main()函數。
希望對大家有幫助!