我正在一个项目中,需要使用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)拍照?

#1 楼

要使用picamera在0.025秒内拍摄照片,您需要帧速率大于或等于80fps。之所以需要80而不是40fps(假设1 / 0.025 = 40),是因为目前存在一些问题,导致多图像编码器中的每隔一帧都被跳过,因此有效捕获率最终达到相机帧率的一半。 br />
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年8月5日下午6:52

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

–戴夫·琼斯(Dave Jones)
2014年8月6日,1:15

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

–塞林
2015年10月19日,下午5:36

@Cerin这样的功耗是多少?

–泰德·泰勒(Ted Taylor)
16年8月30日在20:03

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

– bakalolo
18年6月29日在0:25

#2 楼

根据此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的说明。