v5.0.0#

v5.0.0 ist ein Major-Release. Die wichtigsten Neuerungen: die neu aufgebaute OpenMV Protocol V2-Host-Verbindung, eine klassenbasierte csi-Kamera-API, die auf Boards mit mehreren Kameras skaliert, ein lauffähiges Simulator-Target, MoveNet-Einzelposenschätzung, MicroPython 1.28 und eine große Reihe von Korrekturen für Kamera, ML und ToF. Außerdem bringt es einige API-Brüche mit sich — jede für Benutzer sichtbare Änderung seit v4.8.1 ist unten aufgeführt, zusammen mit genauen Migrationshinweisen.

Highlights#

  • OpenMV Protocol V2. Die Host-/IDE-Verbindung wurde von Grund auf neu aufgebaut: gerahmt, sequenziert, CRC-geprüft, mit gemultiplexten Kanälen für stdio, die Stream-Vorschau und Benutzerdaten. Ein neues protocol-Modul ermöglicht es Skripten, eigene Transports und Datenkanäle zu erstellen. Siehe die Änderungen am protocol-Modul.

  • Klassenbasierte csi -Kamera-API. import sensor wird zu import csi / csi.CSI, mit nativer Unterstützung für mehrere Kameras. Siehe die csi-Migration.

  • Simulator-Target. Die Firmware lässt sich nun unter dem Arm FVP / QEMU-Simulator (MPS2/MPS3) bauen und ausführen, einschließlich NPU-, ROMFS- und PSRAM-Emulation — Vision- und ML-Skripte können ohne angeschlossene Hardware laufen.

  • MoveNet-Posenschätzung. Ein neuer MoveNet-Postprozessor sowie ein mitgeliefertes movenet_singlepose_192.tflite-Modell auf OpenMV AE3 und N6.

  • MicroPython 1.28 und ulab 6.12.0, ST Edge AI 4.0-Tooling sowie das ausgelagerte OpenMV SDK (siehe die Build-/Tooling-Änderungen).

Neue Funktionen#

Weitere Änderungen und Verbesserungen#

  • MicroPython auf 1.28.0 aktualisiert von der v4.8.1-Basis. Fügt Hochgeschwindigkeits-SD-Karten-Modus auf H5/H7/N6, AHB5-Taktung im Low-Power-Modus und als GPIOs steuerbare JTAG-Pins auf dem OPENMV_AE3 hinzu.

  • ulab auf 6.12.0 aktualisiert — nativer %-Operator auf ndarrays (der Hilfsfunktion ml.utils.mod() wurde entfernt; siehe die Änderungen an der ML-Bibliothek).

  • ST Edge AI-Tooling auf 4.0 aktualisiert — betrifft die Kompilierung und Bereitstellung von ST-Modellen auf dem Gerät.

  • ml.Model — das Schlüsselwortargument load_to_fb wurde entfernt; der Modellspeicher wird automatisch vom vereinheitlichten Allokator verwaltet.

  • image.Image.scale() direkt vor Ort — das direkte Hochskalieren eines Bildes (zum Beispiel img.scale(x_scale=2.0, y_scale=2.0)) vergrößert nun den Framebuffer passend, anstatt fehlzuschlagen.

  • Größerer stdio-Puffer — der Standard-Textpuffer zur IDE wuchs auf OpenMV 2/3/4, Nicla Vision, AE3 und N6 von 512 auf 1024 Byte, sodass größere print()-Schübe nicht abgeschnitten werden.

  • Gleichmäßigerer Host-Event-Fluss — stdout-NOTIFY-Events an den Host werden auf höchstens eines pro Host-Lesevorgang gedrosselt statt eines pro print(), das die Ringpuffer-Wassermarke überschreitet.

  • Unterbrechbare lange Operationen — lange Bildzeichen-, GPU- (Nema/Dave2D) und NPU-Warteschleifen bedienen Events nun in einem deterministischen Intervall, sodass Skripte während aufwändiger Arbeit für den Stop-Button der IDE ansprechbar bleiben.

