Python 读取视频并转换为帧的函数
Python function to read video and convert to frames
我想将我的输入视频转换为一组帧。我已阅读 post
Python - Extracting and Saving Video Frames。
但我想要一个功能,我可以插入视频作为参数,而不是视频文件的位置。
在下面的 VideoCapture 函数中,它获取视频文件的位置。
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
但是有没有一种函数或方法可以将视频传递给该方法并将其转换为帧数组而不将任何内容保存到磁盘上。
拍摄的视频必须保存到一个目录中,然后我们才能在其上执行功能。这也是应用程序的工作方式。
OO 方法:编写一种 "VideoWrapper" class 并导出 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 = []
在这种情况下,您可以在代码中传递一个 class 类型。
更好的 class 会实现 __enter__
和 __exit__
方法,以便使用 with
语句、异常处理等。这可能太多了,一个更简单的 "Pythonic" 版本将是:
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
是的!有!但这需要一点设置。一切都在这里详细说明:
基础是您需要 linux 中的 tmpfs
分区,并利用 Python 的 tempfile
功能(它只是将 mkstemp
包装在linux 再一次)。
如果您的内存中已有视频文件,例如:
video_bytes = s3.download('file.avi')
而且只想在内存中处理(并继续使用OpenCV),然后查看我上面列出的其他post。
我想将我的输入视频转换为一组帧。我已阅读 post Python - Extracting and Saving Video Frames。
但我想要一个功能,我可以插入视频作为参数,而不是视频文件的位置。
在下面的 VideoCapture 函数中,它获取视频文件的位置。
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
但是有没有一种函数或方法可以将视频传递给该方法并将其转换为帧数组而不将任何内容保存到磁盘上。
拍摄的视频必须保存到一个目录中,然后我们才能在其上执行功能。这也是应用程序的工作方式。
OO 方法:编写一种 "VideoWrapper" class 并导出 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 = []
在这种情况下,您可以在代码中传递一个 class 类型。
更好的 class 会实现 __enter__
和 __exit__
方法,以便使用 with
语句、异常处理等。这可能太多了,一个更简单的 "Pythonic" 版本将是:
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
是的!有!但这需要一点设置。一切都在这里详细说明:
基础是您需要 linux 中的 tmpfs
分区,并利用 Python 的 tempfile
功能(它只是将 mkstemp
包装在linux 再一次)。
如果您的内存中已有视频文件,例如:
video_bytes = s3.download('file.avi')
而且只想在内存中处理(并继续使用OpenCV),然后查看我上面列出的其他post。