v5.0.1#

v5.0.1 è una release di manutenzione basata su v5.0.0 — il modulo legacy sensor diventa un livello di compatibilità Python sopra csi, le immagini caricate nel frame buffer ora vengono visualizzate in anteprima come i frame della camera, gli encoder JPEG perdono il limite di 1 MB sull’output e gestiscono correttamente l’overflow, e c’è una serie di correzioni a camera, protocollo, rete e libreria ML. Non introduce nessuna modifica API non retrocompatibile per gli script scritti per csi; le poche modifiche di comportamento sono elencate sotto modifiche API non retrocompatibili.

In evidenza#

  • Il modulo sensor è ora un modulo Python frozen costruito su csi. Stampa un avviso di deprecazione all’import; alcune funzioni che il modulo csi non può supportare ora sollevano OSError. Vedi le modifiche al modulo sensor.

  • Le immagini caricate vengono visualizzate in anteprima come i frame della camera. Un’immagine posta nel frame buffer con copy_to_fb=True (image.Image, image.ImageIO.read(), fir.snapshot(), tof.snapshot()) viene inviata all’IDE — con tutto ciò che vi è stato disegnato sopra — quando l’immagine successiva sovrascrive il frame buffer, invece che immediatamente. Vedi le modifiche all’anteprima.

  • Revisione dell’encoder JPEG. Il limite di 1 MB sul buffer di output non c’è più (il buffer viene dimensionato in base alla memoria libera), l’overflow sia sul percorso software che su quello hardware viene gestito invece di scrivere file troncati, e salvare un’immagine compressa con l’altra estensione compressa solleva un’eccezione invece di scrivere dati spazzatura.

  • Nuova protocol.poll() e sei nuovi widget CBOR (text, lineedit, pushbutton, spinbox, radio, waveform) per protocol.CBORChannel.

  • Post-processore YOLO Pro, supporto per FLIR Lepton 3.1R / UW, letture burst dell’IMU, CAN su OpenMV N6 e un target simulatore con supporto di rete.

Nuove funzionalità#

  • YoloPro — un nuovo post-processore per i modelli di rilevamento oggetti Edge Impulse YOLO Pro, più un esempio yolo_pro_detector.py. (f3f150ebd, ea7bbb398)

  • protocol.poll() — esegue su richiesta un’iterazione del task di protocollo, per trasporti personalizzati che non sono pilotati dall’interrupt USB o dal timer poll_ms. protocol.init() può anche essere chiamata di nuovo per reinizializzare lo stack. (c00c215f9, f849ffb1b)

  • Più widget per i canali CBOR — protocol.CBORChannel.add() acquisisce text (stringa statica), lineedit (stringa scrivibile), pushbutton (azione momentanea), spinbox (inserimento numerico a passi), radio (gruppo di opzioni) e waveform (serie temporale 1D con argomenti sample_rate, series e typecode; assegna i byte dei campioni interlacciati per trasmetterla in streaming). (8016d29ba)

  • csi.CUSTOM — csi.CSI.framesize() ora restituisce una costante utilizzabile dopo che è stata impostata una risoluzione (w, h) personalizzata, invece di un intero anonimo. (af8841654)

  • Lettura burst dell’IMU — imu.__read_reg() accetta un buffer scrivibile opzionale e lo riempie da registri consecutivi in una sola transazione. (244ca480a)

  • FLIR Lepton 3.1R e Lepton UW sono riconosciuti dal driver Lepton, incluse le loro modalità di guadagno radiometrico. (0fc356632)

  • Rete nel simulatore — il target QEMU MPS2_AN500 ora dispone di lwIP e di una NIC in modalità utente, con requests, mqtt e sensor frozen, e di uno unit test di rete. (23546dfb1, 61d187305, 15096c3a2)

  • Esempio di API compatibile con OpenAI — openai_compatible.py acquisisce uno snapshot JPEG e lo invia via POST a un endpoint chat-completions per la descrizione della scena. (79033c6aa)

  • Esempi LoRa SX126x — il driver lora-sx126x di micropython-lib (con lora-sync / lora-async) è frozen nel firmware di OpenMV RT1062, con esempi sender/receiver/ping-pong/image-stream per collegare un modulo SX1261 o SX1262 al bus SPI. Si tratta di un supporto contribuito dalla community; OpenMV non vende hardware LoRa. (19576e1b1)

