​使用 Python 生成视频帧

​使用 Python 生成视频帧

任务

我们要解决的问题陈述非常容易理解。我们需要访问设备的摄像头。我们的工作是编写一段代码,从摄像机捕获视频,获取视频的每一帧,将其保存在我们的设备上,这样当我们打开所需的文件夹时,它就会包含所有帧。相机将保持开启状态,直到我们按下“x”键。

以下是一些可以帮助你的术语列表。

  • 帧:视频实际上是一系列图像。当一组图像播放得非常快时,我们的眼睛无法跟上图像的变化。结果,在我们的大脑中,我们在图像中看到的物体似乎在移动,这被称为视频。组成视频的单个图像称为帧。当你非常快地浏览所有帧时,你就会得到视频。
  • 每秒帧数 (fps):每秒帧数或 fps,是指视频在一秒钟内播放的帧数。当我们说视频以 24fps 的速度播放时,这意味着播放该视频时,一秒钟内显示 24 帧。这意味着如果一段视频长 1 分钟,并以 24fps 播放,则视频播放器总共会播放 1440 帧!这就是视频文件比照片大的真正原因。

解决方案

为了解决这个任务,我们将使用由英特尔开发的 OpenCV 库。

首先,让我们创建一个新的 python 文件并将其命名为frame_generator.py。

第 0 步:首先,我们需要确保我们的设备中已下载 Python。我们还需要一些 IDE 来运行 Python 代码,例如 IDLE、Pycharm 或 Visual Studio Code (VS Code)。

第 1 步:我们需要确保安装了 OpenCV 包。如果没有,那么我们需要转到命令提示符,键入以下命令并按回车键:

pip install opencv-python

这将在你的设备中安装 OpenCV 包。

第 2 步:在你的文件frame_generator.py 中,导入 cv2 包。

import cv2

第 3 步:使用 cv2 的*VideoCapture()*方法从设备的摄像头读取视频,并将其存储在名为 cap 的变量中。通常一个设备的camera index是0,这样的话,这一行就会变成这样:

cap = cv2.VideoCapture(0)

