Python - 提取和保存视频帧

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/33311153/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 13:10:44  来源:igfitidea点击:

Python - Extracting and Saving Video Frames

pythonpython-2.7opencv

提问by GShocked

So I've followed this tutorialbut it doesn't seem to do anything. Simply nothing. It waits a few seconds and closes the program. What is wrong with this code?

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

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

Also, in the comments it says that this limits the frames to 1000? Why?

另外,在评论中说这将帧数限制为 1000?为什么?

EDIT: I tried doing success = Truefirst but that didn't help. It only created one image that was 0 bytes.

编辑:我尝试先做,success = True但这没有帮助。它只创建了一个 0 字节的图像。

采纳答案by GShocked

So here was the final code that worked:

所以这是最终有效的代码:

import cv2
print(cv2.__version__)
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

So for this to work, you'll have to get some stuff. First, download OpenCV2. Then install this for Python2.7.x. Go to the FFmpeg folder inside the 3rd party folder (something like C:\OpenCV\3rdparty\ffmpeg, but I'm not sure). Copy opencv_ffmpeg.dll(or the x64 version if your python version is x64) and paste it into your Python folder (probably C:\Python27). Rename it opencv_ffmpeg300.dllif your OpenCV version is 3.0.0 (you can find it here), and change accordingly to your version. Btw, you must have your python folder in your environment path.

所以要让它起作用,你必须得到一些东西。首先,下载 OpenCV2。然后为 Python2.7.x安装它。转到第 3 方文件夹内的 FFmpeg 文件夹(类似于C:\OpenCV\3rdparty\ffmpeg,但我不确定)。复制opencv_ffmpeg.dll(或 x64 版本,如果您的 python 版本是 x64)并将其粘贴到您的 Python 文件夹中(可能是C:\Python27)。opencv_ffmpeg300.dll如果您的 OpenCV 版本是 3.0.0(您可以在此处找到),请重命名它,并根据您的版本进行相应更改。顺便说一句,你必须在你的环境路径中有你的python 文件夹

回答by fireant

From heredownload this videoso we have the same video file for the test. Make sure to have that mp4 file in the same directory of your python code. Then also make sure to run the python interpreter from the same directory.

这里下载此视频,以便我们获得相同的测试视频文件。确保该 mp4 文件位于 Python 代码的同一目录中。然后还要确保从同一目录运行 python 解释器。

Then modify the code, ditch waitKeythat's wasting time also without a window it cannot capture the keyboard events. Also we print the successvalue to make sure it's reading the frames successfully.

然后修改代码,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

How does that go?

这是怎么回事?

回答by Puja Sharma

After a lot of research on how to convert frames to video I have created this function hope this helps. We require opencv for this:

在对如何将帧转换为视频进行了大量研究后,我创建了此功能,希望对您有所帮助。为此,我们需要 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)

change the value of fps(frames per second),input folder path and output folder path according to your own local locations

根据自己的本地位置更改fps(每秒帧数),输入文件夹路径和输出文件夹路径的值

回答by Yuchao Jiang

The previous answers have lost the first frame. And it will be nice to store the images in a folder.

之前的答案已经丢失​​了第一帧。将图像存储在文件夹中会很好。

# 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))

By the way, you can check the frame rate by VLC. Go to windows -> media information -> codec details

顺便说一下,您可以通过 VLC检查帧速率e。转到 windows -> 媒体信息 -> 编解码器详细信息

回答by SpaceFarmer2020

I am using Python via Anaconda's Spyder software. Using the original code listed in the question of this thread by @Gshocked, the code does not work (the python won't read the mp4 file). So I downloaded OpenCV 3.2 and copied "opencv_ffmpeg320.dll" and "opencv_ffmpeg320_64.dll" from the "bin" folder. I pasted both of these dll files to Anaconda's "Dlls" folder.

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

Anaconda also has a "pckgs" folder...I copied and pasted the entire "OpenCV 3.2" folder that I downloaded to the Anaconda "pckgs" folder.

Anaconda 也有一个“pckgs”文件夹……我将下载的整个“OpenCV 3.2”文件夹复制并粘贴到 Anaconda 的“pckgs”文件夹中。

Finally, Anaconda has a "Library" folder which has a "bin" subfolder. I pasted the "opencv_ffmpeg320.dll" and "opencv_ffmpeg320_64.dll" files to that folder.

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

After closing and restarting Spyder, the code worked. I'm not sure which of the three methods worked, and I'm too lazy to go back and figure it out. But it works so, cheers!

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

回答by XRarach

This is a tweak from previous answer for python 3.x from @GShocked, I would post it to the comment, but dont have enough reputation

这是对@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)

回答by Bhushan Babar

To extend on this question (& answer by @user2700065) for a slightly different cases, if anyone does not want to extract every frame but wants to extract frame every one second. So a 1-minute video will give 60 frames(images).

对于稍微不同的情况,扩展这个问题(@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)

回答by Harsh Patel

This is Function which will convert most of the video formats to number of frames there are in the video. It works on Python3with OpenCV 3+

这是将大多数视频格式转换为视频中的帧数的功能。它的工作原理上Python3OpenCV 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)

It supports .mtsand normal files like .mp4and .avi. Tried and Tested on .mtsfiles. Works like a Charm.

它支持.mts和普通文件,如.mp4.avi。对.mts文件进行了尝试和测试。奇迹般有效。

回答by Bence K?vári

This function extracts images from video with 1 fps, IN ADDITION it identifies the last frame and stops reading also:

此功能以 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

回答by Rejoice T J

This code extract frames from the video and save the frames in .jpg formate

此代码从视频中提取帧并将帧保存为 .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