Fehlerbehebungen#

Kamera und Sensoren:

  • find_apriltags() beschädigt auf D-Cache-/GPU-Boards (N6, AE3) keine Ergebnisse mehr und funktioniert nun auf dem AE3.

  • Bayer-Bildausgabe vom STM32 N6 ISP nach dem Umschalten von Pixelformaten korrigiert.

  • Grünstich-Überstrahlung beim automatischen Weißabgleich in hellen Szenen sowie einen Fall mit nicht initialisierten AWB-Statistiken im ersten Einzelbild behoben; den STM32-ISP-Gamma-Clamp (32 auf 63) für einen größeren Gamma-/Kontrast-/Helligkeitsbereich angehoben.

  • PS5520-Autobelichtung oszilliert in hellem Licht nicht mehr; das PAG7936-AEC/AGC-Verhalten wurde überarbeitet (kombinierte Steuerung, korrigierte Verstärkungsobergrenze).

  • OV5640-Autofokus-Firmware-Upload auf Portenta/Nicla wiederhergestellt (MIMXRT-I2C-SUSPEND-Fix).

  • Einen Deadlock bei der Kameraerfassung behoben, wenn ein Bildraten-Limit mit JPEG-Erfassung kombiniert wird (STM32).

  • GenX320 csi.IOCTL_GENX320_READ_EVENTS_RAW-Lesevorgänge verzerren die IDE-Vorschau nicht mehr.

  • FLIR Lepton csi.IOCTL_LEPTON_SET_MODE über csi.CSI.ioctl() funktioniert nun, wenn es mit einem einzigen Argument aufgerufen wird.

Bildverarbeitung:

  • draw_image() / blend() Alpha-Blending korrigiert, wenn eine Maske angegeben wird.

  • Bit-Reihenfolge beim 1-Bit-(BINARY-)PNG-Encode/Decode sowie die Graustufen-aus-1-Bit-Dekodierung korrigiert.

  • mjpeg.Mjpeg-Metadaten zur Aufnahmedauer/FPS korrigiert.

  • Einen Stack-Überlauf bei der Software-JPEG-Dekodierung auf Boards mit kleinem Stack (OpenMV M7) behoben.

  • JPEG-/PNG-Dateiformat-Autoerkennung auf Nicht-ARM-Hosts (Simulator) korrigiert.

Time-of-Flight:

ML und System:

  • Die NPU wird korrekt bereinigt, wenn die Inferenz auf dem N6 unterbrochen wird.

  • Deep-Sleep-/Standby-Aufwachen auf dem N6 wiederhergestellt; der AE3-Jump-to-Bootloader-Hänger ist behoben.

  • Speicherlecks beim Soft-Reset (STM32 Nema GPU) sowie einen vorzeitig eingesammelten zusätzlichen Framebuffer behoben.

  • Benutzerdefinierte Python-Protokollkanäle überstehen nun einen Soft-Reboot, der USB-Transport erholt sich von Bus-Reset / blockierten Endpoints, und das Überfluten durch USB-SOF-Interrupts ist behoben.

Hardware- und Board-Unterstützung#

  • OpenMV N6 — Ethernet aktiviert (kabelgebundenes Netzwerk); NPU AXI SRAM (1,75 MB) in einen gemeinsamen transienten Pool zusammengeführt für mehr RAM zwischen Inferenzen; Deep-Sleep-/Standby-Aufwachen; mitgelieferte TFLite-Modelle und Haar-Kaskaden in ROMFS.

  • OpenMV AE3 — mitgelieferte Modelle und Kaskaden in ROMFS; cbor2 in die Firmware eingefroren.

  • Alif (AE3, N6) — Low-Power-machine.RTC-Aufwachen.

  • Hochauflösende AprilTagsfind_apriltags() in voller Sensorauflösung auf dem AE3, Arduino Giga und Arduino Portenta H7.

  • Simulator-Targets — MPS2_AN500 / MPS3_AN547 (Arm FVP / QEMU), mit NPU-, ROMFS- und PSRAM-Emulation.

