3

I want to convert my input video to a set of frames. I have read the post on Python - Extracting and Saving Video Frames.

But I would like to have a function where I can insert the video as the parameter, not the location of the video file.

In the VideoCapture function below, it takes in the location of the video file.

import cv2
def vidtoframes(videoFile):
 vidcap = cv2.VideoCapture(videoFile)
 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

But is there a function or way to pass a video to the method and convert it to array of frames without saving anything onto the disk.

john
  • 619
  • 9
  • 24
  • Do you mean video URL? – zindarod Jul 06 '18 at 18:00
  • 1
    I want to make a web application that can convert video to a set of frames, so I would like to make the code universal. I want to convert video that is uploaded to the site into an array of frames and return them, without saving anything to files. – john Jul 06 '18 at 18:02
  • I am not sure what you mean. If the video is uploaded then it is saved somewhere and you can give it's path to OpenCV but if the video can be streamed like Youtube then you can use [youtube-dl](https://stackoverflow.com/a/50881927/2286337). – zindarod Jul 06 '18 at 18:07
  • 1
    I am very new to web development. So I am wondering, where would the video be saved? – john Jul 06 '18 at 18:20
  • 1
    Or how would I find its location? – john Jul 06 '18 at 18:20

3 Answers3

1

The video that is taken must be saved to a directory and then we can perform the functions upon it. That is how an application would work as well.

  • Thank you, Hidrana, for taking the time to help others on stack overflow. To improve the quality of your answer, please consider showing an example solution and perhaps explain why the fix is necessary. – SteveJ Aug 24 '19 at 21:26
0

OO approch: write a sort of "VideoWrapper" class and derived classes:

from abc import abstractmethod

class VideoWrapper:
    def __init__(self, path: str, chunk_size: int = 1):
        self.path = path
        self.chunk_size = chunk_size

    @abstractmethod
    def __iter__(self): ...

class VideoFileWrapper(VideoWrapper):
    def __iter__(self):
        chunk = []
        cap = cv2.VideoCapture(self.path)
        while cap.isOpened():
            ret, frame = cap.read()
            chunk.append(frame)
            if len(chunk) == self.chunk_size:
                yield chunk
                chunk = []


class VideoFolderWrapper(VideoWrapper):
    def __iter__(self):
        chunk = []
        for frame_path in glob(os.path.join(self.path, '*')):
            frame = cv2.imread(frame_path)
            chunk.append(frame)
            if len(chunk) == self.chunk_size:
               yield chunk
               chunk = []

in that case you could pass a single class type across your code. an even nicer class would implement __enter__ and __exit__ methods in order to use the with statement, exception handling and so on. that might be too much, a simpler "Pythonic" version will be:

def video_wrapper(path):
    if os.path.isdir(path):
        frames = list(glob(os.path.join(path, '*.png')))
        frames.sort(key=file_name_order)
        for frame_path in frames:
            frame = cv2.cvtColor(cv2.imread(frame_path),cv2.COLOR_BGR2RGB)
            yield frame
    elif os.path.exists(path):
        cap = cv2.VideoCapture(path)
        while cap.isOpened():
        ret, frame = cap.read()
        yield frame
Assaf-ge
  • 464
  • 4
  • 6
0

Yes! There is! But it will require a wee bit of setup. Everything is detailed here:

Streaming video in memory with OpenCV VideoWriter and Python BytesIO

The basics are that you need a tmpfs partition in linux, and utilize the tempfile functionality of Python (which just wraps mkstemp in linux again).

If you have a video file in memory already, something like:

video_bytes = s3.download('file.avi')

And just want to deal with it in memory (and continue to use OpenCV), then check out the other post I listed above.

VocoJax
  • 1,469
  • 1
  • 13
  • 19