Altre modifiche e miglioramenti#

  • Riscrittura della libreria requests — le risposte con trasferimento chunked vengono decodificate, è esposto un argomento timeout (predefinito 5 s), i corpi JSON e stringa vengono serializzati/codificati correttamente, gli header vengono analizzati senza distinzione tra maiuscole e minuscole e la riga di stato per posizione, il dict headers del chiamante viene copiato (così auth non si propaga più alle richieste successive), e il corpo viene letto a blocchi in un bytearray. (889f0b096)

  • mqtt importa ssl in modo lazy, quindi il modulo e le connessioni in chiaro (non TLS) funzionano sulle build senza supporto SSL. (c2e0899e8)

  • Buffer di output JPEG dimensionato in base alla memoria libera invece di un limite fisso di 1 MB; gli encoder riducono il buffer alla dimensione codificata prima che l’immagine venga scritta, quindi le acquisizioni da sensori grandi ad alta qualità non falliscono più. (aa1ca6776)

  • Pulizia del post-processing ML — la generazione dei bounding box è standardizzata tra i post-processori Darknet, Edge Impulse e Ultralytics, e l’output di YOLOv8 viene trasposto dopo il thresholding in modo da essere memorizzato una riga per rilevamento come gli altri modelli. (b5c7853f2, c45f99cad)

  • Spegnimento sicuro del PAG7936 — un nuovo flag di arresto del sensore mette il PAG7936 in sleep prima del toggle di RESET/PWDN, risolvendo i blocchi quando il sensore è usato su un cavo di prolunga. Il driver inoltre seleziona a runtime il proprio set di registri MIPI CSI-2 o parallelo in base all’indirizzo I2C del sensore invece che al momento della build. (10026530c, f6acf14ec, 5f0251c74)

  • Il pacing della riproduzione di ImageIO ora gestisce gli eventi in sospeso mentre attende l’intervallo tra i frame invece di dormire in WFI. (a54790193)

  • Aggiornamenti del sottomodulo MicroPython — supporto di rete completo sul port QEMU, machine.mem_backup su STM32 tramite SRAM di backup/registri BKP, controllo di flusso hardware SDIO mantenuto disabilitato su STM32F4, e riutilizzo degli attributi MPU per le regioni non cacheable. (31ada5626, ab61d27a6, 06bddf13a)

  • differential-translation.py acquisisce tramite il proprio oggetto csi.CSI invece del modulo sensor deprecato, e la spaziatura degli import negli esempi è stata normalizzata. (68c866e7f, 9ceff4513)

Correzioni di bug#

Camera e sensori:

  • Impostare due risoluzioni (w, h) personalizzate di seguito lasciava il sensore alla prima dimensione mentre csi.CSI.width() / height() riportavano la seconda; il percorso rapido «nessuna modifica» ora esclude le dimensioni personalizzate. (cfbb70156)

  • csi.CSI.lens_correction() interpretava radi e coef come booleani, quindi i valori passati al driver non erano quelli forniti. (ab44b3a77)

  • PAG7936: impostare esposizione e guadagno uno di seguito all’altro faceva sì che si sovrascrivessero a vicenda (entrambi condividono un’unica modalità manuale e i registri di rilettura sono in ritardo di un frame); il driver ora inizializza i registri manuali solo quando entra in modalità manuale e scrive solo il controllo che viene impostato. (e7a18c0a0)

  • L’acquisizione BAYER con PAG7936 e PS5520 su OpenMV N6 falliva con «Failed to initialize the CSI interface» a qualsiasi dimensione diversa dalla risoluzione piena, perché l’ISP dell’N6 non può ridimensionare il Bayer raw. I sensori ora funzionano in una modalità nativa corrispondente alla dimensione richiesta per BAYER (PS5520: VGA, HD, SXGA-M, FHD, QHD, WQXGA2; QVGA non ha una modalità nativa e non è supportata). (fe6790055, b7622b245)