API-Brüche#

Für Benutzer sichtbare API-Brüche zwischen v4.8.1 und v5.0.0. Umfang: Python-C-Module in modules/ und Python-Bibliotheken in scripts/libraries/.

Jede Änderung ist mit ihrer Auswirkung gekennzeichnet:

  • major — die meisten Skripte müssen angepasst werden.

  • minor — schmale API; betrifft nur Skripte, die sie verwendet haben.

  • behavior — gleiche API, andere Ergebnisse; abgestimmte Skripte erneut prüfen.

  • tooling — betrifft nur das Bauen aus dem Quellcode / nachgelagerte Forks.

Die Änderungen sind in dieser Reihenfolge nach Auswirkung gruppiert — zuerst major, dann minor, behavior und tooling. Wenn Sie Ihren Code lediglich portieren möchten, springen Sie zur Migrations-Checkliste am Ende für eine komprimierte To-do-Liste. Jeder Commit-Hash verlinkt auf seinen Diff auf GitHub.

sensor ersetzt durch csi (major)#

Jedes offizielle Beispiel wurde umgeschrieben, um import sensor zugunsten von import csi aufzugeben. Die alte funktionale API auf Modulebene (sensor.reset(), sensor.set_pixformat(), …) wird durch die klassenbasierte csi.CSI-API abgelöst, die natürlich auf Boards mit mehreren Kameras skaliert (csi0, csi1, …) und für alle neuen Funktionen erforderlich ist (das stream=-Schlüsselwortargument, Multi-Sensor-Streaming, …).

Das sensor-qstr ist in modules/py_csi.c weiterhin für rückwärtskompatible Firmware-Builds verdrahtet, erhält aber keine neuen Funktionen, und alle Beispiele, Dokumentationen und Bibliothekscode setzen nun csi voraus.

Commits: 945c5853c, 61f835b7e

Vom Modul zur Klasse

Vorher (sensor):

import sensor
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
sensor.skip_frames(time=2000)
img = sensor.snapshot()

Nachher (csi):

import csi
csi0 = csi.CSI()
csi0.reset()
csi0.pixformat(csi.RGB565)
csi0.framesize(csi.QVGA)
csi0.snapshot(time=2000)
img = csi0.snapshot()

Setter-/Getter-Paare zu kombinierten Accessoren zusammengefasst

In der neuen API gibt eine ohne Argumente aufgerufene Methode den aktuellen Wert zurück; mit einem Wert aufgerufen, setzt sie ihn. Die set_*-/get_*-Präfixe sind verschwunden. Methodennamen verloren außerdem das ing-Suffix, wo es redundant war (windowingwindow). Die Spalte der neuen API verlinkt auf die Referenzdokumentation.

sensor (alt)

csi.CSI (neu)

set_pixformat(fmt) / get_pixformat()

pixformat([fmt])

set_framesize(sz) / get_framesize()

framesize([sz])

set_framerate(fps) / get_framerate()

framerate([fps])

set_windowing(roi) / get_windowing()

window([roi])

set_framebuffers(n) / get_framebuffers()

framebuffers([n])

set_gainceiling(g)

gainceiling([g])

set_brightness(v)

brightness([v])

set_contrast(v)

contrast([v])

set_saturation(v)

saturation([v])

set_quality(v)

quality([v])

set_colorbar(b)

colorbar([b])

set_special_effect(e)

special_effect([e])

set_lens_correction(...)

lens_correction(...)

set_hmirror(b) / get_hmirror()

hmirror([b])

set_vflip(b) / get_vflip()

vflip([b])

set_transpose(b) / get_transpose()

transpose([b])

set_auto_rotation(b) / get_auto_rotation()

auto_rotation([b])

set_auto_gain(b, [db, ceiling]) / get_gain_db()

auto_gain(...) / gain_db()

set_auto_exposure(b, [us]) / get_exposure_us()

auto_exposure(...) / exposure_us()

set_auto_whitebal(b, [rgb]) / get_rgb_gain_db()

