13.1.10. Samostalni prozori terminala

Tools → Open Terminal otvara neovisne prozore terminala – svaki je minijaturna sesija OpenMV IDE-a u vlastitom prozoru, s preglednikom međuspremnika slike, histogramom i interaktivnim terminalom, povezanim preko prijenosa po vašem izboru. Veza glavnog prozora pritom ostaje netaknuta, pa vam samostalni terminal omogućuje da promatrate drugu kameru dok prva ostaje povezana, ili da otklanjate pogreške na kameri s druge strane mreže.

Samostalni prozor terminala: interaktivni terminal s lijeve strane sa svojom alatnom trakom, međuspremnik slike i histogram s desne strane

Samostalni prozor terminala preko serijskog porta: interaktivni terminal s lijeve strane sa svojom alatnom trakom za pokretanje / zaustavljanje / resetiranje, međuspremnik slike i histogram s desne strane – oni se aktiviraju kad kamera unutar toka šalje sličice.

New Terminal traži jedan od tri prijenosa:

  • Serial port – bilo koji serijski port s bilo kojom brzinom prijenosa (baud) (zadano 115.200). To obuhvaća USB port druge kamere, kameru spojenu preko USB-to-UART mosta, Bluetooth serijsku vezu (koja se prikazuje kao običan serijski port) ili bilo koji ne-OpenMV serijski uređaj kojem treba terminal. Na USB portu brzina prijenosa (baud) ne ograničava brzinu – podaci se uvijek kreću brzinom USB veze – ali na USB portu kamere izbjegavajte 921.600 i 12.000.000, koji prebacuju kameru iz REPL-a u IDE-ov protokol za otklanjanje pogrešaka.

  • TCP – spojite se na poslužitelj na odabranom hostu i portu, ili sami osluškujte kao poslužitelj na odabranom portu.

  • UDP – isti par uloga, preko UDP-a.

IDE pamti zadnjih deset konfiguracija i navodi ih u podizborniku Open Terminal radi ponovnog otvaranja jednim klikom; Clear Menu ih zaboravlja.

Za razliku od okna za izlaz glavnog prozora, koje služi samo za ispis, samostalni terminal je potpuno interaktivan: to je REPL. Pišite na upitu i Python se izvršava na povezanoj kameri redak po redak, uz povijest i dovršavanje tipkom tab koje pruža sam MicroPython. Alatna traka dodaje ekvivalente uobičajenih kontrolnih sekvenci jednim klikom – pokretanje trenutne skripte u uređivaču, zaustavljanje pokrenute skripte i meki reset – te iste kontrole za brisanje, spremanje i prelamanje kao u glavnom oknu terminala.

Međuspremnik slike iznad terminala također je uživo. Kad povezana kamera unutar toka šalje komprimirane sličice – ugrađene u isti tok kao i njezin ispis – terminal ih dekodira i prikazuje, a gumbi Record i Zoom rade točno kao u glavnom prozoru. Ta kombinacija je IDE-ova priča o otklanjanju pogrešaka preko mreže: kamera koja izlaže svoj REPL preko Wi-Fi-ja dobiva potpunu petlju uredi-pokreni-pregledaj bez ijednog USB kabela.

13.1.10.1. Slanje sličica unutar toka

Kodiranje koje terminal razumije jednostavno je: bajt 0xFE otvara sličicu, drugi 0xFE je zatvara, a svaki bajt korisnog sadržaja između njih ima postavljen najviši bit i nosi šest bitova komprimirane slike – tri bajta slike postaju četiri bajta korisnog sadržaja. Običan tekst nikad ne koristi te vrijednosti bajtova, pa sličice i izlaz print() dijele tok bez sudara: terminal prikazuje tekst i prikazuje sličice.

Skripta u nastavku snima, pretvara svaku sličicu u JPEG i ispisuje je u tom obliku. Pakiranje bitova izvodi se preko ulab (koji nema operatore pomaka, pa su pomaci napisani kao množenja i dijeljenja) i dovoljno je brzo da prati kameru:

import csi
import sys
import time
from ulab import numpy as np

csi0 = csi.CSI()
csi0.reset()
csi0.pixformat(csi.RGB565)
csi0.framesize(csi.QVGA)

clock = time.clock()


def encode_for_ide(data):
    n = len(data)
    n3 = n - (n % 3)
    m = (n3 // 3) * 4
    out = bytearray(((n * 8) + 5) // 6 + 2)
    out[0] = 0xFE
    out[-1] = 0xFE
    if n3:
        src = np.frombuffer(data, dtype=np.uint8)
        dst = np.frombuffer(out, dtype=np.uint8)
        b0 = src[0:n3:3]
        b1 = src[1:n3:3]
        b2 = src[2:n3:3]
        dst[1:m + 1:4] = (b0 & 0x3F) | 0x80
        dst[2:m + 2:4] = (b0 // 64) | ((b1 & 0x0F) * 4) | 0x80
        dst[3:m + 3:4] = (b1 // 16) | ((b2 & 0x03) * 16) | 0x80
        dst[4:m + 4:4] = (b2 // 4) | 0x80
    if n % 3 == 2:
        x = data[n - 2] | (data[n - 1] << 8)
        out[m + 1] = 0x80 | (x & 0x3F)
        out[m + 2] = 0x80 | ((x >> 6) & 0x3F)
        out[m + 3] = 0x80 | ((x >> 12) & 0x3F)
    elif n % 3 == 1:
        out[m + 1] = 0x80 | (data[n - 1] & 0x3F)
        out[m + 2] = 0x80 | (data[n - 1] >> 6)
    return out


while True:
    clock.tick()
    img = csi0.snapshot().to_jpeg(quality=80)
    sys.stdout.write(encode_for_ide(img.bytearray()))
    print(clock.fps())

Ovo radi u samostalnom terminalu jer ispis u REPL-u čeka: kamera blokira dok terminal ne preuzme podatke, pa stiže svaki bajt sličice, a JPEG se brzo kreće preko USB veze pune ili velike brzine. Ista skripta radi nepromijenjena preko TCP terminala, što je put otklanjanja pogrešaka preko mreže opisan gore. Jedino mjesto gdje ne radi jest IDE-ova glavna veza za otklanjanje pogrešaka, čiji se izlazni kanal pri preopterećenju sam resetira umjesto da čeka – ondje preglednik međuspremnika slike već izvorno prikazuje sličice kamere, pa se ništa ne propušta.