Python-비디오 프레임 추출 및 저장


134

그래서 저는 이 튜토리얼을 따랐 지만 아무것도하지 않는 것 같습니다. 단순히 아무것도. 몇 초간 기다렸다가 프로그램을 닫습니다. 이 코드에 어떤 문제가 있습니까?

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 바이트 인 이미지를 하나만 만들었습니다.


1
의 가치는 success무엇입니까?
101

2
가치 는 무엇입니까 ? 유형은 부울 수 있지만, 그것은이다 True또는 False?
That1Guy

1
예,하지만 당신의 가치 는 무엇 입니까? 프로그램이 단순히 "몇 초간 기다렸다가 종료"하는 경우 거짓 일 수 있습니다. 즉, print success어딘가에 추가하십시오 .
101

1
강제하는 것은 이치에 맞지 않습니다 success. 거짓이면 어떤 이유로 인해 비디오 읽기가 실패했음을 의미합니다. 먼저 그 비트를 작동시켜야합니다.
101.

1
readh가 실패했습니다. 튜토리얼의 지시에 따라 python 및 ffmpeg로 opencv를 빌드 했습니까? brew install opencv --python27 --ffmpeg다른 버전의 Python을 사용하는 경우 해당 버전으로 변경해야합니다.
Knells

답변:


227

에서 여기 이 다운로드 비디오를 우리가 시험 같은 비디오 파일을 그래서. 파이썬 코드와 같은 디렉토리에 mp4 파일이 있는지 확인하십시오. 그런 다음 동일한 디렉토리에서 파이썬 인터프리터를 실행해야합니다.

그런 다음 코드를 수정 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

어떻게 되나요?


4
이것은 빈 jpeg 파일을 저장하고 반환합니다Read a new frame: False

3
즉, opencv는 비디오를 읽을 수 없습니다. 대부분 ffmpeg에 액세스 할 수 없습니다. 어떤 OS를 사용하고 있습니까?
Fireant


3
특정 버전의 opencv에 대한 지침을 Google에서 확인하고 Windows에서 ffmpeg 및 opencv-python을 작동시키는 방법을 정확하게 따르십시오.
Fireant

3
그래서 사용 호환성 내 문제를 해결하기 위해 질문을. DLL의 이름을 opencv_ffmpeg300.dll로 변경해야했습니다 (OpenCV2의 Python 설치가 3.0.0 이었으므로). Python 디렉토리 (C : \ Python27)에 배치했습니다. ffmpeg 또는 opencv의 Windows 버전을 설치할 필요는 없었지만 OpenCV와 함께 제공되는 DLL이 필요했지만 그 후에 나머지 OpenCV를 삭제했습니다. 어쨌든 나는 이것을 대답으로 선택할 것이지만 이것을 읽는 사람은이 필수 DLL에 대해 알아야합니다.

37

누군가가 모든 프레임을 추출하고 싶지 않지만 1 초마다 프레임을 추출하려는 경우 약간 다른 경우에 대해이 질문 (@ 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)

내가 사용하고 opencv-2.4.9그래서 대신에, cv2.CAP_PROP_POS_MSEC나는 것은 사용했다cv2.cv.CAP_PROP_POS_MSEC
Pratik 쿠마에게

1
5 초마다 프레임을 원하는 경우 코드를 변경하는 방법은 무엇입니까?
Soumya Boral

1
@SoumyaBoralcount = count + 5
Bhushan 바바

@BhushanBabar는 cv2.imwrite()루프 cv2.imread()전에 호출했기 때문에 루프 시작 부분에 있어야하지 않습니까?
mLstudent33

@ mLstudent33 죄송합니다. 이해하지 마십시오.
Bhushan Babar

12

이것은 @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)

11

이것은 대부분의 비디오 형식을 비디오에있는 프레임 수로 변환하는 기능입니다. 그것은 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파일 에 대해 시도하고 테스트했습니다 . 매력처럼 작동합니다.