Codifica e salvataggio delle immagini:

  • Encoder JPEG software: l’overflow del buffer di output era sempre fatale perché il percorso di realloc era disabilitato; ora fa crescere il buffer (della metà della sua dimensione alla volta) quando ne è proprietario, ripiega in modo pulito quando la memoria si esaurisce, e riduce il risultato. jpeg_write / mjpeg_write non scrivono più il buffer dopo una codifica fallita. (28e1110be)

  • Encoder JPEG hardware (STM32): l’overflow restituiva un’immagine parzialmente codificata con la dimensione dell’allocazione, producendo file troncati senza marker EOI (ad es. un’acquisizione da 5 MP a qualità 100 con la metà inferiore vuota). Ora segnalano l’overflow, liberano il buffer in caso di fallimento e lo riducono in caso di successo. (22ce9619c)

  • L’encoder VC8000 produceva silenziosamente croma 4:2:0 per ogni richiesta; il sottocampionamento diverso da 4:2:0 ora ripiega sul codec HW che lo supporta. (71f2be7f2)

  • image.Image.save() di un’immagine PNG come .jpg scriveva fino a 1 MB di heap non inizializzato, e di un’immagine JPEG come .png scriveva un file vuoto. Entrambi ora sollevano un’eccezione; un’immagine già nel formato di destinazione viene comunque copiata così com’è. (6c1fdf822)

  • png_write ora controlla il valore restituito dal compressore e comprime prima di creare il file, così un fallimento non lascia più dietro di sé un file vuoto. (557f52d66)

Modulo image:

  • image.Image.get_pixel() con rgbtuple=True su immagini BAYER e YUV scriveva il pixel convertito oltre una variabile locale sullo stack a un offset controllato dal chiamante. (13f2a17b6)

  • gif.Gif.add_frame() ha perso un ramo di conversione Bayer/YUV irraggiungibile; sono accettate solo immagini GRAYSCALE e RGB565, come l’API Python già imponeva. (f20d99d96)

Protocollo:

  • Registrare un canale dinamico con tutti gli slot già in uso causava una scrittura fuori dai limiti; l’ID del canale ora viene controllato per primo, e gli ID dei canali riservati sono verificati staticamente per rientrare nella tabella dei canali. (68f635d1f)

  • Gli oggetti dei canali dinamici sopravvivevano a un soft reset nei root pointer, quindi il GC continuava a scansionare blocchi di heap obsoleti dell’esecuzione precedente; la tabella ora viene azzerata all’init. (ef0ebb03b, e23641145)

Port:

  • i.MX RT: aggiunta la de-inizializzazione mancante di CAN ed Encoder al soft reset. (7cb9d3dc2)

Hardware e supporto delle schede#

  • OpenMV N6 — CAN è ora abilitato (machine.CAN). (294f0febd, 91e1c9573)

  • OpenMV AE3 — il driver SPI sdcard è frozen per lo slot microSD dello shield AE3 Battery Shield. (a258f4814)

  • OpenMV RT1062 — lora-sx126x / lora-sync / lora-async frozen (vedi Nuove funzionalità).

  • FLIR Lepton 3.1R / UW — riconosciuti dal driver Lepton su tutte le schede compatibili con Lepton.

  • PAG7936 — arresto per spegnimento sicuro, selezione dell’interfaccia a runtime, correzione di esposizione/guadagno e acquisizione BAYER su N6.

  • PS5520 — acquisizione BAYER su N6 alle dimensioni native.

  • Simulatore (MPS2_AN500) — supporto di rete.

  • Tutte le schede — il modulo di compatibilità sensor è frozen nel manifest di ogni scheda.

Modifiche API non retrocompatibili#

v5.0.1 non introduce alcuna modifica non retrocompatibile alle API csi o image. Gli script che giravano su v5.0.0 girano senza modifiche, con le seguenti variazioni di comportamento.

modulo sensor (behavior)#

Il modulo nativo sensor (modules/py_csi.c) è stato rimosso e sostituito da un modulo Python frozen che implementa la stessa API sopra csi. Vedi sensor.

Commit: 5e3d40631

  • import sensor stampa sul terminale WARNING: The sensor module is deprecated and will be removed in a future release. Please use the csi module instead..

  • L’oggetto csi.CSI nascosto viene creato all’import, quindi una camera mancante ora solleva un errore a import sensor anziché a sensor.reset().

  • Queste funzioni ora sollevano OSError perché csi non ha un equivalente: get_fb(), alloc_extra_fb(), dealloc_extra_fb(), set_auto_rotation(), get_auto_rotation(), disable_delays(), disable_full_flush(). (Le due funzioni *_extra_fb sollevavano già un’eccezione in v5.0.0.) Usa csi.CSI(delays=False) / csi.CSI(fflush=False) per le ultime due.

  • Le framesize che csi non esporta (QQCIF, QQSIF, QQQQVGA, HQQQQVGA, HQQQVGA, HQQVGA, B64X32, B64X64, B128X64, B128X128, B160X160, B320X320, LCD, QQVGA2) sono ora tuple (w, h) passate come risoluzioni personalizzate. get_framesize() restituisce la tupla impostata finché la camera è ancora a quella dimensione, così i confronti di uguaglianza con le costanti continuano a funzionare.

  • ioctl() inoltra al massimo quattro argomenti dopo la richiesta.

  • sleep() / shutdown() sollevano OSError in caso di fallimento come prima (la RuntimeError di csi viene tradotta).

