Reputation: 629
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.
Upvotes: 3
Views: 4423
Reputation: 1549
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.
Upvotes: 0
Reputation: 508
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
Upvotes: 0
Reputation: 34
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.
Upvotes: 1