0

我是 Python 和 Raspberry Pi 的新手,我正在尝试编写一个程序来录制 8 秒视频,然后以慢动作播放。它也不必是高质量的视频,它只需要运行程序而没有很长的延迟。

几年前,我目睹了一个正是这样做的项目。它响应触发记录了 8 秒的镜头,并且只用了几秒钟就可以在显示器上以慢动作处理和播放该视频。但是,我不知道那个人是怎么做到的。

我尝试过使用 ffmpeg,但创建慢动作视频需要 90 多秒。我尝试过 OpenCV,但无济于事。我听说 MsgBox 功能也是一个选项,但我找不到该功能的完整文档。我愿意使用任何文件格式,但目前视频输出为 H264。有没有人有好的想法来创建(或只是播放)一个没有缓慢处理速度的慢动作视频,拜托?

这是我用来以 25 fps 录制并以慢动作回放的当前代码,但它需要 1-2 分钟的处理时间(我希望只有几秒钟):

import os
from picamera import PiCamera
from time import sleep
import vlc, subprocess

filename = "/home/pi/vid1.h264"
camera = PiCamera()

camera.start_preview()
camera.start_recording(filename)
sleep(8)
camera.stop_recording()
camera.stop_preview()

# Converts to slow motion video
input = filename
output = "/home/pi/slowvid1.h264"
command = f"ffmpeg -i {input} -vf setpts=2*PTS {output}"
os.system(command)

subprocess.Popen(['vlc',output, '--fullscreen','--play-and-exit'])

这是我让 OpenCV 工作的问题的链接 使用 OpenCV 进行 慢动作视频播放不起作用(python)

4

1 回答 1

0

这是一种方法。我使用PiCamera以 60 fps 的速度捕捉 MJPEG 帧 8 秒。请阅读本文档中的第 4.7 节。

我选择了视频端口,因为它是最快的捕获方法,因为它不会通过对多个帧进行平均来进行复杂的去噪,这会减慢速度。

我选择 MJPEG “Motion JPEG”作为输出格式,因为这意味着帧在收到之前在 GPU 上进行了 JPEG 压缩,这意味着我需要更少的 CPU 资源和更少的 RAM,因为这些帧是压缩的。

当每一帧到达时,除了简单地将其附加到 RAM(内存)中的 JPEG 压缩帧列表之外,我没有做任何其他处理。

录制完成后,我只需遍历内存中的帧列表,将它们从 JPEG 转换回 OpenCV 用于图像的 Numpy 数组,然后显示它们。由于它们是以 60fps 的速度采集的,这意味着每 16 毫秒记录一个新帧。因此,如果我以 64 毫秒的延迟播放,它应该会慢 4 倍。

#!/usr/bin/env python3

import numpy as np
import cv2
import time
import picamera

class SplitFrames(object):
    def __init__(self):
        self.frame_num = 0
        # List of all the JPEG-encoded frames we receive
        self.frames = []
        # Total memory used
        self.memory = 0

    def write(self, buf):
        if buf.startswith(b'\xff\xd8'):
            # Start of new frame
            l = len(buf)
            print(f'DEBUG: New frame of {l} bytes')
            self.frames.append(buf)
            self.frame_num += 1
            self.memory    += l
        else:
            print(f'ERROR: partial frame of {len(buf)} bytes received belonging to previous frame')

################################################################################
# Main program - alter these variables according to needs
################################################################################
targetFPS, duration = 60, 8
width, height = 1024, 768
print(f'Recording frames of {width}x{height} at {targetFPS} fps for {duration} seconds')

################################################################################
# Recording loop
################################################################################
with picamera.PiCamera(framerate=targetFPS) as camera:
    camera.resolution=(width,height)
    camera.start_preview()
    # Give the camera some warm-up time
    time.sleep(2)
    output = SplitFrames()
    start = time.time()
    camera.start_recording(output, format='mjpeg')
    camera.wait_recording(duration)
    camera.stop_recording()
    finish = time.time()

# Calculate a few statistics
fps = output.frame_num / (finish - start)
avg = int(output.memory/output.frame_num)
MB  = output.memory/(1024*1024)
print(f'Captured {output.frame_num} frames at {fps:.3f} fps, average bytes/frame={avg}, total RAM={MB:.3f} MB')

################################################################################
# Playback loop - grab frames from list and display with delay
################################################################################
for frame_num, frame in enumerate(output.frames):
    print(f'DEBUG: Playing back frame {frame_num}')
    im = cv2.imdecode(np.frombuffer(frame, dtype=np.uint8), cv2.IMREAD_COLOR)
    cv2.imshow('Slow Motion Replay', im)
    cv2.waitKey(64)

运行时,输出如下所示:

Recording frames of 1024x768 at 60 fps for 8 seconds
DEBUG: New frame of 26661 bytes
DEBUG: New frame of 33335 bytes
DEBUG: New frame of 33558 bytes
DEBUG: New frame of 34146 bytes
...
...
DEBUG: New frame of 34208 bytes
DEBUG: New frame of 34408 bytes
DEBUG: New frame of 34356 bytes
DEBUG: New frame of 34248 bytes
Captured 480 frames at 59.763 fps, average bytes/frame=36938, total RAM=16.909 MB

正如您所看到的,它仅使用 17MB 的 RAM 来实现 8s 的 60fps @ 1024x768 像素,不到 1GB RasPi 3 的 RAM 的 2%,不到 4GB RasPi 4 的 0.5%,因此您可以运行更长时间而不会用完内存。

然后它会立即以四分之一的速度播放。这是录制 iPhone 高速计时器后播放的迷你动画 GIF:

在此处输入图像描述

注意 1:您不必使用OpenCV进行播放,您可以使用任何其他可以显示 JPEG 的包。

注意 2:您可以在重放循环中显示图像之前调整图像大小、对其进行注释或以某种方式对其进行处理。

注意 3:请注意,您可以将cv2.imshow()回放循环中的 替换为对OpenCV VideoWriter()的调用并将视频保存到磁盘,而不是根据需要将其显示在屏幕上。

注意 4:您可以添加一个quality参数camera.start_recording()来控制图像质量/大小。或者您可以更改为原始 RGB 或 YUV 格式。

关键词:RasPi、Raspberry Pi、RaspberryPi、图像处理、视频录制、PiCamera、高速、高速、60 fps、慢动作、慢动作、慢动作、缓冲区、内存中缓冲、回放。

于 2020-12-31T11:44:22.100 回答