Aby robić zdjęcia za pomocą aparatu fotograficznego w 0,025 s, potrzebujesz szybkości klatek większej lub równej 80 fps. Powodem, dla którego wymagane jest 80, a raczej 40 klatek na sekundę (biorąc pod uwagę, że 1 / 0,025 = 40) jest to, że obecnie istnieje problem, który powoduje, że każda inna klatka jest pomijana w koderze wielu obrazów, więc efektywna szybkość przechwytywania kończy się o połowę liczby klatek na sekundę w aparacie.
Moduł aparatu Pi jest zdolny do 80 klatek na sekundę w późniejszych wersjach oprogramowania układowego (patrz tryby aparatu w dokumentacji aparatu), ale tylko przy rozdzielczości VGA (prośby o wyższe rozdzielczości z liczbą klatek na sekundę> 30 klatek na sekundę spowodują zwiększenie rozdzielczości z VGA do żądanej rozdzielczości, więc jest to ograniczenie, z którym miałbyś do czynienia nawet przy 40 klatkach na sekundę). Innym problemem, który prawdopodobnie napotkasz, są ograniczenia prędkości karty SD. Innymi słowy, prawdopodobnie będziesz musiał przechwycić coś szybciej, jak port sieciowy lub strumienie w pamięci (zakładając, że wszystkie obrazy, które musisz przechwycić zmieści się w pamięci RAM).
Poniższy skrypt daje mi szybkość przechwytywania ~ 38 fps (tj. Nieco powyżej 0,025 s na zdjęcie) na Pi z podkręcaniem ustawionym na 900 MHz:
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)))
Jeśli chcesz zrobić coś pomiędzy każdą ramką, jest to możliwe nawet capture_sequence
poprzez podanie funkcji generatora zamiast listy wyjść:
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)))
Należy pamiętać, że w powyższym przykładzie przetwarzanie odbywa się szeregowo przed następnym przechwytywaniem (tzn. Każde wykonane przetwarzanie koniecznie opóźnia następne przechwytywanie). Możliwe jest zmniejszenie tego opóźnienia dzięki sztuczkom wątkowym, ale powoduje to pewną złożoność.
Możesz także zajrzeć do niezakodowanych przechwytywania do przetwarzania (które usuwają narzut związany z kodowaniem, a następnie dekodowaniem plików JPEG). Należy jednak pamiętać, że procesor Pi jest niewielki (szczególnie w porównaniu do GPU VideoCore). Chociaż możesz być w stanie uchwycić przy 40 klatkach na sekundę, nie ma mowy, abyś był w stanie wykonać jakiekolwiek poważne przetwarzanie tych klatek przy 40 klatkach na sekundę, nawet przy wszystkich wymienionych wyżej sztuczkach. Jedynym realistycznym sposobem wykonywania przetwarzania ramek z tą prędkością jest wysyłanie ramek przez sieć na szybszą maszynę lub przetwarzanie na GPU.