使用Raspberry Pi相机模块在短时间内拍摄图像


13

我正在一个项目中,我需要使用Raspberry Pi摄像头模块每秒拍摄约30张图像(无电影)。

我正在为此使用Picamera库(http://picamera.readthedocs.org/en/latest/api.html),但是问题是,拍摄照片大约需要0.2-0.4秒,这很长。我已经将该use_video_port属性设置为True,这有所帮助,但是时间仍然很长。

你们中没人知道如何使用Python和Raspberry Pi相机模块在短时间内(约0.025s)拍照吗?

Answers:


18

要使用picamera在0.025s内拍摄照片,您需要帧速率大于或等于80fps。之所以要求80而不是40fps(假设1 / 0.025 = 40),是因为目前存在一些问题,导致多图像编码器中的每隔一帧都被跳过,因此有效捕获率最终达到相机帧率的一半。

Pi的摄像头模块在更高版本的固件中能够达到80fps(请参阅picamera文档中的摄像头模式),但是仅在VGA分辨率下(要求帧速率> 30fps的更高分辨率将导致从VGA升级到所需分辨率,因此这是甚至在40fps时也会遇到的限制)。您可能会遇到的另一个问题是SD卡速度限制。换句话说,您可能需要更快地捕获到某些东西,例如网络端口或内存中的流(假设您需要捕获的所有图像都可以放入RAM中)。

以下脚本使我在超频设置为900Mhz的Pi上的捕获率为〜38fps(即,每张图片略高于0.025s):

import io
import time
import picamera

with picamera.PiCamera() as camera:
    # Set the camera's resolution to VGA @40fps and give it a couple
    # of seconds to measure exposure etc.
    camera.resolution = (640, 480)
    camera.framerate = 80
    time.sleep(2)
    # Set up 40 in-memory streams
    outputs = [io.BytesIO() for i in range(40)]
    start = time.time()
    camera.capture_sequence(outputs, 'jpeg', use_video_port=True)
    finish = time.time()
    # How fast were we?
    print('Captured 40 images at %.2ffps' % (40 / (finish - start)))

如果您希望在每个帧之间做某事,即使capture_sequence提供了生成器功能而不是输出列表,也可以做到这一点:

import io
import time
import picamera
#from PIL import Image

def outputs():
    stream = io.BytesIO()
    for i in range(40):
        # This returns the stream for the camera to capture to
        yield stream
        # Once the capture is complete, the loop continues here
        # (read up on generator functions in Python to understand
        # the yield statement). Here you could do some processing
        # on the image...
        #stream.seek(0)
        #img = Image.open(stream)
        # Finally, reset the stream for the next capture
        stream.seek(0)
        stream.truncate()

with picamera.PiCamera() as camera:
    camera.resolution = (640, 480)
    camera.framerate = 80
    time.sleep(2)
    start = time.time()
    camera.capture_sequence(outputs(), 'jpeg', use_video_port=True)
    finish = time.time()
    print('Captured 40 images at %.2ffps' % (40 / (finish - start)))

请记住,在上面的示例中,该处理是在下一次捕获之前按顺序进行的(即您执行的任何处理都必然会延迟下一次捕获)。可以通过线程技巧减少此延迟,但是这样做会带来一定程度的复杂性。

您可能还希望研究未编码的捕获以进行处理(这样可以消除编码和解码JPEG的开销)。但是,请记住,Pi的CPU 很小(尤其是与VideoCore GPU相比)。尽管您可以以40fps的速度捕获,但是即使有上述所有技巧,也无法以40fps的速度对那些帧进行任何认真的处理。以这种速率执行帧处理的唯一现实方法是通过网络将帧发送到更快的计算机,或在GPU上执行处理。


感谢您的快速回复!但是在您的程序中,运行.capture_sequence时,我将无法处理单个图片,对吗?有没有办法做到这一点?因为我需要处理每个单独的图片,否则下一个是令牌。
Timo Denk 2014年

1
将答案修改为包括一种使用生成器功能在帧之间执行处理的方法。
戴夫·琼斯

.capture_sequence似乎忽略了KeyboardInterrupts。您知道如何解决此问题吗?
塞林2015年

@Cerin这样的功耗是多少?
泰德·泰勒

对于该解决方案,fps速度很快,但是如何将图像保存到流中的文件中呢?
bakalolo

4

根据此StackOverflow答案,您可以使用gstreamer和以下命令来完成所需的操作:

raspivid -n -t 1000000 -vf -b 2000000 -fps 25 -o - | gst-launch-1.0 fdsrc ! video/x-h264,framerate=25/1,stream-format=byte-stream ! decodebin ! videorate ! video/x-raw,framerate=10/1 ! videoconvert ! jpegenc ! multifilesink location=img_%04d.jpg

此命令似乎采用raspivid的视频输出来生成每秒25帧的视频流,然后使用gstreamer将视频转换为单个jpeg图像。

本文提供有关如何从备用存储库安装gstreamer1.0的说明。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.