Para tirar fotos em 0,025s com a câmera, você precisará de uma taxa de quadros maior ou igual a 80fps. A razão para exigir 80 fps a 40 fps (considerando que 1 / 0,025 = 40) é que atualmente há algum problema que faz com que todos os outros quadros sejam pulados no codificador de imagem múltipla, para que a taxa de captura efetiva seja metade da taxa de quadros da câmera.
O módulo de câmera do Pi é capaz de 80fps em firmwares posteriores (consulte os modos de câmera nos documentos da picamera), mas apenas em uma resolução VGA (solicitações de resoluções mais altas com taxas de quadros> 30fps resultarão no aumento do VGA para a resolução solicitada, portanto, isso é uma limitação que você enfrentaria mesmo a 40fps). O outro problema que você provavelmente encontrará são as limitações de velocidade do cartão SD. Em outras palavras, você provavelmente precisará capturar algo mais rápido, como uma porta de rede ou fluxos na memória (assumindo que todas as imagens que você precisa capturar caberão na RAM).
O script a seguir me dá uma taxa de captura de ~ 38fps (ou seja, logo acima de 0,025s por foto) em um Pi com overclock definido em 900Mhz:
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)))
Se você deseja fazer algo entre cada quadro, isso é possível mesmo capture_sequence
fornecendo uma função de gerador em vez de uma lista de saídas:
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)))
Lembre-se de que, no exemplo acima, o processamento ocorre em série antes da próxima captura (ou seja, qualquer processamento que você faça necessariamente atrasará a próxima captura). É possível reduzir essa latência com truques de segmentação, mas isso envolve uma certa complexidade.
Você também pode procurar capturas não codificadas para processamento (que removem a sobrecarga de codificação e, em seguida, decodificam JPEGs). No entanto, lembre-se de que a CPU do Pi é pequena (especialmente em comparação com a GPU VideoCore). Embora você possa capturar a 40fps, não há como executar qualquer processamento sério desses quadros a 40fps, mesmo com todos os truques mencionados acima. A única maneira realista de executar o processamento de quadros nessa taxa é enviá-los por uma rede para uma máquina mais rápida ou executar o processamento na GPU.