auto_whitebal(...) / rgb_gain_db()

set_auto_blc(b, [regs]) / get_blc_regs()

auto_blc(...) / blc_regs()

set_color_palette(p) / get_color_palette()

color_palette([p])

set_frame_callback(cb)

frame_callback(cb)

set_vsync_callback(cb)

vsync_callback(cb)

get_id()

cid()

Funktionen ohne direkte Entsprechung

sensor (entfernt)

Was stattdessen zu verwenden ist

sensor.alloc_extra_fb(w, h, pixfmt) / sensor.dealloc_extra_fb()

image.Image (w, h, pixfmt) — ein reguläres, auf dem Heap allokiertes Bild. Der Framebuffer wird nicht mehr für Benutzerpuffer aufgeteilt.

sensor.skip_frames(time=..., frames=...)

csi.CSI.snapshot() — Skip-Frames in snapshot über dessen time=-/frames=-Argumente integriert.

sensor.disable_delays(...) / sensor.disable_full_flush(...)

In den csi.CSI-Konstruktor verschoben: csi.CSI(delays=False) / csi.CSI(fflush=False).

sensor.get_frame_available()

csi.CSI.readable()

sensor.get_fb()

Entfernt. Das von csi.CSI.snapshot() zurückgegebene Bild ist das kanonische Handle.

sensor.set_framebuffers(n, expand=True)

csi.CSI.framebuffers() — das expand-Argument wurde entfernt (siehe die csi-Folgeänderungen).

Neu bei csi.CSI

  • csi.CSI(stream=True|False) — ein Selektor zur Konstruktionszeit, der auswählt, welche CSI den Vorschau-Framebuffer speist (ersetzt das update=-Schlüsselwortargument pro Schnappschuss, siehe die csi-Folgeänderungen).

  • csi.CSI(cid=N) / csi.devices() — Multi-CSI-Unterstützung für Boards mit mehr als einem Bildsensor.

image-Modul — Überarbeitung der Signaturen (major)#

Das image-Modul erfuhr nach csi die umfangreichste API-Änderung — Zeichensignaturen, Ergebnisobjekte und mehrere Detektoren haben sich alle geändert.

Koordinatenargumente müssen Tupel sein

modules/py_image.c wurde auf Basis von mp_arg_parse_all neu geschrieben. Alle Zeichen-/Pixelmethoden, die zuvor separate x, y, ...-Positionsargumente entgegennahmen, erfordern nun, dass diese Koordinaten in ein einzelnes Tupel gepackt werden.

