Raspberry Pi kamera modülünü kullanarak kısa sürede görüntü çekin


13

Raspberry Pi kamera modülünü kullanarak saniyede yaklaşık 30 görüntü çekmem gereken bir proje üzerinde çalışıyorum.

Bunun için Picamera kütüphanesini kullanıyorum ( http://picamera.readthedocs.org/en/latest/api.html ) ama sorun şu ki, uzun bir süre fotoğraf çekmek yaklaşık 0.2 - 0.4 saniye sürüyor. Zaten use_video_portözelliği ayarladım True, ki bu biraz yardımcı oldu, ama zaman hala uzun.

Python ve Raspberry Pi kamera modülünü kullanarak kısa sürede (yaklaşık 0,025 sn) fotoğraf çekmeyi bilen var mı?

Yanıtlar:


18

Picamera ile 0,025s içinde fotoğraf çekmek için 80 fps veya daha yüksek bir kare hızına ihtiyacınız olacaktır. 80 yerine 40 fps gerektirmesinin nedeni (1 / 0.025 = 40 olduğu göz önüne alındığında), şu anda diğer tüm karelerin çoklu görüntü kodlayıcısında atlanmasına neden olan ve böylece etkili yakalama oranının kameranın kare hızının yarısı kadar azalmasına neden olan bir sorun olmasıdır.

Pi'nin kamera modülü, daha sonraki yazılımlarda 80 kare / saniye kapasiteye sahiptir (picamera belgelerindeki kamera modlarına bakın ), ancak yalnızca bir VGA çözünürlüğünde (30 kare / sn'den büyük çerçevelerle daha yüksek çözünürlük talepleri, VGA'dan istenen çözünürlüğe yükseltilmesine neden olur, bu nedenle 40 fps'de bile karşılaşacağınız bir sınırlama). Karşılaşabileceğiniz diğer sorun SD kart hız sınırlamalarıdır. Başka bir deyişle, muhtemelen bir ağ bağlantı noktası veya bellek içi akışlar gibi daha hızlı bir şey yakalamanız gerekir (yakalamanız gereken tüm görüntülerin RAM'e sığacağı varsayılarak).

Aşağıdaki komut dosyası, overclock özelliği 900Mhz olarak ayarlanmış bir Pi'de ~ 38fps (yani resim başına 0.025s'in hemen üzerinde) yakalama oranı sağlıyor:

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)))

Her kare arasında bir şey yapmak istiyorsanız, bu, capture_sequenceçıktı listesi yerine bir jeneratör işlevi sağlayarak bile mümkündür :

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)))

Yukarıdaki örnekte, işlemin bir sonraki yakalamadan önce seri olarak gerçekleştiğini unutmayın (yani, yaptığınız herhangi bir işlem bir sonraki yakalamayı geciktirecektir). Bu gecikmeyi diş çekme hileleriyle azaltmak mümkündür, ancak bunu yapmak belirli bir karmaşıklık gerektirir.

Ayrıca, işleme için kodlanmamış yakalamalara bakmak isteyebilirsiniz (bu, kodlama yükünü kaldırarak JPEG'lerin kodunu çözer). Bununla birlikte, Pi'nin CPU'sunun küçük olduğunu unutmayın (özellikle VideoCore GPU ile karşılaştırıldığında). 40 fps'de çekim yapabilmenize rağmen, yukarıda belirtilen tüm hilelerle bile bu karelerin 40 fps'de ciddi bir şekilde işlenmesinin bir yolu yoktur. Bu hızda çerçeve işlemeyi gerçekleştirmenin tek gerçekçi yolu, çerçeveleri bir ağ üzerinden daha hızlı bir makineye göndermek veya GPU üzerinde işlem yapmaktır.


Hızlı cevabınız için teşekkür ederim! Ama programınızda .capture_sequence çalışırken resimleri tek tek işleyemeyeceğim, değil mi? Bunu yapmanın bir yolu var mı? Çünkü bir sonraki belirteç olmadan önce her bir resim ile çalışmam gerekiyor.
Timo Denk

1
Yanıt, bir üreteç işlevine sahip kareler arasında işlem gerçekleştirme yöntemini içerecek şekilde değiştirildi.
Dave Jones

.capture_sequence, KeyboardInterrupts'ı yok sayıyor gibi görünüyor. Bu sorunu nasıl çözeceğinizi biliyor musunuz?
Cerin

@Cerin böyle bir şeydeki güç tüketimi ne olurdu?
Ted Taylor of Life

Bu çözüm için fps hızlıdır, ancak görüntüleri akıştan dosyalara nasıl kaydederim?
2018

4

Bu StackOverflow yanıtına göre, istediğinizi gerçekleştirmek için gstreamer ve aşağıdaki komutu kullanabilirsiniz:

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

Bu komut, saniyede 25 kare olan bir video akışı oluşturmak için raspivid'in video çıkışını alıyor ve ardından videoyu ayrı jpeg görüntülerine dönüştürmek için gstreamer kullanıyor.

Bu makalede , gstreamer1.0'ın alternatif bir havuzdan nasıl yükleneceği hakkında yönergeler verilmektedir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.