Делайте снимки за короткое время с помощью модуля камеры Raspberry Pi

13

Я работаю над проектом, в котором мне нужно делать около 30 изображений в секунду (без фильма), используя модуль камеры Raspberry Pi.

Для этого я использую библиотеку Picamera ( http://picamera.readthedocs.org/en/latest/api.html ), но проблема в том, что съемка занимает около 0,2 - 0,4 секунды, что очень долго. Я уже установил use_video_portсвойство True, что немного помогло, но время все еще слишком велико.

Кто-нибудь из вас знает, как делать короткие снимки (около 0,025 с), используя Python и модуль камеры Raspberry Pi?

Тимо Денк
источник

Ответы:

18

Чтобы сделать снимки в 0,025 с с помощью Picamera, вам потребуется частота кадров, превышающая или равная 80 кадр / с. Причина, по которой требуется 80, а не 40 кадров в секунду (учитывая, что 1 / 0,025 = 40), заключается в том, что в настоящее время существует некоторая проблема, которая заставляет пропускать каждый второй кадр в кодировщике с несколькими изображениями, поэтому эффективная скорость захвата сводится к половине частоты кадров камеры.

Модуль камеры Pi способен работать со скоростью 80 кадров в секунду в более поздних прошивках (см. Режимы камеры в документации Picamera), но только с разрешением VGA (запросы на более высокие разрешения с частотой кадров> 30 кадров в секунду приведут к повышению масштаба с VGA до требуемого разрешения, поэтому это ограничение, с которым вы столкнетесь даже на 40fps). Другая проблема, с которой вы, вероятно, столкнетесь, - это ограничения скорости SD-карты. Другими словами, вам, вероятно, понадобится записать что-то более быстрое, например, сетевой порт или потоки в памяти (при условии, что все изображения, которые вам нужно захватить, поместятся в ОЗУ).

Следующий скрипт дает мне скорость захвата ~ 38 кадров в секунду (то есть чуть выше 0,025 с на картинку) на Pi с разгоном, установленным на 900 МГц:

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 маленький (особенно по сравнению с GPU VideoCore). В то время как вы можете быть в состоянии захвата в 40fps, нет никакого способа , вы собираетесь быть в состоянии выполнить любую серьезную обработку этих кадров в 40fps даже со всеми трюками , упомянутых выше. Единственный реалистичный способ выполнить обработку кадров с такой скоростью - это отправить кадры по сети на более быстрый компьютер или выполнить обработку на графическом процессоре.

Дейв Джонс
источник
Спасибо за ваш быстрый ответ! Но в вашей программе я не смогу обрабатывать отдельные картинки во время работы .capture_sequence, верно? Есть ли способ сделать это? Потому что мне нужно поработать с каждой отдельной картинкой, прежде чем следующая лексема.
Тимо Денк
1
Изменен ответ, чтобы включить метод выполнения обработки между кадрами с функцией генератора.
Дейв Джонс
.capture_sequence игнорирует KeyboardInterrupts. Вы знаете, как обойти это?
Cerin
@ Какое будет потребление энергии на чем-то подобном?
Тед Тейлор из Life
Fps быстр для этого решения, но как сохранить изображения в файлы из потока?
Бакалоло
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 из альтернативного репозитория.

HeatfanJohn
источник