8

프레임을 비디오로 변환하는 방법에 대한 많은 연구 끝에이 기능이 도움이되기를 바랍니다. 이를 위해 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 (초당 프레임 수), 입력 폴더 경로 및 출력 폴더 경로 값을 변경하십시오.


files.sort (key = lambda x : int (x [5 : -4])) 위 줄을 추가하면 문자열이 아닌 숫자에 따라 프레임을 정렬하는 데 도움이됩니다. 예 : 처음에는 frame1.jpg 다음에 frame10.jpg frame2.jpg가 아닌, 위의 줄은 그 안에있는 숫자에 따라 파일을 정렬합니다.
Puja Sharma

3
질문 비디오에서 프레임에 있었다
Santhosh Dhaipule Chandrakanth

어떤 이유로 나를 위해 비디오를 저장하지 않습니다
Raksha

7

이전 답변은 첫 번째 프레임을 잃었습니다. 그리고 이미지를 폴더에 저장하는 것이 좋습니다.

# 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로 프레임 래트를 확인할 수 있습니다 . 창-> 미디어 정보-> 코덱 세부 정보로 이동합니다.


추출하는 동안 프레임 속도를 높이는 방법이 있습니까?
Pratik Khadloya

아니요. 동영상이 만들어지면 프레임 속도가 고정됩니다. 그 이상을 추출 할 수 없습니다.
Yuchao Jiang

정말 놀라운 대답입니다. 나를 위해 완벽하게 작동했습니다. 프레임 120-160과 같은 특정 범위의 프레임 만 가져 오도록 코드에서 루프를 조정하는 방법이 있습니까? 감사!
Bowen Liu

변수 개수를 사용하여 추출 할 프레임을 지정할 수 있습니다.
Yuchao Jiang

비디오에서 추출하려면 어떻게해야합니까? 비디오 시작부터 비디오 끝까지 시간상 등거리에있는 15 개의 프레임이 있다고 가정 해 보겠습니다. 을 사용해야한다는 cv.CAP_PROP_POS_AVI_RATIO것을 알았지 만 방법을 모르겠습니다. tnx
NeStack

7

이 코드는 비디오에서 프레임을 추출하고 프레임을 .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

4

Anaconda의 Spyder 소프트웨어를 통해 Python을 사용하고 있습니다. @Gshocked의이 스레드 질문에 나열된 원본 코드를 사용하면 코드가 작동하지 않습니다 (파이썬은 mp4 파일을 읽지 않습니다). 그래서 OpenCV 3.2를 다운로드하고 "bin"폴더에서 "opencv_ffmpeg320.dll"과 "opencv_ffmpeg320_64.dll"을 복사했습니다. 이 두 dll 파일을 Anaconda의 "Dlls"폴더에 붙여 넣었습니다.

Anaconda에는 "pckgs"폴더도 있습니다. Anaconda "pckgs"폴더에 다운로드 한 전체 "OpenCV 3.2"폴더를 복사하여 붙여 넣었습니다.

마지막으로 Anaconda에는 "bin"하위 폴더가있는 "Library"폴더가 있습니다. "opencv_ffmpeg320.dll"및 "opencv_ffmpeg320_64.dll"파일을 해당 폴더에 붙여 넣었습니다.

Spyder를 닫고 다시 시작한 후 코드가 작동했습니다. 세 가지 방법 중 어떤 것이 효과가 있었는지 잘 모르겠고 돌아가서 알아 내기에는 너무 게으르다. 그러나 그것은 그렇게 작동합니다, 건배!


4

이 기능은 1fps로 비디오에서 이미지를 추출합니다. 또한 마지막 프레임을 식별하고 읽기도 중지합니다.

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

0

다음 스크립트는 폴더에있는 모든 비디오의 0.5 초마다 프레임을 추출합니다. (파이썬 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)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.