Migra a csi — vedi la tabella di migrazione v5.0.0.

Caricamento di immagini nel frame buffer (behavior)#

Le funzioni che caricano un’immagine nel frame buffer — image.Image con copy_to_fb=True, image.Image.copy() / image.Image.scale() e le conversioni to_* con copy_to_fb=True, image.ImageIO.read(), fir.snapshot() e tof.snapshot() con copy_to_fb=True — in precedenza inviavano immediatamente la nuova immagine all’anteprima dell’IDE, quindi tutto ciò che veniva disegnato sull’immagine restituita non veniva mai visto. Ora contrassegnano il frame buffer come in sospeso e lo inviano, con tutto ciò che vi è stato disegnato, subito prima che l’immagine successiva lo sovrascriva — lo stesso comportamento di csi.CSI.snapshot().

Commit: 87b6db5ee, 7b1a35c2f, f773c740d

I loop che leggono uno stream di immagini non richiedono modifiche e ora mostrano i loro disegni. Uno script che carica una singola immagine e si ferma deve inviarla esplicitamente con un flush:

img = image.Image("example.bmp", copy_to_fb=True)
img.flush()          # new: send it to the IDE preview now
time.sleep_ms(1000)

Libreria ML (behavior)#

Riguarda solo il codice che estende (subclass) o copia i post-processori forniti. YoloV8 ora traspone l’output del modello dopo il thresholding, così i rilevamenti sopravvissuti vengono memorizzati una riga per box (bb[:, 4:]), in linea con i post-processori Darknet ed Edge Impulse, invece di una colonna per box (bb[4:, :]). I risultati pubblici ((x, y, w, h), score) sono invariati.

Commit: c45f99cad, b5c7853f2

modulo protocol (minor)#

protocol.poll() è tornata. v5.0.0 l’aveva rimossa quando il task di protocollo è passato al timer; ritorna come modo esplicito per pilotare il task con trasporti personalizzati. Nient’altro è cambiato — gli script che non l’hanno mai chiamata non sono interessati.

Commit: c00c215f9

Build / tooling (tooling)#

Nulla di tutto ciò riguarda gli script MicroPython. py_image.c è stato suddiviso, con gli oggetti descrittore (cascade, keypoints, LBP, keypoint match) spostati in py_image_descriptor.c e gli oggetti statistici (similarity, statistics, percentile, threshold, histogram) in py_image_stats.c. L’API degli encoder di imlib è stata allineata al resto di imlib: jpeg_compress / png_compress restituiscono 0 in caso di successo e -1 in caso di errore, e jpeg_compress ha perso il suo argomento realloc (il ridimensionamento dipende dalla proprietà del buffer). OMV_PROTOCOL_MAX_CHANNELS è diventato OMV_PROTOCOL_CHANNEL_MAX in omv_protocol_channel.h, e i port ora chiamano py_protocol_init0() all’init. Il define di scheda OMV_PAG7936_MIPI_CSI2 non c’è più (l’interfaccia viene selezionata a runtime). Completano il quadro aggiornamenti delle dipendenze CI e una correzione per il changelog di release vuoto. Consulta la cronologia del repository del firmware per i dettagli rilevanti per i fork.

Checklist di migrazione#

  • Usi ancora import sensor? Funziona, con un avviso. Passa a csi (migrazione v5.0.0); sostituisci disable_delays / disable_full_flush con gli argomenti del costruttore csi.CSI() ed elimina le chiamate a get_fb / all’auto-rotazione.

  • Carichi una singola immagine con copy_to_fb=True e ti aspetti di vederla? Aggiungi img.flush() dopo il caricamento.

  • Hai copiato il post-processore YOLOv8? Indicizza l’output dopo il thresholding per riga (bb[:, 4:]) anziché per colonna.

  • Confronti csi0.framesize() dopo aver impostato una tupla? Ora restituisce csi.CUSTOM.

  • Tutto il resto: riflasha ed esegui.