v5.0.0

v5.0.0 è una release importante. In primo piano: il collegamento host OpenMV Protocol V2 ricostruito, un’API per camere csi basata su classi che scala alle schede multi-camera, un target simulatore eseguibile, la stima di posa a singola persona MoveNet, MicroPython 1.28 e un ampio lotto di correzioni per camera, ML e ToF. Introduce inoltre una serie di modifiche API non retrocompatibili — ogni cambiamento visibile all’utente da v4.8.1 è elencato di seguito, insieme alle istruzioni precise per la migrazione.

In evidenza

  • OpenMV Protocol V2. Il collegamento host/IDE è stato ricostruito da zero: a frame, sequenziato, con verifica CRC e canali multiplexati per stdio, l’anteprima dello stream e i dati utente. Un nuovo modulo protocol consente agli script di creare i propri transport e canali dati. Vedi le modifiche al modulo protocol.

  • API per camere csi basata su classi. import sensor diventa import csi / csi.CSI, con supporto multi-camera nativo. Vedi la migrazione a csi.

  • Target simulatore. Il firmware ora si compila e funziona sul simulatore Arm FVP / QEMU (MPS2/MPS3), inclusa l’emulazione di NPU, ROMFS e PSRAM — gli script di visione e ML possono essere eseguiti senza alcun hardware collegato.

  • Stima di posa MoveNet. Un nuovo post-processore MoveNet più un modello movenet_singlepose_192.tflite incluso su OpenMV AE3 e N6.

  • MicroPython 1.28 e ulab 6.12.0, il tooling ST Edge AI 4.0 e l”OpenMV SDK esternalizzato (vedi le modifiche alla build / al tooling).

Nuove funzionalità

  • Il modulo protocol — crea transport e canali dati personalizzati da Python: protocol.init(), protocol.register(), protocol.is_active() e una classe protocol.ProtocolChannel con send_event(), oltre alle costanti CHANNEL_FLAG_* e CHANNEL_ID_*. La firma finale di protocol.init() è documentata in le modifiche al modulo protocol.

  • protocol.CBORChannel — un pacchetto di estensione protocol frozen che serializza campi denominati in CBOR con widget di visualizzazione (label, depth) e controlli interattivi (toggle, slider, select).

  • Introspezione della memoria host e dello stream — un nuovo comando di protocollo SYS_MEMORY espone all’IDE le statistiche di memoria a runtime per ciascun pool, e un nuovo ioctl di stream STREAM_SOURCE consente all’host di scegliere quale camera alimenta l’anteprima sulle schede multi-camera (versione protocollo 1.0.1).

  • Streaming multi-cameracsi.CSI accetta un argomento stream= che seleziona quale sensore alimenta l’anteprima dell’IDE; l’header del frame dello stream ora trasporta un FPS smussato con EMA, in modo che l’IDE mostri il frame rate senza il boilerplate clock.fps(). Vedi la migrazione a csi e i follow-up su csi.

  • Sensore a eventi GenX320 — un nuovo filtro Spatio-Temporal Contrast (csi.IOCTL_GENX320_SET_STC con le modalità csi.GENX320_STC_DISABLE, csi.GENX320_STC_ONLY, csi.GENX320_STC_TRAIL_ONLY e csi.GENX320_STC_TRAIL) e la lettura grezza degli eventi (csi.IOCTL_GENX320_READ_EVENTS_RAW), con nuovi script di esempio.

  • MoveNet — un nuovo post-processore MediaPipe di posa a singola persona (kwargs threshold, nms_threshold, nms_sigma) che restituisce ((x, y, w, h), score, keypoints) con un array di keypoint COCO a 17 giunti; un modello movenet_singlepose_192.tflite e un esempio sono inclusi su AE3 e N6.

  • ml.utils.draw_predictions() — un nuovo argomento opzionale scores= aggiunge la confidenza per etichetta, il font e lo spessore del riquadro ora si ridimensionano automaticamente in base alla larghezza dell’immagine, e una nuova modalità format="point" disegna un marcatore centrale per i rilevatori centerpoint/peak.

  • La nuova classe display.TVDisplay (con un generico ioctl()) sostituisce il modulo autonomo tv. Vedi le modifiche al modulo display.

  • Un nuovo rilevatore find_line_segments() (ED-Lines) — ora disponibile su tutte le build, con un nuovo argomento threshold=. Vedi le modifiche al modulo image.

