问题:Python-提取和保存视频帧
因此,我已按照本教程进行操作,但似乎没有任何作用。根本没有。等待几秒钟,然后关闭程序。此代码有什么问题?
import cv2
vidcap = cv2.VideoCapture('Compton.mp4')
success,image = vidcap.read()
count = 0
success = True
while success:
success,image = vidcap.read()
cv2.imwrite("frame%d.jpg" % count, image) # save frame as JPEG file
if cv2.waitKey(10) == 27: # exit if Escape is hit
break
count += 1
另外,在评论中说这将帧数限制为1000?为什么?
编辑:我尝试先做,success = True
但这没有帮助。它仅创建了一个0字节的图像。
回答 0
从这里下载此视频,以便我们拥有用于测试的相同视频文件。确保将mp4文件放在python代码的同一目录中。然后还要确保从同一目录运行python解释器。
然后修改代码,waitKey
浪费时间也没有窗口,它无法捕获键盘事件。另外,我们打印该success
值以确保它已成功读取帧。
import cv2
vidcap = cv2.VideoCapture('big_buck_bunny_720p_5mb.mp4')
success,image = vidcap.read()
count = 0
while success:
cv2.imwrite("frame%d.jpg" % count, image) # save frame as JPEG file
success,image = vidcap.read()
print('Read a new frame: ', success)
count += 1
怎么样了?
回答 1
如果有人不想提取每一帧,但想每秒钟提取一帧,则针对稍有不同的情况扩展此问题(@ user2700065的答案)。因此,一分钟的视频将提供60帧(图像)。
import sys
import argparse
import cv2
print(cv2.__version__)
def extractImages(pathIn, pathOut):
count = 0
vidcap = cv2.VideoCapture(pathIn)
success,image = vidcap.read()
success = True
while success:
vidcap.set(cv2.CAP_PROP_POS_MSEC,(count*1000)) # added this line
success,image = vidcap.read()
print ('Read a new frame: ', success)
cv2.imwrite( pathOut + "\\frame%d.jpg" % count, image) # save frame as JPEG file
count = count + 1
if __name__=="__main__":
a = argparse.ArgumentParser()
a.add_argument("--pathIn", help="path to video")
a.add_argument("--pathOut", help="path to images")
args = a.parse_args()
print(args)
extractImages(args.pathIn, args.pathOut)
回答 2
这是来自@GShocked的python 3.x以前答案的调整,我将其发布到注释中,但信誉不足
import sys
import argparse
import cv2
print(cv2.__version__)
def extractImages(pathIn, pathOut):
vidcap = cv2.VideoCapture(pathIn)
success,image = vidcap.read()
count = 0
success = True
while success:
success,image = vidcap.read()
print ('Read a new frame: ', success)
cv2.imwrite( pathOut + "\\frame%d.jpg" % count, image) # save frame as JPEG file
count += 1
if __name__=="__main__":
print("aba")
a = argparse.ArgumentParser()
a.add_argument("--pathIn", help="path to video")
a.add_argument("--pathOut", help="path to images")
args = a.parse_args()
print(args)
extractImages(args.pathIn, args.pathOut)
回答 3
此功能可将大多数视频格式转换为视频中的帧数。它的工作原理上Python3
与OpenCV 3+
import cv2
import time
import os
def video_to_frames(input_loc, output_loc):
"""Function to extract frames from input video file
and save them as separate frames in an output directory.
Args:
input_loc: Input video file.
output_loc: Output directory to save the frames.
Returns:
None
"""
try:
os.mkdir(output_loc)
except OSError:
pass
# Log the time
time_start = time.time()
# Start capturing the feed
cap = cv2.VideoCapture(input_loc)
# Find the number of frames
video_length = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) - 1
print ("Number of frames: ", video_length)
count = 0
print ("Converting video..\n")
# Start converting the video
while cap.isOpened():
# Extract the frame
ret, frame = cap.read()
# Write the results back to output location.
cv2.imwrite(output_loc + "/%#05d.jpg" % (count+1), frame)
count = count + 1
# If there are no more frames left
if (count > (video_length-1)):
# Log the time again
time_end = time.time()
# Release the feed
cap.release()
# Print stats
print ("Done extracting frames.\n%d frames extracted" % count)
print ("It took %d seconds forconversion." % (time_end-time_start))
break
if __name__=="__main__":
input_loc = '/path/to/video/00009.MTS'
output_loc = '/path/to/output/frames/'
video_to_frames(input_loc, output_loc)
它支持.mts
和普通文件,例如.mp4
和.avi
。在.mts
文件上尝试和测试。奇迹般有效。
回答 4
经过大量有关如何将帧转换为视频的研究,我创建了此功能,希望对您有所帮助。为此,我们需要opencv:
import cv2
import numpy as np
import os
def frames_to_video(inputpath,outputpath,fps):
image_array = []
files = [f for f in os.listdir(inputpath) if isfile(join(inputpath, f))]
files.sort(key = lambda x: int(x[5:-4]))
for i in range(len(files)):
img = cv2.imread(inputpath + files[i])
size = (img.shape[1],img.shape[0])
img = cv2.resize(img,size)
image_array.append(img)
fourcc = cv2.VideoWriter_fourcc('D', 'I', 'V', 'X')
out = cv2.VideoWriter(outputpath,fourcc, fps, size)
for i in range(len(image_array)):
out.write(image_array[i])
out.release()
inputpath = 'folder path'
outpath = 'video file path/video.mp4'
fps = 29
frames_to_video(inputpath,outpath,fps)
根据您自己的本地位置更改fps(帧/秒),输入文件夹路径和输出文件夹路径的值
回答 5
先前的答案丢失了第一帧。而且最好将图像存储在文件夹中。
# create a folder to store extracted images
import os
folder = 'test'
os.mkdir(folder)
# use opencv to do the job
import cv2
print(cv2.__version__) # my version is 3.1.0
vidcap = cv2.VideoCapture('test_video.mp4')
count = 0
while True:
success,image = vidcap.read()
if not success:
break
cv2.imwrite(os.path.join(folder,"frame{:d}.jpg".format(count)), image) # save frame as JPEG file
count += 1
print("{} images are extacted in {}.".format(count,folder))
顺便说一下,您可以通过VLC 检查帧率。转到Windows->媒体信息->编解码器详细信息
回答 6
此代码从视频中提取帧并将帧保存为.jpg formate
import cv2
import numpy as np
import os
# set video file path of input video with name and extension
vid = cv2.VideoCapture('VideoPath')
if not os.path.exists('images'):
os.makedirs('images')
#for frame identity
index = 0
while(True):
# Extract images
ret, frame = vid.read()
# end of frames
if not ret:
break
# Saves images
name = './images/frame' + str(index) + '.jpg'
print ('Creating...' + name)
cv2.imwrite(name, frame)
# next frame
index += 1
回答 7
我正在通过Anaconda的Spyder软件使用Python。使用@Gshocked在此线程问题中列出的原始代码,该代码不起作用(Python无法读取mp4文件)。因此,我下载了OpenCV 3.2,并从“ bin”文件夹中复制了“ opencv_ffmpeg320.dll”和“ opencv_ffmpeg320_64.dll”。我将这两个dll文件都粘贴到了Anaconda的“ Dlls”文件夹中。
Anaconda也有一个“ pckgs”文件夹…我复制并粘贴了我下载到Anaconda“ pckgs”文件夹中的整个“ OpenCV 3.2”文件夹。
最后,Anaconda有一个“ Library”文件夹,其中有一个“ bin”子文件夹。我将“ opencv_ffmpeg320.dll”和“ opencv_ffmpeg320_64.dll”文件粘贴到该文件夹中。
关闭并重新启动Spyder之后,代码即可正常工作。我不确定这三种方法中的哪一种有效,而且我懒得回头再去弄清楚。但这很奏效,欢呼!
回答 8
此功能以1 fps的速度从视频中提取图像,此外它还标识最后一帧并停止读取:
import cv2
import numpy as np
def extract_image_one_fps(video_source_path):
vidcap = cv2.VideoCapture(video_source_path)
count = 0
success = True
while success:
vidcap.set(cv2.CAP_PROP_POS_MSEC,(count*1000))
success,image = vidcap.read()
## Stop when last frame is identified
image_last = cv2.imread("frame{}.png".format(count-1))
if np.array_equal(image,image_last):
break
cv2.imwrite("frame%d.png" % count, image) # save frame as PNG file
print '{}.sec reading a new frame: {} '.format(count,success)
count += 1
回答 9
以下脚本将每隔半秒提取一次文件夹中所有视频的帧。(适用于python 3.7)
import cv2
import os
listing = os.listdir(r'D:/Images/AllVideos')
count=1
for vid in listing:
vid = r"D:/Images/AllVideos/"+vid
vidcap = cv2.VideoCapture(vid)
def getFrame(sec):
vidcap.set(cv2.CAP_PROP_POS_MSEC,sec*1000)
hasFrames,image = vidcap.read()
if hasFrames:
cv2.imwrite("D:/Images/Frames/image"+str(count)+".jpg", image) # Save frame as JPG file
return hasFrames
sec = 0
frameRate = 0.5 # Change this number to 1 for each 1 second
success = getFrame(sec)
while success:
count = count + 1
sec = sec + frameRate
sec = round(sec, 2)
success = getFrame(sec)