13.1.9. Widok Kanały#

Bufor ramki pokazuje, co kamera widzi; widok Kanały pokazuje, co skrypt mierzy i decyduje. Skrypt publikuje nazwane wartości przez protokół debugowania – temperaturę, liczbę wykryć, przebieg z mikrofonu, mapę głębi z czujnika czasu przelotu lub element sterujący, który użytkownik ma móc zmieniać – a IDE renderuje każdą z nich na żywo jako widżet, wykres lub mapę w panelu pod buforem ramki. Niczego nie trzeba rysować na obrazie ani wyławiać z terminala. Po stronie kamery to kilka wierszy z protocol.CBORChannel; po stronie IDE to pozycja Kanały w selektorze panelu.

The Channels view showing a thermal camera script's controls channel: FPA and AUX temperature readouts with their unit, Measurement and High Temp toggles, Temp Min and Temp Max sliders, and H-Mirror and V-Flip toggles

Elementy sterujące skryptu kamery termowizyjnej: dwa odczyty temperatury, przełączniki trybów pomiaru i suwaki zakresu temperatur. Zmiana dowolnego z nich wysyła nową wartość do skryptu.#

Widok jest zorganizowany według kanałów. Każdy kanał zarejestrowany przez skrypt staje się sekcją z nazwą kanału jako nagłówkiem, a każdy rekord w kanale staje się wierszem pod nią, w kolejności, w jakiej skrypt je dodał. Gdy skrypt rejestruje kanał lub zmienia kształt któregoś z nich, widok odbudowuje się; gdy skrypt się zatrzymuje, ostatnie wartości pozostają na ekranie, z wyłączonymi elementami sterującymi, do uruchomienia następnego skryptu.

13.1.9.1. Widżety#

Odczyty i elementy sterujące przyjmują oczywiste formy. label (etykieta) to wartość tylko do odczytu z jednostką; rekord text to blok statycznego tekstu sformatowanego na nagłówki i objaśnienia. Rodzaje zapisywalne odsyłają nową wartość do skryptu w chwili, gdy ją zmienisz, a wywołanie zwrotne on_write skryptu otrzymuje nazwę rekordu i wartość: toggle to przełącznik, slider i spinbox ustawiają liczbę w zakresie i kroku skryptu (pole liczbowe do precyzyjnego wpisywania), przyciski radio i select wybierają jedną z opcji skryptu, lineedit to pole dowolnego tekstu, a pushbutton wyzwala chwilową akcję. Widok zachowuje Twoją zmianę na ekranie, zamiast cofać ją do ostatnio opublikowanej przez kamerę wartości, gdy zapis jest w toku.

Od strony skryptu cały zestaw to protocol.CBORChannel z jednym add na widżet i wywołaniem zwrotnym dla zapisów:

import time
import protocol
from protocol import CBORChannel

def on_write(ch, name, value):
    print(name, "=", value)      # every change lands here

ch = CBORChannel(on_write=on_write)
ch.add("Status", type="label", value="starting")
ch.add("Enable", type="toggle", value=True)
ch.add("Threshold", type="slider", min=0, max=100,
       step=1, value=50, unit="%")
ch.add("Mode", type="select",
       options=["Idle", "Track", "Record"], value="Idle")
ch.add("Calibrate", type="pushbutton")
protocol.register(name="controls", backend=ch)

while True:
    if ch["Enable"]:                   # read a control back
        ch["Status"] = "threshold %d%%" % ch["Threshold"]
    time.sleep_ms(100)

Uruchom go i przełącz panel na Kanały: pojawia się sekcja o nazwie controls z pięcioma widżetami, a przesuwanie suwaka wypisuje wartości w terminalu. Pozostałe typy widżetów – spinbox, radio, lineedit, text – to po jednym dodatkowym add każdy; rozdział o protokole hosta omawia je wszystkie.

13.1.9.2. Wykresy przebiegów#

Rekord waveform (przebiegu) to blok przeplatanych próbek z częstotliwością próbkowania – dźwięk, osie akcelerometru, przebieg z ADC – a widok rysuje go jako przewijany wykres, po jednej serii na oś, nazwanej przez skrypt. Elementy sterujące wykresu znajdują się na jego pasku narzędzi i na samym wykresie:

  • Przeciągaj, aby przesuwać, i przewijaj, aby powiększać; kliknij dwukrotnie, aby wrócić do śledzenia bieżącej krawędzi. Historia ustawia, ile przeszłych danych jest zachowywanych, abyś mógł się przez nie cofać.

  • Automatyczna skala dopasowuje oś pionową do danych; po wyłączeniu oś ma zakres zadeklarowany przez skrypt.

  • Kliknij wykres prawym przyciskiem myszy, aby ustawić znacznik i odczytać dokładny czas i wartość próbki, albo ustawić poziom wyzwalania. Gdy Wyzwalanie jest uzbrojone, wykres stoi w miejscu, dopóki sygnał nie przetnie poziomu na zboczu narastającym lub opadającym – oscyloskopowy sposób łapania stanów przejściowych – a Uzbrój ponownie czeka na następny.

  • Widmo przełącza wykres na wykres częstotliwościowy tych samych danych, z wyborem okna (Hanna, Hamminga, Blackmana, prostokątne), Uśrednianie i Zatrzymanie szczytu między ramkami oraz logarytmiczną osią częstotliwości (Częstotliwość log.). Odczyt pod wykresem podaje częstotliwość szczytu i jego poziom.

  • Pauza zamraża wykres bez wpływu na nagrywanie; Statystyki dodaje wiersz min / max / RMS; a menu prawego przycisku myszy zapisuje wykres jako obraz.