Altre modifiche e miglioramenti

  • MicroPython aggiornato a 1.28.0 dalla base v4.8.1. Aggiunge la modalità SD card ad alta velocità su H5/H7/N6, il clocking AHB5 in modalità a basso consumo e pin JTAG controllabili come GPIO sull’OPENMV_AE3.

  • ulab aggiornato a 6.12.0 — operatore % nativo sugli ndarray (l’helper ml.utils.mod() è stato rimosso; vedi le modifiche alla libreria ML).

  • Tooling ST Edge AI aggiornato a 4.0 — interessa la compilazione e il deployment dei modelli ST on-device.

  • ml.Model — l’argomento keyword load_to_fb è stato rimosso; la memoria del modello è gestita automaticamente dall’allocatore unificato.

  • image.Image.scale() in place — ridimensionando un’immagine ingrandendola in place (ad esempio img.scale(x_scale=2.0, y_scale=2.0)) il frame buffer ora cresce per adattarsi invece di fallire.

  • Buffer stdio più grande — il buffer di testo predefinito verso l’IDE è cresciuto da 512 a 1024 byte su OpenMV 2/3/4, Nicla Vision, AE3 e N6, in modo che burst di print() più grandi non vengano troncati.

  • Flusso di eventi host più fluido — gli eventi NOTIFY di stdout verso l’host sono limitati ad al massimo uno per lettura dell’host invece di uno per ogni print() che supera la soglia del ring buffer.

  • Operazioni lunghe interrompibili — i lunghi loop di disegno delle immagini, GPU (Nema/Dave2D) e di attesa NPU ora gestiscono gli eventi a intervalli deterministici, in modo che gli script rimangano reattivi al pulsante Stop dell’IDE durante il lavoro intensivo.

Correzioni di bug

Camera e sensori:

  • find_apriltags() non corrompe più i risultati sulle schede con D-cache/GPU (N6, AE3), e ora funziona sull’AE3.

  • Corretto l’output dell’immagine Bayer dall’ISP dell’STM32 N6 dopo il cambio del formato pixel.

  • Corretto il blowout verde dell’auto-white-balance in scene luminose e un caso di statistiche AWB del primo frame non inizializzate; alzato il clamp gamma dell’ISP STM32 (da 32 a 63) per un intervallo gamma/contrasto/luminosità più ampio.

  • L’auto-esposizione PS5520 non oscilla più in luce intensa; il comportamento AEC/AGC del PAG7936 è stato rielaborato (controllo combinato, tetto del guadagno corretto).

  • Ripristinato l’upload del firmware di autofocus OV5640 su Portenta/Nicla (correzione MIMXRT I2C SUSPEND).

  • Corretto un deadlock nella cattura della camera quando un limite di frame rate è combinato con la cattura JPEG (STM32).

  • Le letture GenX320 csi.IOCTL_GENX320_READ_EVENTS_RAW non disturbano più l’anteprima dell’IDE.

  • FLIR Lepton csi.IOCTL_LEPTON_SET_MODE tramite csi.CSI.ioctl() ora funziona se chiamato con un singolo argomento.

Elaborazione delle immagini:

  • Corretto il blending alpha di draw_image() / blend() quando viene fornita una maschera.

  • Corretto l’ordine dei bit nella codifica/decodifica PNG a 1 bit (BINARY) e la decodifica scala-di-grigi-da-1-bit.

  • Corretti i metadati di durata/FPS della registrazione mjpeg.Mjpeg.

  • Corretto uno stack overflow nella decodifica JPEG software sulle schede con stack ridotto (OpenMV M7).

  • Corretto il rilevamento automatico del formato file JPEG/PNG su host non ARM (simulatore).

Time-of-Flight:

ML e sistema:

  • La NPU viene ripulita correttamente quando l’inferenza viene interrotta sull’N6.

  • Ripristinato il risveglio da deep-sleep / standby sull’N6; corretto il blocco del jump-to-bootloader dell’AE3.

  • Corretti i memory leak al soft-reset (STM32 Nema GPU) e un frame buffer ausiliario raccolto prematuramente.

  • I canali di protocollo Python personalizzati ora sopravvivono a un soft-reboot, il transport USB si recupera da bus reset / endpoint in stallo, ed è corretto il flooding degli interrupt USB SOF.

Hardware e supporto delle schede

  • OpenMV N6 — Ethernet abilitato (rete cablata); NPU AXI SRAM (1,75 MB) unita in un pool transiente condiviso per più RAM tra le inferenze; risveglio da deep-sleep/standby; modelli TFLite e cascade Haar inclusi in ROMFS.

  • OpenMV AE3 — modelli e cascade inclusi in ROMFS; cbor2 integrato nel firmware come frozen.

  • Alif (AE3, N6) — risveglio machine.RTC a basso consumo.

  • AprilTag ad alta risoluzionefind_apriltags() alla risoluzione piena del sensore su AE3, Arduino Giga e Arduino Portenta H7.

  • Target simulatore — MPS2_AN500 / MPS3_AN547 (Arm FVP / QEMU), con emulazione di NPU, ROMFS e PSRAM.

Modifiche API non retrocompatibili

Modifiche API visibili all’utente tra v4.8.1 e v5.0.0. Ambito: C-module Python in modules/ e librerie Python in scripts/libraries/.

Ogni modifica è etichettata con il suo impatto:

  • major — la maggior parte degli script richiede modifiche.

  • minor — API ristretta; interessa solo gli script che la usavano.

  • behavior — stessa API, risultati diversi; ricontrolla gli script calibrati.

  • tooling — interessa solo la compilazione dai sorgenti / i fork downstream.

Le modifiche sono raggruppate per impatto in quest’ordine — prima major, poi minor, behavior e tooling. Se vuoi solo portare il tuo codice, salta alla checklist di migrazione alla fine per un elenco condensato di cose da fare. Ogni hash di commit rimanda al suo diff su GitHub.

sensor sostituito da csi (major)

Ogni esempio ufficiale è stato riscritto per eliminare import sensor in favore di import csi. La vecchia API funzionale a livello di modulo (sensor.reset(), sensor.set_pixformat(), …) è superata dall’API csi.CSI basata su classi, che scala naturalmente alle schede con più camere (csi0, csi1, …) ed è richiesta per tutte le nuove funzionalità (il kwarg stream=, lo streaming multi-sensore, …).

Il qstr sensor è ancora collegato in modules/py_csi.c per le build di firmware retrocompatibili, ma non riceverà nuove funzionalità, e tutti gli esempi, la documentazione e il codice delle librerie ora assumono csi.

Commit: 945c5853c, 61f835b7e

Da modulo a classe

Prima (sensor):

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

Dopo (csi):

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

Coppie setter/getter accorpate in accessori combinati

Nella nuova API un metodo chiamato senza argomenti restituisce il valore corrente; chiamato con un valore lo imposta. I prefissi set_*/get_* sono spariti. I nomi dei metodi hanno anche perso il suffisso ing dove era ridondante (windowingwindow). La colonna della nuova API rimanda alla documentazione di riferimento.

sensor (vecchio)

csi.CSI (nuovo)

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

Funzioni senza equivalente diretto

sensor (rimosso)

Cosa usare al suo posto

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

image.Image (w, h, pixfmt) — una normale immagine allocata sull’heap. Il framebuffer non viene più suddiviso per i buffer utente.

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

csi.CSI.snapshot() — lo skip dei frame è stato incorporato in snapshot tramite i suoi argomenti time= / frames=.

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

Spostati nel costruttore di csi.CSI: csi.CSI(delays=False) / csi.CSI(fflush=False).

sensor.get_frame_available()

csi.CSI.readable()

sensor.get_fb()