第 4 步:现在,我们需要指定视频的四字符代码。四字符码,通常缩写为fourcc,是一个4字节的序列,用于标识数据格式。要了解有关 fourcc 的更多信息,请单击(https://en.wikipedia.org/wiki/FourCC)。

通常XVID代码最适合带有 .mp4 或 .avi 扩展名的视频。我们将定义 fourcc 代码并将其存储在名为 fourcc 的变量中

fourcc = cv.VideoWriter_fourcc(*'XVID')

第 5 步:我们将把设备摄像头拍摄的视频保存在一个名为output 的文件中,扩展名为*.avi。我们将文件名存储在名为 file_name 的变量中我们还创建了一个名为save并存储初始值“frame 1”的变量,并创建了一个名为c*的变量,其初始值为 2。

file_name = 'output'
save = 'frame 1'
c = 2;

稍后将使用变量save和c来保存从视频中获得的帧。

第 6 步:使用方法*VideoWriter()*方法,我们将显示我们设备的摄像头看到的内容,为了简单起见,我们将表达式存储在一个名为output 的变量中。我们需要传递文件名、fourcc、每秒显示的帧数和视频捕获窗口的大小(通常为 640×480)。在这里,我们将每秒生成 24 帧。

output = cv2.VideoWriter((file_name+'.avi'), fourcc, 24.0, (640,480))

第 7 步:现在,我们将读取相机正在拍摄的视频。由于我们不知道相机何时会关闭,因此我们无法使用设定值。那我们应该怎么办呢?

答案很简单。我们需要迭代一个循环来生成帧,直到打开相机。OpenCV 为我们提供了一个非常有用的函数isOpened(),它可以帮助我们检查相机是否打开。这是通过编写以下代码实现的:

while cap.isOpened():
  #Rest of the logic goes here

接下来的所有步骤都将在 while 循环内进行。

第 8 步:我们现在从设备的相机读取每一帧。为此,我们需要 2 个变量,我们称它们为resframe。我们使用OpenCV 的read()方法读取每一帧。获取的图像存储在frame 中,而状态存储在res 中。这意味着变量res存储TrueFalse,指示帧是否已成功读取。

res, frame = cap.read()

第 9 步:我们提供一个条件,如果变量res不是True,那么我们将显示一条错误消息并从循环中中断。

if not res:
        print("Frame Cannot Be Received")
        break

这意味着如果没有获得帧,那么循环内的其余代码将不会被执行,而循环之后的那一行将被执行。

第10 步:我们现在需要翻转帧。这是因为相机通常会读取横向倒置的图像。它类似于镜子中的图像。使用 OpenCV 的flip()方法翻转帧。该方法以图像和以度为单位的翻转角度作为参数。

frame = cv2.flip(frame, 90)

第 11 步:然后我们使用输出的write()方法和OpenCV 的imshow()方法显示帧。

output.write(frame)
cv2.imshow('Frame', frame)

字符串“Frame”表示显示视频的窗口的名称是“Frame”。

第 12 步:我们现在将每一帧保存在将要保存 python 文件的文件夹中。使用 OpenCV 的imwrite()方法,帧将以.png格式保存。由于我们需要保存多帧,所以我们将实现逻辑如下。

cv2.imwrite(save+'.png', frame )
save = 'Frame' + str(c)
c = c+1

这里save的初始值为“Frame 1”。所以第一帧存储为“Frame1.png”。现在, save的值变为“Frame2”,因为我们将c的值(最初等于 2)与“Frame”连接或连接起来,然后将 c 的值增加 1。

这确保在下一次迭代中,save的值为“Frame2”,保存的图像为“Frame2.png”, c的新值为3。这一直持续到按下字母“x”在键盘上终止循环。

第 13 步:为了关闭视频窗口,我们需要检查键盘上是否按下了字母“x”。这可以通过检查当 1 作为参数传递时 OpenCv 的waitKey()函数的返回值是否等于当字符 ‘x’ 作为参数传递时的ord()函数的返回值来实现。这意味着当按下“x”时,控件将跳出循环。

if cv2.waitKey(1) == ord('x'):
        break

这实际上意味着如果在 1 毫秒内没有收到帧,或者如果按下字母“x”,则循环结束。

第 14 步:程序的主要逻辑现已完成。剩下的就是跳出循环并通过键入以下代码关闭所有内容。

cap.release()
output.release()
cv2.destroyAllWindows()

release()方法关闭所有打开的对象(在本例中为capout)。destroyAllWindows() 销毁或关闭所有已创建的窗口。这很重要,因为如果我们从终端运行代码,那么有时所有窗口都不会关闭,除非我们退出 python 代码。

第 15 步:为了运行代码,如果代码是在 IDLE 和 Pycharm 等 IDE 中编写的,我们可以按“运行”或“执行”按钮。或者,我们可以打开命令终端并输入python frame_generator.py并按 Enter。

恭喜,你现在已经成功生成了相机捕捉到的帧!!!

如果你在执行这些步骤时遇到问题,这里是完整代码。

import cv2

# Accessing the camera 
cap = cv2.VideoCapture(0)

# Defining the codec and creating the VideoWriter object
fourcc = cv.VideoWriter_fourcc(*'XVID')
file_name = 'output'
output = cv.VideoWriter((file_name+'.avi'), fourcc, 24.0, (640,  480))

# Defining the variables save and c
save = 'Frame1'
c = 2;
while cap.isOpened():

    res, frame = cap.read()
    if not res:
        print("Frame Cannot Be Received")
        break
    
    # Flipping the frame horizontally to get correct orientation
    frame = cv2.flip(frame, 90)

    # Displaying the current frame
    output.write(frame)
    cv2.imshow('Frame', frame)

    # Saving the frames
    cv2.imwrite(save+'.png', frame )
    save = "Frame"+ str(c)
    c = c+1

    # If no input is received for 1ms, or if the key 'x' is pressed, interpreter goes outside of the loop
    if cv2.waitKey(1) == ord('x'):
        break

# Releasing everything after coming out of loop
cap.release()
output.release()
cv2.destroyAllWindows()

结论

因此,我们已经了解了如何通过编写简单的代码来生成相机正在读取的每一帧。人工智能和机器学习是当下的需要。我们越了解如何操作这些技术,就越能控制它们,对人工智能的恐惧也会大大减少。

作者:磐怼怼 | 来源:公众号——深度学习与计算机视觉(ID:uncle_pn)

版权声明:本文内容转自互联网,本文观点仅代表作者本人。本站仅提供信息存储空间服务,所有权归原作者所有。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至1393616908@qq.com 举报,一经查实,本站将立刻删除。

(0)

相关推荐

发表回复

登录后才能评论