पायथन - वीडियो फ्रेम्स को निकालना और सहेजना


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
आपका रीड फेल हो रहा है। आप ट्यूटोरियल में निर्देश के रूप में अजगर और ffmpeg के साथ opencv बनाया है? brew install opencv --python27 --ffmpegयदि आप पायथन के किसी भिन्न संस्करण का उपयोग कर रहे हैं, तो आपको इसे अपने संस्करण में बदलने की आवश्यकता होगी।
नॉट्स

जवाबों:


227

से यहाँ इस डाउनलोड वीडियो तो हम परीक्षण के लिए एक ही वीडियो फ़ाइल है। सुनिश्चित करें कि आपके python कोड की उसी निर्देशिका में 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 का उपयोग नहीं कर सकता है। आप कौन सा ओएस उपयोग कर रहे हैं?
फिरौती

1
इसे देखें: kronoskoders.logdown.com/posts/…
Fireant

3
Google opencv के आपके विशिष्ट संस्करण के लिए निर्देश देता है और विंडोज पर काम करने वाले ffmpeg और opencv-python प्राप्त करने के तरीके के बारे में सटीक रूप से अनुसरण करता है।
२३

3
इसलिए मैंने इस प्रश्न का उपयोग संगतता के साथ अपनी समस्या को हल करने के लिए किया । मुझे opencv_ffmpeg300.dll को DLL का नाम बदलना पड़ा (जैसा कि OpenCV2 का पायथन-इंस्टॉलेशन 3.0.0 था)। मैंने इसे अपने पायथन डायरेक्टरी (C: \ Python27) में रखा। मुझे ffmpeg के विंडोज़ संस्करण और न ही ओपनस्क्रीन को स्थापित करने की आवश्यकता नहीं थी, लेकिन मुझे उस DLL की आवश्यकता थी जो OpenCV के साथ आती है, लेकिन मैंने उसके बाद OpenCV के बाकी हिस्सों को हटा दिया। किसी भी तरह, मैं इसे एक उत्तर के रूप में चुनूंगा, लेकिन इसे पढ़ने वाले किसी भी व्यक्ति को इस अनिवार्य DLL के बारे में पता होना चाहिए।

37

इस सवाल पर विस्तार करने के लिए (और @ 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
प्रतीक कुमार

1
अगर मुझे हर 5 सेकंड में फ्रेम चाहिए तो कोड कैसे बदलें?
सौम्या बोराल

1
@ सौम्याबोरलcount = count + 5
भूषण बाबर

@ भूषणबबर को cv2.imwrite()लूप की शुरुआत में नहीं होना चाहिए क्योंकि आपने लूप से cv2.imread()पहले फोन किया था?
mLstudent33

@ mLstudent33 क्षमा करें, आपको नहीं मिला, कृपया विस्तृत करें।
भूषण बाबर

12

यह @GShocked से अजगर 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)

एफपीएस (फ्रेम प्रति सेकंड), इनपुट फ़ोल्डर पथ और आउटपुट फ़ोल्डर पथ के मूल्य को अपने स्थानीय स्थानों के अनुसार बदल दें


files.sort (कुंजी = लैम्ब्डा x: int (x [5: -4])) ABOVE लाइन को जोड़ने से जो फ्रेम को संख्या के अनुसार क्रमबद्ध करने में मदद करता है न कि स्ट्रिंग के लिए जैसे: शुरू में फ्रेम 1।jpg को फ्रेम 10 के साथ पालन किया गया था। जेपीजी नहीं फ्रेम 2.jpg, ऊपर की संख्या इसमें संख्याओं के अनुसार फाइलों को क्रमबद्ध करती है।
पूजा शर्मा

3
प्रश्न वीडियो से फ्रेम तक था
संतोष धिपुले चंद्रकांत

किसी कारण से मेरे लिए वीडियो को सहेजना नहीं
रक्षा

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

वैसे, आप वीएलसी द्वारा फ्रेम चूहे ई की जांच कर सकते हैं । विंडोज़ पर जाएं -> मीडिया जानकारी -> कोडेक विवरण


क्या निष्कर्षण करते समय फ्रेम दर को बढ़ाने का एक तरीका है?
प्रतीक खदलोया

नहीं, जब कोई वीडियो बनाया जाता है, तो फ्रेम दर तय की जाती है। आप इससे अधिक नहीं निकाल सकते।
युकाओ जियांग

क्या अद्भुत जवाब है। मेरे लिए पूरी तरह से काम किया। क्या कोड में लूप को मोड़ने का कोई तरीका होगा ताकि मुझे केवल एक निश्चित सीमा से फ्रेम मिलें, जैसे कि फ्रेम 120 - 160? धन्यवाद!
बोवेन लियू

आप जिस फ़्रेम को निकालना चाहते हैं, उसे निर्दिष्ट करने के लिए आप चर गणना का उपयोग कर सकते हैं।
युचाओ जियांग

यदि मुझे वीडियो से निकालने की इच्छा हो तो मुझे क्या करना होगा? मान लीजिए कि वीडियो शुरू होने के समय से लेकर वीडियो के अंत तक समान रूप से 15 फ्रेम होते हैं? मुझे पता चला कि मुझे उपयोग करना है cv.CAP_PROP_POS_AVI_RATIO, लेकिन मुझे नहीं पता कि कैसे। tnx
नेस्टैक

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

मैं एनाकोंडा के स्पाइडर सॉफ्टवेयर के माध्यम से पायथन का उपयोग कर रहा हूं। इस धागे के सवाल में सूचीबद्ध मूल कोड का उपयोग करके @Gshocked, कोड काम नहीं करता है (अजगर mp4 फ़ाइल नहीं पढ़ेगा)। इसलिए मैंने OpenCV 3.2 डाउनलोड किया और "opencv_ffmpeg320.dll" और "opencv_ffmpeg320_64.dll" को "बिन" फ़ोल्डर से कॉपी किया। मैंने एनाकोंडा के "डीएलएस" फ़ोल्डर में इन दोनों डीएल फाइलों को चिपकाया।

एनाकोंडा में एक "pckgs" फ़ोल्डर भी है ... मैंने कॉपी किया और पूरे "OpenCV 3.2" फ़ोल्डर को चिपकाया, जिसे मैंने एनाकोंडा "pckgs" फ़ोल्डर में डाउनलोड किया।

अंत में, एनाकोंडा के पास एक "लाइब्रेरी" फ़ोल्डर है जिसमें "बिन" सबफ़ोल्डर है। मैंने उस फ़ोल्डर में "opencv_ffmpeg320.dll" और "opencv_ffmpeg320_64.dll" फ़ाइलों को चिपकाया।

स्पाइडर को बंद करने और फिर से शुरू करने के बाद, कोड ने काम किया। मुझे यकीन नहीं है कि तीनों में से किस विधि ने काम किया है, और मुझे वापस जाने और इसका पता लगाने के लिए बहुत आलसी है। लेकिन यह काम करता है, चीयर्स!


4

यह फ़ंक्शन 1 एफपीएस के साथ वीडियो से छवियां निकालता है, ADDITION में यह अंतिम फ्रेम की पहचान करता है और पढ़ना भी बंद कर देता है:

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

निम्नलिखित स्क्रिप्ट फ़ोल्डर में सभी वीडियो के हर आधे सेकंड में फ्रेम निकालेगी। (अजगर 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)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.