Rimosso. L’immagine restituita da csi.CSI.snapshot() è l’handle canonico.

sensor.set_framebuffers(n, expand=True)

csi.CSI.framebuffers() — l’argomento expand è stato rimosso (vedi i follow-up su csi).

Novità su csi.CSI

  • csi.CSI(stream=True|False) — un selettore in fase di costruzione che sceglie quale CSI alimenta il framebuffer dell’anteprima (sostituisce il kwarg update= per-snapshot, vedi i follow-up su csi).

  • csi.CSI(cid=N) / csi.devices() — supporto multi-CSI per le schede con più di un sensore di immagine.

modulo image — revisione delle firme (major)

Il modulo image ha subito il più ampio cambiamento di API dopo csi — le firme di disegno, gli oggetti dei risultati e diversi rilevatori sono tutti cambiati.

Gli argomenti di coordinate devono essere tuple

modules/py_image.c è stato riscritto sopra mp_arg_parse_all. Tutti i metodi di disegno / pixel che in precedenza accettavano argomenti posizionali separati x, y, ... ora richiedono che quelle coordinate siano impacchettate in un’unica tupla.

Commit: d18bbc472, 0c60c94b9 (PR #3061)

Prima

Dopo

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)

Sono tutti metodi di image.Image.

Oggetti dei risultati convertiti in attrtuple

Questi tipi sono ora oggetti attrtuple di MicroPython: similarity, statistics, percentile, threshold, line, circle, rect, qrcode, apriltag, datamatrix, barcode, displacement, kptmatch. L’accesso agli attributi senza parentesi è ora la forma canonica.

Commit: 3399d302e

Prima (stile a metodo):

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

Dopo (stile ad attributo):

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

blob e histogram sono invariati — mantengono i loro tipi esistenti e gli accessori () (un attrtuple non può esprimere i valori calcolati lazy di un blob né gli accessori con argomenti di un istogramma).

Rinomina del parametro haar di find_features

image.Image.find_features()scale_factor= è stato rinominato in scale=.

Commit: be4c5cd73

get_regression — ora sempre robusta, aggiunto target_size

image.Image.get_regression() ora usa sempre la regressione robusta (Theil-Sen). Il vecchio percorso veloce ai minimi quadrati è stato rimosso, quindi il keyword robust= è sparito — ciò che prima richiedeva robust=True è ora l’unico comportamento. Un nuovo kwarg target_size=(w, h) (default (80, 60)) ridimensiona in area la ROI prima del fit Theil-Sen O(N^2), in modo che giri sempre su una dimensione d’immagine ragionevole; gli endpoint della retta fittata vengono rimappati sulle coordinate sorgente. L’esempio linear_regression_robust.py è stato eliminato e linear_regression_fast.py è stato rinominato in linear_regression.py.

Commit: c7c2e69a0, 0ff2afa72

find_line_segments — nuovo algoritmo

image.Image.find_line_segments() — il vecchio rilevatore LSD è stato sostituito da ED-Lines e ha acquisito un nuovo kwarg threshold=50. L’output degli script precedentemente calibrati sarà diverso.

Commit: 87da2a7b7, 2c47b5735

Libreria AprilTag sostituita

image.Image.find_apriltags() — il rilevatore AprilTag è stato sostituito con una nuova implementazione. Il set di famiglie è cambiato:

Commit: e813bada7

modulo csi follow-up (minor)

Follow-up minori su csi oltre a la migrazione a csi.

snapshot(update=…) rimosso

Il kwarg update su csi.CSI.snapshot() è sparito. Per impedire a un dispositivo CSI di alimentare il framebuffer dell’anteprima, escludilo in fase di costruzione:

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

Commit: 9a8077827, 26b79a2c5

Argomento expand di framebuffers() rimosso

csi.CSI.framebuffers() — il terzo argomento posizionale (expand) è sparito; la firma è ora framebuffers([count]).

Commit: 86cb3a5de

modulo protocol (minor)

Interessa solo gli script che pilotavano direttamente il collegamento host. Vedi protocol.

timer_ms rinominato in poll_ms