The Channels view with two waveform records scrolling live: a 16 kHz microphone trace and a three-series accelerometer trace with its X, Y, and Z legend, each with its Record, Spectrum, Pause, and Stats buttons

Dwa rekordy przebiegów przewijane na żywo: przebieg z mikrofonu i trzyseryjny przebieg z IMU.#

Pole przebiegu przyjmuje częstotliwość próbkowania oraz, dla kilku sygnałów naraz, liczbę przeplatanych series i ich nazwy; każda aktualizacja to surowe bajty array próbek w typecode pola:

import math
import time
import protocol
from array import array
from protocol import CBORChannel

RATE, CHUNK = 1000, 100            # 1 kHz, 100 ms per update

ch = CBORChannel()
ch.add("IMU", type="waveform", sample_rate=RATE, series=3,
       typecode="f", min=-2.0, max=2.0,
       options=["X", "Y", "Z"], unit="g")
protocol.register(name="signals", backend=ch)

t = 0
while True:
    block = array("f")
    for i in range(CHUNK):
        phase = 2 * math.pi * 2 * (t + i) / RATE
        block.extend((math.sin(phase), math.cos(phase), 1.0))
    ch["IMU"] = bytes(block)        # interleaved X, Y, Z
    t += CHUNK
    time.sleep_ms(100)

13.1.9.3. Mapy głębi#

Rekord depth (głębi) to siatka odległości – ramki produkowane przez czujnik czasu przelotu – a widok rysuje ją jako mapę w fałszywych kolorach powiększoną do wysokości wykresu. Pasek narzędzi wybiera sposób renderowania: paletę (własne palety kamery Depth, Rainbow i Ironbow oraz jasną i ciemną paletę dla kamer zdarzeniowych), filtr skalowania, który powiększa małą siatkę czujnika (bicubic dla gładkiej powierzchni, bilinear albo nearest dla jednego bloku na piksel czujnika), oraz mapowanie tonów, które zamienia odległość na kolor: Zakres skryptu używa zakresu zadeklarowanego przez skrypt, Zakres auto rozciąga kolory na odległości faktycznie obecne w każdej ramce (ignorując kilka procent wartości skrajnych), a Wyrównaj rozkłada je według rozkładu ramki, dzięki czemu płaska scena nadal pokazuje swoje szczegóły. Nagłówek podaje rozmiar mapy, zadeklarowany zakres oraz minimum, maksimum i średnią ramki; najechanie na mapę odczytuje odległość pod kursorem, a Zapisać obraz zapisuje wyrenderowaną mapę do pliku PNG.

The Channels view showing an 8 x 8 time-of-flight depth map scaled up smoothly with the Depth palette, the palette, scaling, and tone-mapping selectors in its toolbar, and the header reporting the size, declared range, and the frame's minimum, maximum, and mean

Mapa głębi z czujnika czasu przelotu pokazująca dłoń przed czujnikiem, z selektorami palety, skalowania i mapowania tonów na pasku narzędzi.#

Pole głębi deklaruje rozmiar siatki i zakres; każda aktualizacja to siatka jako upakowane 32-bitowe liczby zmiennoprzecinkowe, czyli to, co produkuje czytnik modułu tof:

import struct
import time
import tof
import protocol
from protocol import CBORChannel

tof.init()
ch = CBORChannel()
ch.add("depth", type="depth", width=tof.width(),
       height=tof.height(), min=0, max=1000)
protocol.register(name="ToF", backend=ch)

while True:
    try:
        d, dmin, dmax = tof.read_depth(vflip=True, hmirror=True)
    except RuntimeError:
        continue
    ch["depth"] = struct.pack("<%df" % len(d), *d)
    time.sleep_ms(50)

13.1.9.4. Nagrywanie#

Każdy wykres i mapa ma przycisk Rozpocznij nagrywanie, a kanał z więcej niż jednym z nich ma pasek Nagraj wszystko, który uruchamia je razem. Nagrywanie zapisuje dane w miarę ich napływania – nie rendering – do pliku, którego format wynika z rozszerzenia wybranego w oknie zapisu: CSV dla arkuszy kalkulacyjnych i narzędzi do wykresów, WAV dla jednokanałowych przebiegów dźwiękowych, tablice NumPy .npy dla Pythona oraz Edge Impulse JSON lub CBOR do przesłania wprost do projektu Edge Impulse jako dane treningowe, z opcjonalną etykietą nazywającą pliki. Oferowane są tylko formaty, które mogą pomieścić dane rekordu; mapa głębi na przykład nie może być plikiem WAV. Długie przechwycenie jest dzielone na numerowane części, aby żaden pojedynczy plik nie urósł nieporęcznie, a nagrywanie przetrwa ponowne zarejestrowanie kanałów przez skrypt. Odczyt obok przycisku śledzi, ile próbek zapisano, i rozmiar pliku.

Interwał Channel Polling panelu, w sekcji protokołu w preferencjach, ustala, jak często IDE prosi kamerę o nowe dane kanałów; wartość domyślna pasuje do skryptów publikujących kilka razy na sekundę, a skrypt strumieniujący dźwięk skorzysta na krótszym interwale.

Zobacz także

protocol.CBORChannel od strony skryptu – typy rekordów, ich argumenty i wywołanie zwrotne on_write – oraz przykłady 12-Protocol w File → Examples jako działające skrypty publikujące odczyty, elementy sterujące i mapę głębi.