Commits: d18bbc472, 0c60c94b9 (PR #3061)

Vorher

Nachher

img.draw_arrow(x0, y0, x1, y1, color=...)

img.draw_arrow((x0, y0, x1, y1), color=...)

img.draw_line(x0, y0, x1, y1, ...)

img.draw_line((x0, y0, x1, y1), ...)

img.draw_cross(x, y, ...)

img.draw_cross((x, y), ...)

img.draw_circle(x, y, r, ...)

img.draw_circle((x, y, r), ...)

img.draw_rectangle(x, y, w, h, ...)

img.draw_rectangle((x, y, w, h), ...)

img.draw_string(x, y, "txt", ...)

img.draw_string((x, y), "txt", ...)

img.draw_ellipse(x, y, rx, ry, rot, ...)

img.draw_ellipse((x, y, rx, ry, rot), ...)

img.flood_fill(x, y, ...)

img.flood_fill((x, y), ...)

img.get_pixel(x, y, rgbtuple=...)

img.get_pixel((x, y), rgbtuple=...)

img.set_pixel(x, y, color)

img.set_pixel((x, y), color)

Alle sind Methoden von image.Image.

Ergebnisobjekte in attrtuple umgewandelt

Diese Typen sind nun MicroPython-attrtuple-Objekte: similarity, statistics, percentile, threshold, line, circle, rect, qrcode, apriltag, datamatrix, barcode, displacement, kptmatch. Der Attributzugriff ohne Klammern ist nun die kanonische Form.

Commit: 3399d302e

Vorher (Methoden-Stil):

img.draw_cross(match.cx(), match.cy())
img.draw_rectangle(blob.rect())

Nachher (Attribut-Stil):

img.draw_cross((match.cx, match.cy))
img.draw_rectangle(blob.rect)

blob und histogram sind unverändert — sie behalten ihre bestehenden Typen und ()-Accessoren (ein attrtuple kann die verzögert berechneten Werte eines Blobs oder die argumentbasierten Accessoren eines Histogramms nicht abbilden).

Umbenennung des find_features-haar-Parameters

image.Image.find_features()scale_factor= wurde in scale= umbenannt.

Commit: be4c5cd73

get_regression — nun immer robust, target_size hinzugefügt

image.Image.get_regression() verwendet nun immer die robuste (Theil-Sen-)Regression. Der alte schnelle Pfad der kleinsten Quadrate wurde entfernt, sodass das robust=-Schlüsselwort verschwunden ist — was früher robust=True erforderte, ist nun das einzige Verhalten. Ein neues target_size=(w, h)-Schlüsselwortargument (Standard (80, 60)) skaliert den ROI flächenmäßig herunter, bevor der O(N^2)-Theil-Sen-Fit ausgeführt wird, sodass er stets auf einer vernünftigen Bildgröße läuft; die Endpunkte der gefitteten Linie werden auf die Quellkoordinaten zurückgerechnet. Das Beispiel linear_regression_robust.py wurde gelöscht und linear_regression_fast.py in linear_regression.py umbenannt.

Commits: c7c2e69a0, 0ff2afa72

find_line_segments — neuer Algorithmus

image.Image.find_line_segments() — der alte LSD-Detektor wurde durch ED-Lines ersetzt, und er erhielt ein neues threshold=50-Schlüsselwortargument. Die Ausgabe zuvor abgestimmter Skripte wird sich unterscheiden.

Commits: 87da2a7b7, 2c47b5735

AprilTag-Bibliothek ersetzt

image.Image.find_apriltags() — der AprilTag-Detektor wurde durch eine neue Implementierung ersetzt. Der Satz an Familien änderte sich:

Commit: e813bada7

csi-Modul-Folgeänderung (minor)#

Kleinere csi-Folgeänderungen aufbauend auf der csi-Migration.

snapshot(update=…) entfernt

Das update-Schlüsselwortargument bei csi.CSI.snapshot() ist verschwunden. Um zu verhindern, dass ein CSI-Gerät den Vorschau-Framebuffer speist, deaktivieren Sie dies zur Konstruktionszeit:

csi0 = csi.CSI(stream=False)                  # was: csi0.snapshot(update=False)
csi1.snapshot(blocking=False, image=fir_img)  # was: ...(update=False, ...)

Commits: 9a8077827, 26b79a2c5

framebuffers()-expand-Argument entfernt

csi.CSI.framebuffers() — das dritte Positionsargument (expand) ist verschwunden; die Signatur lautet nun framebuffers([count]).

Commit: 86cb3a5de

protocol-Modul (minor)#

Betrifft nur Skripte, die die Host-Verbindung direkt angesteuert haben. Siehe protocol.

timer_ms in poll_ms umbenannt

protocol.init() — das timer_ms-Argument wurde in poll_ms umbenannt.

protocol.init(..., poll_ms=10)   # was: timer_ms=10

Commits: 8a0635e8c, 95a290607

protocol.poll() entfernt

Die Protokollaufgabe wird nun intern geplant. Aufrufe von protocol.poll() lösen AttributeError aus.

Commit: 8a0635e8c

soft_reboot-Konfigurationsargument entfernt

protocol.init() — das soft_reboot-Argument ist verschwunden. Alle aktuellen Transports tolerieren Soft-Reboots, sodass das Verhalten nun bedingungslos ist.

Commit: 0bf766aa2

display-Module (minor)#

Die TV-Ausgabe läuft nun über ein display.TVDisplay-Objekt anstelle des eigenständigen tv-Moduls. display erhielt außerdem ein generisches ioctl().

Commits: f0accb389, 1a5a87121, 920c097a0, 9eac55098

tof-Modul (behavior)#

Gleiche API wie zuvor; die Standardwerte und die Fehlerbehandlung haben sich geändert. Siehe tof.

Standard-Timeout geändert

tof.read_depth() und tof.snapshot() (mit timeout=-1 aufgerufen) verwenden nun standardmäßig 100 ms statt unbegrenzt zu warten. Übergeben Sie einen expliziten größeren Wert, wenn Sie das alte Verhalten benötigen.

Commit: b6772b80d

Automatische Wiederherstellung

Der Treiber setzt nun bei Entfernungsmess-/Timeout-Fehlern den I2C-Bus und den Sensor hart zurück. Die Beispiele rufen tof.reset() nicht mehr in ihren Ausnahmehandlern auf — Benutzercode, der eine manuelle Wiederherstellung durchführte, sollte sie entfernen (sie würde gegen die neue automatische Wiederherstellung arbeiten).

Commits: b6772b80d, 80ffaa5c3

ML-Bibliothek (behavior)#

Gleiche API, andere Zahlen — prüfen Sie jede abgestimmte ML-Pipeline erneut.

Die Vorverarbeitung streckt nun statt Letterboxing anzuwenden

Normalization verwendet nun image.SCALE_ASPECT_IGNORE (Strecken) anstelle von image.SCALE_ASPECT_EXPAND (Letterbox). Die NMS-Nachverarbeitung wechselte ebenfalls zu unabhängiger x/y-Skalierung.

Bemerkung

Auswirkung. YOLO-artige Detektoren und Keypoint-Regressoren verbessern sich im Allgemeinen. Die Beispiele BlazeFace, BlazePalm, FaceLandmarks und HandLandmarks erfordern nun einen manuellen quadratischen Zuschnitt des Eingabe-ROI — die Beispielskripte wurden aktualisiert; benutzerdefinierter Code muss dasselbe tun.

Commit: 68dc29a33

ml.utils.mod()-Hilfsfunktion entfernt

ulab 6.12.0 unterstützt % auf ndarrays nativ. Code, der mod aus ml.utils importierte, muss a % b verwenden.

Commits: 35ece5728, 82fbd858c

Build / Tooling (tooling)#

Nichts davon betrifft MicroPython-Skripte. Das Bauen der Firmware aus dem Quellcode erfordert nun das externe OpenMV SDK (1.6.0, zuvor im Baum). Mehrere im Baum befindliche Build-Tools wurden entfernt und der N6 wurde auf den TinyUSB-Stack umgestellt; nachgelagerte Forks sollten die Historie des Firmware-Repositorys prüfen — insbesondere die file_open()-Signatur, die ihr buffered-Argument verloren hat.

Migrations-Checkliste#

Für eine saubere Portierung auf v5.0.0 ist die typische Arbeit:

  1. Ersetzen Sie import sensor durch import csi; csi0 = csi.CSI() und übersetzen Sie jeden set_*-/get_*-Aufruf in seinen csi.CSI-Accessor (die csi-Migration).

  2. Packen Sie Koordinatenargumente an img.draw_*, get_pixel() und set_pixel() in Tupel (die Änderungen am image-Modul).

  3. Lassen Sie die () bei attrtuple-Ergebnis-Accessoren weg, wenn Sie die neue idiomatische Form wünschen, oder belassen Sie den alten Stil, da attrtuples weiterhin aufrufbare Accessoren unterstützen (die Änderungen am image-Modul).

  4. Überprüfen Sie find_line_segments(), get_regression() und jede Wahl der find_apriltags()-Familie (die Änderungen am image-Modul).

  5. Benennen Sie timer_mspoll_ms in protocol.init()-Aufrufen um; entfernen Sie protocol.poll() und soft_reboot= (die Änderungen am protocol-Modul).

  6. Für ML-Workflows: überarbeiten Sie jedes Modell, das letterboxte Eingaben benötigte (die Änderungen an der ML-Bibliothek).