首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在树莓Pi上保存图像流的最快方法

在树莓Pi上保存图像流的最快方法
EN

Stack Overflow用户
提问于 2019-12-09 18:36:34
回答 1查看 2.2K关注 0票数 4

我们有一个摄像头连接到一个覆盆子Pi 4通过USB3。该相机只能提供原始图像2056x1542x3,我们可以在30 FPS左右读取。在Raspberry Pi 4中,我们需要将这些图像保存到磁盘上--由于空间和写入SD卡的速度,因此无论如何保存原始图像(10 MB/件)是不可行的。相反,我们希望压缩这些图像,然后尽快保存它们。

我们的当前解决方案看起来类似于下面的片段:

代码语言:javascript
复制
def save_image(frame,filename):
    cv2.imwrite(filename,frame)

...

(ret, frame) = cam.get_next_frame()
if ret == IS_SUCCESS:
    timestamp = get_timestamp()
    filename = conf["cv_image_folder"] + timestamp + ".jpg"
    save_thread = threading.Thread(target=save_image, args=(frame,filename,))
    save_thread.start()

OpenCV是用libjpeg-turbo和所有可能的HW标志编译的,用于加速计算.在大约5或6个FPS,树莓Pi 4使用约100%的所有4个核心。非线程配置也是如此。我们在摄像机上手动设置框架,并监视生成的线程数(大约在5-6FPS处有3-4个并发线程)。我们选择JPEG (尽管它是有损的),因为PNG或TIFF压缩需要更长的计算时间。

有什么办法可以改善这种情况吗?

EN

回答 1

Stack Overflow用户

发布于 2019-12-13 11:14:23

我认为Dan的发现,你可以得到拜耳图像将证明你的问题的解决方案,但我做了一些工作,使用博通的MMAL的MMAL“多媒体抽象层”进行VideoCore GPU上的JPEG编码,以减少CPU负荷,并想把它放在这里。它可能被证明是有用的,结合丹的建议和/或其他人寻求做类似的事情。

由于在GPU上运行,它可以以每秒大约4帧的速度将您的(相当大的)映像编码到磁盘上,同时几乎不使用。我观察到3个CPU核心是空闲的,第四个核心在10-15%的使用率上下徘徊。

代码只获取一个名为"image.jpg"的映像,并将其调整到您正在使用的维度,然后重复对其进行编码,并将其发送到磁盘100次。

代码语言:javascript
复制
#!/usr/bin/env python3

import io
import numpy as np
from picamera import mmal, mmalobj as mo
from PIL import Image
from threading import Event

# Globals
w, h = 2048, 1536      # These seem to need to be multiples of 64, or maybe 16
EncoderAvail = Event()
EncoderAvail.set()

# Set up MMAL-based JPEG encoding
encoder = mo.MMALImageEncoder()
encoder.inputs
encoder.inputs[0].format = mmal.MMAL_ENCODING_RGB24
encoder.inputs[0].framesize = (w, h)
encoder.inputs[0].commit()
encoder.outputs[0].copy_from(encoder.inputs[0])
encoder.outputs[0].format = mmal.MMAL_ENCODING_JPEG
encoder.outputs[0].commit()
encoder.outputs[0].params[mmal.MMAL_PARAMETER_JPEG_Q_FACTOR] = 90

def image_callback(port, buf):
    with open(f"frame-{frame}.jpg", 'wb') as jpeg:
        jpeg.write(buf.data)
        EncoderAvail.set()
    #return bool(buf.flags & mmal.MMAL_BUFFER_HEADER_FLAG_FRAME_END)
    return True

encoder.outputs[0].enable(image_callback)
encoder.inputs[0].enable(lambda port, buf: True)

# Encode the same image repeatedly as we are measuring the encode time not acquire time
im = Image.open('image.jpg').resize((w,h))
rgb_data = np.array(im)

for frame in range(100):
    print(f"Frame: {frame}")

    # Make red bar across top that gets longer with each frame to be sure we are getting them all
    rgb_data[0:10,:frame,0] = 255

    EncoderAvail.wait()
    buf = encoder.inputs[0].get_buffer()
    buf.data = rgb_data[:]
    EncoderAvail.clear()
    encoder.inputs[0].send_buffer(buf)

encoder.outputs[0].disable()
encoder.inputs[0].disable()

代码在很大程度上是基于Picamera的东西- 这里。代码可能不是最优的--例如,我不知道如何将缓冲区的数量增加到2,这将启用双缓冲,并且可能会产生很大的影响。我也不知道如何使它更多的事件驱动,因为它是相当同步的。

正如我所说的,通过更改mmal.MMAL_ENCODING_RGB24,您可以将它更改为将拜耳图像编码为JPEG,这样您就可以仍然使用它。

如果有人知道更多关于MMAL的东西,并能够改进它,请随时接受我的代码,改进它,并添加它作为一个新的答案,让我知道,这样我们都可以学习。

我注意到,它目前似乎也没有遵守JPEG质量设置,所以如果有人可以改进,请告诉我。

关键词:覆盆子Pi,GPU,JPEG编码,JPEG编码器,MMAL,视频GPU,Broadcom,多媒体抽象层,Raspi。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59254780

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档