protocol.init() — l’argomento timer_ms è stato rinominato in poll_ms.

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

Commit: 8a0635e8c, 95a290607

protocol.poll() rimosso

Il task del protocollo è ora schedulato internamente. Le chiamate a protocol.poll() solleveranno AttributeError.

Commit: 8a0635e8c

Argomento di configurazione soft_reboot rimosso

protocol.init() — l’argomento soft_reboot è sparito. Tutti i transport attuali tollerano i soft-reboot, quindi il comportamento è ora incondizionato.

Commit: 0bf766aa2

moduli display (minor)

L’output TV ora passa attraverso un oggetto display.TVDisplay invece del modulo autonomo tv. display ha anche acquisito un generico ioctl().

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

modulo tof (behavior)

Stessa API di prima; sono cambiati i default e la gestione degli errori. Vedi tof.

Timeout predefinito cambiato

tof.read_depth() e tof.snapshot() (chiamati con timeout=-1) ora hanno come default 100 ms invece di attendere indefinitamente. Passa un valore esplicito più grande se hai bisogno del vecchio comportamento.

Commit: b6772b80d

Recupero automatico

Il driver ora effettua un hard-reset del bus I2C e del sensore sugli errori di ranging/timeout. Gli esempi non chiamano più tof.reset() nei loro gestori di eccezioni — il codice utente che faceva un recupero manuale dovrebbe rimuoverlo (entrerà in conflitto con il nuovo auto-recupero).

Commit: b6772b80d, 80ffaa5c3

Libreria ML (behavior)

Stessa API, numeri diversi — ricontrolla qualsiasi pipeline ML calibrata.

Il preprocessing ora effettua uno stretch invece del letterbox

Normalization ora usa image.SCALE_ASPECT_IGNORE (stretch) invece di image.SCALE_ASPECT_EXPAND (letterbox). Anche il post-processing NMS è passato a uno scaling x/y indipendente.

Nota

Impatto. I rilevatori in stile YOLO e i regressori di keypoint generalmente migliorano. Gli esempi BlazeFace, BlazePalm, FaceLandmarks e HandLandmarks ora richiedono un ritaglio quadrato manuale sulla ROI di input — gli script di esempio sono stati aggiornati; il codice utente personalizzato deve fare lo stesso.

Commit: 68dc29a33

Helper ml.utils.mod() rimosso

ulab 6.12.0 supporta nativamente % sugli ndarray. Il codice che importava mod da ml.utils deve usare a % b.

Commit: 35ece5728, 82fbd858c

Build / tooling (tooling)

Nulla di questo interessa gli script MicroPython. La compilazione del firmware dai sorgenti ora richiede l”OpenMV SDK esterno (1.6.0, in precedenza in-tree). Diversi strumenti di build in-tree sono stati rimossi e l’N6 è passato allo stack TinyUSB; i fork downstream dovrebbero esaminare la storia del repository del firmware — in particolare la firma di file_open() che elimina il suo argomento buffered.

Checklist di migrazione

Per un port pulito a v5.0.0 il lavoro tipico è:

  1. Sostituisci import sensor con import csi; csi0 = csi.CSI() e traduci ogni chiamata set_*/get_* nel corrispondente accessore di csi.CSI (la migrazione a csi).

  2. Racchiudi gli argomenti di coordinate di img.draw_*, get_pixel() e set_pixel() in tuple (le modifiche al modulo image).

  3. Elimina le () dagli accessori dei risultati attrtuple se vuoi la nuova forma idiomatica, oppure lascia il vecchio stile invariato dato che gli attrtuple supportano ancora gli accessori richiamabili (le modifiche al modulo image).

  4. Verifica find_line_segments(), get_regression() e qualsiasi scelta della famiglia find_apriltags() (le modifiche al modulo image).

  5. Rinomina timer_mspoll_ms nelle chiamate a protocol.init(); rimuovi protocol.poll() e soft_reboot= (le modifiche al modulo protocol).

  6. Per i workflow ML: rivedi qualsiasi modello che necessitava di input con letterbox (le modifiche alla libreria ML).