所以我遵循这个教程,但它似乎没有做任何事情。只是没有。它等待几秒钟并关闭程序。这段代码有什么问题?

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字节的图像。


从这里下载这个视频,这样我们就有了相同的测试视频文件。确保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

这是怎么回事?


在对如何将帧转换为视频进行了大量研究后,我创建了这个函数,希望这能有所帮助。我们需要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(帧/秒)的值,输入文件夹路径和输出文件夹路径根据您自己的本地位置


之前的答案已经失去了第一帧。把图片存储在文件夹里会很好。

# 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 ->媒体信息->编解码器详细信息”


我通过Anaconda的Spyder软件使用Python。使用@ gshock在这个线程的问题中列出的原始代码,代码不起作用(python不会读取mp4文件)。所以我下载了OpenCV 3.2,从bin文件夹中拷贝了“opencv_ffmpeg320.dll”和“opencv_ffmpeg320_64.dll”。我将这两个dll文件粘贴到Anaconda的“dll”文件夹。

蟒蛇也有一个“pckgs”文件夹…我复制并粘贴了整个“OpenCV 3.2”文件夹,我下载到Anaconda“pckgs”文件夹。

最后,Anaconda有一个“Library”文件夹,其中有一个“bin”子文件夹。我将“opencv_ffmpeg320.dll”和“opencv_ffmpeg320_64.dll”文件粘贴到该文件夹。

关闭并重新启动Spyder后,代码正常工作。我不确定这三种方法中哪一种有效,我也懒得回去研究。但它确实有效,干杯!


这是对python 3之前答案的一个调整。x来自@ gsurprised,我想把它贴在评论里,但是没有足够的声誉

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)

在稍微不同的情况下扩展这个问题(@user2700065的回答),如果有人不想提取每一帧,但想每一秒提取一帧。所以1分钟的视频会有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)

这是函数,它将大多数视频格式转换为视频中的帧数。它可以在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()
        if not ret:
            continue
        # 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文件上尝试和测试。工作就像一个咒语。


这个函数以1帧/秒的速度从视频中提取图像,此外,它还识别最后一帧并停止读取:

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

这段代码从视频中提取帧并以.jpg格式保存帧

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

下面的脚本将提取帧每半秒的所有视频在文件夹。(适用于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)

从视频演示中提取幻灯片/帧有几个原因,特别是在教育或会议相关视频的情况下。它可以让你在不观看整个视频的情况下访问学习笔记。 我曾多次遇到过这个问题,所以我决定使用python自己创建一个解决方案。我已经使代码开源,你可以很容易地设置这个工具,并在几个简单的步骤中运行它。 参考这个youtube视频教程。 关于如何使用此工具的步骤。

克隆这个项目video2pdfslides 通过运行"pip install -r requirements.txt"来设置您的环境 复制视频路径 执行"python video2pdfslide .py <video_path>" 繁荣!PDF幻灯片将在输出文件夹中提供 做笔记,享受吧!


我可能在这里迟到了,但你可以使用这个PIP包从视频中快速生成图像。你也可以使用特定的fps来获取图像。

pip安装videoToImages

然后在终端中输入以下命令

视频到图像 --视频文件夹 [路径到视频文件夹]

示例:videoToimages——videoofolder "c:/videos"

对于特定的输出FPS,将——FPS 10设置为任何所需的值。-fps 1表示视频中每秒钟一个图像。

完整的命令:

videoToimages—视频文件夹“c:/videos” videoToimages——videoofolder "c:/videos"——fps 10——img_size (512, 512)


在2022年,你也可以选择使用ImageIO来做到这一点,恕我直言,这是更加轻松和易读的。

import imageio.v3 as iio

for idx, frame in enumerate(iio.imiter("imageio:cockatoo.mp4")):
    iio.imwrite(f"extracted_images/frame{idx:03d}.jpg", frame)

旁注1:"imageio:cockatoo.mp4"是imageio为测试和演示目的提供的标准图像。您可以简单地将其替换为“path/to/your/video.mp4”。

旁注2:你必须安装一个ImageIO的可选依赖项来读取视频数据,这可以通过pip install ImageIO -ffmpeg或pip install av来完成。


你可以对照OpenCV计算时间,你会发现,在这方面,OpenCV也没有太多好处:

Read-Only Timings
=================
OpenCV:         0.453
imageio_ffmpeg: 0.765
imageio_pyav:   0.272
Read + Write Timings
====================
OpenCV:         3.237
imageio_ffmpeg: 1.597
imageio_pyav:   1.506

默认情况下,OpenCV和ImageIO+av读取时的速度差不多。两者都在底层直接绑定到FFmpeg库,所以这并不奇怪。然而,ImageIO允许您调整FFmpeg的默认线程模型(thread_type="FRAME"),这在批量读取时要快得多。

更重要的是,ImageIO在编写JPEG方面比OpenCV快得多。这是因为pillow比OpenCV快,ImageIO利用了这一点。在这种情况下,写图像占据了运行时的主导地位,因此使用ImageIO而不是OpenCV时,整体性能提高了2倍。

下面是代码供参考:

import imageio.v3 as iio
import cv2
import timeit
from pathlib import Path

# create a common local file for benchmarking
video_file = "shared_video.mp4"

if not Path(video_file).exists():
    frames = iio.imread("imageio:cockatoo.mp4")
    meta = iio.immeta("imageio:cockatoo.mp4", exclude_applied=False)
    iio.imwrite(video_file, frames, fps=meta["fps"])

repeats = 10


def read_cv2():
    vidcap = cv2.VideoCapture(video_file)
    success, image = vidcap.read()
    idx = 0
    while success:
        cv2.imwrite(f"extracted_images/frame{idx:03d}.jpg", image)
        success, image = vidcap.read()
        idx += 1


def read_imageio_ffmpeg():
    for idx, frame in enumerate(iio.imiter(video_file, plugin="FFMPEG")):
        iio.imwrite(f"extracted_images/frame{idx:03d}.jpg", frame)


def read_imageio_pyav():
    for idx, frame in enumerate(
        iio.imiter(video_file, plugin="pyav", format="rgb24", thread_type="FRAME")
    ):
        iio.imwrite(f"extracted_images/frame{idx:03d}.jpg", frame)


time_cv2 = (
    timeit.timeit("read_cv2()", setup="from __main__ import read_cv2", number=repeats)
    / repeats
)
time_imageio_ffmpeg = (
    timeit.timeit(
        "read_imageio_ffmpeg()",
        setup="from __main__ import read_imageio_ffmpeg",
        number=repeats,
    )
    / repeats
)
time_imageio_pyav = (
    timeit.timeit(
        "read_imageio_pyav()",
        setup="from __main__ import read_imageio_pyav",
        number=repeats,
    )
    / repeats
)

print(
    f"""
Timings
=======
OpenCV:         {time_cv2:<3.3f}
imageio_ffmpeg: {time_imageio_ffmpeg:<3.3f}
imageio_pyav:   {time_imageio_pyav:<3.3f}
"""
)