13.3.1.3. Çerçeveleri akışla aktarma

Kamerada çerçeveleri yakalayan bir betik, her çerçeveyi USB üzerinden ana bilgisayara geri akışla aktarabilir. Bu kalıp, openmv.Camera örneği üzerinde iki çağrıdan oluşur: akışı açıp kapatmak için streaming() ve kanaldan bir sonraki çerçeveyi çekmek için read_frame().

13.3.1.3.1. Minimal bir akış ve görüntüleme döngüsü

Kamera tarafındaki betik her zamanki anlık görüntü döngüsüdür; yeni olan, ana bilgisayarın akışı açması ve sonucu geri okumasıdır:

from openmv import Camera

script = """
import csi
csi0 = csi.CSI()
csi0.reset()
csi0.pixformat(csi.RGB565)
csi0.framesize(csi.QVGA)
while True:
    csi0.snapshot()
"""

with Camera('/dev/ttyACM0') as cam:
    cam.stop()
    cam.exec(script)
    cam.streaming(True)

    while True:
        if frame := cam.read_frame():
            print(f"{frame['width']}x{frame['height']}, "
                  f"{frame['raw_size']} bytes")

Kamera çerçeveleri sürekli yakalar; ana bilgisayar her biri ulaştıkça onu akış arabelleğinden çeker. Kamera her yeni anlık görüntüde akış arabelleğinin üzerine yazar, bu yüzden kameranın yakaladığından daha yavaş sorgulayan bir ana bilgisayar sessizce çerçeveleri düşürür – bu da görüntüleyici tarzı kullanım senaryoları için doğru davranıştır.

13.3.1.3.2. Çerçeve sözlüğü

read_frame() ya None (bekleyen çerçeve yok) ya da beş girdiye sahip bir dict döndürür:

Anahtar

Anlamı

width

Çerçeve genişliği (piksel cinsinden).

height

Çerçeve yüksekliği (piksel cinsinden).

format

Kameranın bildirdiği piksel formatı tanımlayıcısı (kameranın csi sabitlerinden bir tamsayı).

depth

Sıkıştırılmış formatlar (JPEG, PNG) için sıkıştırılmış görüntünün bayt cinsinden boyutu. Sıkıştırılmamış formatlar için kullanılmaz.

data

Çerçeve, RGB888 biçiminde bir bytes arabelleği olarak. Her piksel üç bayttır (R, G, B); toplam uzunluk width * height * 3 değeridir.

raw_size

Kameranın çözmeden önce USB üzerinden gönderdiği baytlar. Gerçek iş hacmi hesaplaması için kullanışlıdır.

Paket, döndürmeden önce kameranın yerel formatını (GRAYSCALE, RGB565, JPEG) RGB888 biçimine dönüştürür, böylece ana bilgisayar hiçbir zaman bit ile paketlenmiş RGB565 veya JPEG çözme yolunu kendisi ele almak zorunda kalmaz. Gri tonlama çerçeveleri, luma değeri üç kanalın tümüne kopyalanmış olarak geri gelir.

data arabelleği yukarıdan aşağıya, satır satır düzenlenir; doğrudan bir görüntüleme kitaplığına vermek veya ham bir RGB dosyası olarak kaydetmek, başka herhangi bir düzenleme yapmadan çalışır.

13.3.1.3.3. Ham akış modu

Varsayılan olarak kamera, yakaladığı her çerçeveyi akış kanalına yerleştirmeden önce JPEG ile sıkıştırır ve read_frame() ana bilgisayarda sıkıştırmayı açar. Donanımsal JPEG desteği olmayan kameralarda yazılımsal sıkıştırma, döngüdeki en yavaş adımdır. raw=True geçirmek bunu atlar:

cam.streaming(True, raw=True, resolution=(320, 240))

Kamera o zaman piksel arabelleğini sıkıştırmadan gönderir. Sıkıştırılmamış çerçeveler JPEG eşdeğerlerinden çok daha büyüktür, bu yüzden kamera, göndermeden önce yakaladığı her çerçeveyi akış kanalına sığacak şekilde küçültür; resolution=(width, height) argümanı bu hedefi ayarlar. Ana bilgisayar yine de data alanında RGB888 alır – paket, kameranın format içinde bildirdiği piksel formatından dönüştürür.

13.3.1.3.4. Döngüyü olayların yönetmesine izin verme

read_frame() çağrısını kameranın çerçeve üretebildiğinden daha hızlı yapan bir sorgulama döngüsü, zamanının çoğunu None geri alarak geçirir. Ana bilgisayarın yapacak başka işleri de olduğunda (güncellenecek bir arayüz, sorgulanacak başka kanallar), read_status() daha ucuz bir kontroldür: kayıtlı her kanal adını “veri hazır” boole değerine eşleyen bir sözlük döndürür:

while True:
    status = cam.read_status()

    if status.get('stream'):
        frame = cam.read_frame()
        # ... process the frame ...

    if status.get('stdout'):
        text = cam.read_stdout()
        print(text, end='')

    if status.get('my_channel'):
        data = cam.channel_read('my_channel')
        # ... process custom-channel data ...

CLI görüntüleyicisinin kendisinin kullandığı döngü şekli budur.

13.3.1.3.5. Akışı durdurma

Durdurmak için streaming() çağrısını enable=False ile yapın. Kamera betiğini çalıştırmaya devam eder ancak artık akış arabelleğini doldurmaz; read_frame() o noktadan itibaren yalnızca None döndürür. stop() çağrısı, betiği durdurarak aynı şeyi örtük olarak yapar.