Per scattare foto in 0,025 secondi con Picamera è necessario un frame rate maggiore o uguale a 80 fps. La ragione per richiedere 80 piuttosto 40 fps (dato che 1 / 0,025 = 40) è che attualmente c'è qualche problema che fa saltare ogni altro fotogramma nell'encoder multi-immagine in modo che la velocità di acquisizione effettiva finisca per metà del framerate della fotocamera.
Il modulo fotocamera del Pi è in grado di 80 fps nei firmware successivi (vedere le modalità della fotocamera nei documenti di Picamera), ma solo con una risoluzione VGA (richieste di risoluzioni più elevate con framerate> 30 fps comporteranno l'upscaling da VGA alla risoluzione richiesta, quindi questo è una limitazione che dovresti affrontare anche a 40 fps). L'altro problema che probabilmente incontrerai sono i limiti di velocità della scheda SD. In altre parole, probabilmente dovrai catturare qualcosa di più veloce come una porta di rete o flussi in memoria (supponendo che tutte le immagini che devi catturare si adattino alla RAM).
Il seguente script mi dà una velocità di acquisizione di ~ 38fps (cioè appena sopra 0,025s per foto) su un Pi con overclock impostato su 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 si desidera fare qualcosa tra un frame e l'altro, ciò è possibile anche capture_sequence
fornendo una funzione del generatore anziché un elenco di output:
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)))
Tenere presente che nell'esempio sopra, l'elaborazione avviene in serie prima della successiva acquisizione (ovvero qualsiasi elaborazione effettuata ritarderà necessariamente la successiva acquisizione). È possibile ridurre questa latenza con trucchi di threading, ma ciò comporta una certa complessità.
Potresti anche voler esaminare le acquisizioni non codificate per l'elaborazione (che rimuovono il sovraccarico della codifica e quindi della decodifica dei JPEG). Tuttavia, tieni presente che la CPU del Pi è piccola (soprattutto rispetto alla GPU VideoCore). Mentre potresti essere in grado di catturare a 40fps, non puoi assolutamente eseguire alcuna elaborazione seria di quei frame a 40fps anche con tutti i trucchi sopra menzionati. L'unico modo realistico per eseguire l'elaborazione dei frame a tale velocità è spedire i frame su una rete a una macchina più veloce o eseguire l'elaborazione sulla GPU.