v5.0.0

v5.0.0 est une version majeure. Au programme : la liaison hôte OpenMV Protocol V2 entièrement reconstruite, une API caméra csi basée sur les classes qui s’adapte aux cartes multi-caméras, une cible simulateur exécutable, l’estimation de pose unique MoveNet, MicroPython 1.28 et un large lot de correctifs caméra, ML et ToF. Elle introduit également un certain nombre de changements d’API non rétrocompatibles — chaque modification visible par l’utilisateur depuis la v4.8.1 est listée ci-dessous, accompagnée de la procédure exacte de migration.

Points forts

  • OpenMV Protocol V2. La liaison hôte/IDE a été reconstruite de fond en comble : trames, séquencement, vérification CRC, avec des canaux multiplexés pour stdio, l’aperçu du flux et les données utilisateur. Un nouveau module protocol permet aux scripts de créer leurs propres transports et canaux de données. Voir les changements du module protocol.

  • API caméra csi basée sur les classes. import sensor devient import csi / csi.CSI, avec une prise en charge native du multi-caméra. Voir la migration vers csi.

  • Cible simulateur. Le micrologiciel se compile et s’exécute désormais sous le simulateur Arm FVP / QEMU (MPS2/MPS3), avec émulation du NPU, de ROMFS et de la PSRAM — les scripts de vision et de ML peuvent s’exécuter sans aucun matériel connecté.

  • Estimation de pose MoveNet. Un nouveau post-traitement MoveNet ainsi qu’un modèle movenet_singlepose_192.tflite fourni sur les OpenMV AE3 et N6.

  • MicroPython 1.28 et ulab 6.12.0, l’outillage ST Edge AI 4.0, et le OpenMV SDK externalisé (voir les changements de build / outillage).

Nouvelles fonctionnalités

  • Le module protocol — créez des transports et des canaux de données personnalisés depuis Python : protocol.init(), protocol.register(), protocol.is_active(), et une classe protocol.ProtocolChannel dotée de send_event(), ainsi que les constantes CHANNEL_FLAG_* et CHANNEL_ID_*. La signature finale de protocol.init() est documentée dans les changements du module protocol.

  • protocol.CBORChannel — un paquet d’extension protocol figé qui sérialise des champs nommés en CBOR avec des widgets d’affichage (label, depth) et des contrôles interactifs (toggle, slider, select).

  • Introspection de la mémoire hôte et du flux — une nouvelle commande de protocole SYS_MEMORY expose à l’IDE les statistiques mémoire d’exécution par pool, et un nouvel ioctl de flux STREAM_SOURCE permet à l’hôte de choisir quelle caméra alimente l’aperçu sur les cartes multi-caméras (version du protocole 1.0.1).

  • Streaming multi-caméracsi.CSI accepte un argument stream= qui sélectionne quel capteur alimente l’aperçu de l’IDE ; l’en-tête de trame du flux véhicule désormais un FPS lissé par EMA afin que l’IDE affiche la fréquence d’images sans le code répétitif clock.fps(). Voir la migration vers csi et les compléments csi.

  • Capteur d’événements GenX320 — un nouveau filtre de contraste spatio-temporel (csi.IOCTL_GENX320_SET_STC avec les modes csi.GENX320_STC_DISABLE, csi.GENX320_STC_ONLY, csi.GENX320_STC_TRAIL_ONLY et csi.GENX320_STC_TRAIL) et la lecture brute des événements (csi.IOCTL_GENX320_READ_EVENTS_RAW), avec de nouveaux scripts d’exemple.

  • MoveNet — un nouveau post-traitement MediaPipe de pose unique (arguments nommés threshold, nms_threshold, nms_sigma) renvoyant ((x, y, w, h), score, keypoints) avec un tableau de 17 points clés COCO ; un modèle movenet_singlepose_192.tflite et un exemple sont fournis sur les AE3 et N6.

  • ml.utils.draw_predictions() — un nouvel argument optionnel scores= ajoute la confiance par étiquette, la police et l’épaisseur du trait de la boîte s’adaptent désormais automatiquement à la largeur de l’image, et un nouveau mode format="point" dessine un marqueur central pour les détecteurs centerpoint/peak.

  • La nouvelle classe display.TVDisplay (dotée d’un ioctl() générique) remplace le module autonome tv. Voir les changements du module display.

  • Un nouveau détecteur find_line_segments() (ED-Lines) — désormais disponible sur tous les builds, avec un nouvel argument threshold=. Voir les changements du module image.

Autres changements et améliorations

  • MicroPython mis à jour vers 1.28.0 depuis la base v4.8.1. Ajoute le mode carte SD haute vitesse sur H5/H7/N6, l’horloge AHB5 en mode basse consommation et les broches JTAG contrôlables en tant que GPIO sur l’OPENMV_AE3.

  • ulab mis à jour vers 6.12.0 — opérateur % natif sur les ndarrays (l’utilitaire ml.utils.mod() est supprimé ; voir les changements de la bibliothèque ML).

  • Outillage ST Edge AI mis à jour vers 4.0 — affecte la compilation et le déploiement des modèles ST sur l’appareil.

  • ml.Model — l’argument nommé load_to_fb a été supprimé ; la mémoire du modèle est gérée automatiquement par l’allocateur unifié.

  • image.Image.scale() sur place — agrandir une image sur place (par exemple img.scale(x_scale=2.0, y_scale=2.0)) augmente désormais la taille du tampon d’image pour s’adapter au lieu d’échouer.

  • Tampon stdio plus grand — le tampon de texte par défaut vers l’IDE est passé de 512 à 1024 octets sur les OpenMV 2/3/4, Nicla Vision, AE3 et N6, de sorte que les rafales print() plus volumineuses ne sont pas tronquées.

  • Flux d’événements hôte plus fluide — les événements NOTIFY de stdout vers l’hôte sont limités à au plus un par lecture de l’hôte au lieu d’un par print() franchissant le seuil du tampon circulaire.

  • Opérations longues interruptibles — les longues boucles d’attente de dessin d’image, de GPU (Nema/Dave2D) et de NPU traitent désormais les événements à un intervalle déterministe, de sorte que les scripts restent réactifs au bouton Stop de l’IDE pendant les traitements lourds.

Corrections de bugs

Caméra et capteurs :

  • find_apriltags() ne corrompt plus les résultats sur les cartes à D-cache/GPU (N6, AE3) et fonctionne désormais sur l’AE3.

  • Correction de la sortie d’image Bayer de l’ISP du STM32 N6 après changement de format de pixel.

  • Correction de la saturation verte de la balance des blancs automatique sur les scènes lumineuses et d’un cas de statistiques AWB de première trame non initialisées ; la limite gamma de l’ISP STM32 a été relevée (32 à 63) pour une plage gamma/contraste/luminosité plus large.

  • L’exposition automatique du PS5520 n’oscille plus en pleine lumière ; le comportement AEC/AGC du PAG7936 a été retravaillé (contrôle combiné, plafond de gain corrigé).

  • Le téléversement du micrologiciel d’autofocus de l’OV5640 est rétabli sur Portenta/Nicla (correctif MIMXRT I2C SUSPEND).

  • Correction d’un blocage de capture caméra lorsqu’une limite de fréquence d’images est combinée à une capture JPEG (STM32).

  • Les lectures GenX320 csi.IOCTL_GENX320_READ_EVENTS_RAW ne brouillent plus l’aperçu de l’IDE.

  • FLIR Lepton csi.IOCTL_LEPTON_SET_MODE via csi.CSI.ioctl() fonctionne désormais lorsqu’il est appelé avec un seul argument.

Traitement d’image :

  • Correction du fondu alpha de draw_image() / blend() lorsqu’un masque est fourni.

  • Correction de l’ordre des bits à l’encodage/décodage des PNG 1 bit (BINARY) et du décodage en niveaux de gris depuis du 1 bit.

  • Correction des métadonnées de durée/FPS de l’enregistrement mjpeg.Mjpeg.

  • Correction d’un débordement de pile lors du décodage JPEG logiciel sur les cartes à petite pile (OpenMV M7).

  • Correction de la détection automatique du format de fichier JPEG/PNG sur les hôtes non-ARM (simulateur).

Time-of-Flight :

  • tof.read_depth() ne lève plus d’erreur sur les erreurs de télémétrie transitoires et se rétablit automatiquement des défauts de bus ; le délai d’expiration par défaut de tof.read_depth() / tof.snapshot() est désormais de 100 ms (voir les changements de tof).

  • Correction de la corruption des données de profondeur multi-zones VL53L5CX / VL53L8CX.

ML et système :

  • Le NPU est nettoyé correctement lorsque l’inférence est interrompue sur le N6.

  • Le réveil après sommeil profond / veille est rétabli sur le N6 ; le blocage du saut vers le programme d’amorçage de l’AE3 est corrigé.

  • Correction de fuites mémoire au redémarrage logiciel (GPU Nema du STM32) et d’un tampon d’image auxiliaire collecté prématurément.

  • Les canaux de protocole Python personnalisés survivent désormais à un redémarrage logiciel, le transport USB se rétablit d’une réinitialisation de bus / d’endpoints bloqués, et l’inondation d’interruptions SOF USB est corrigée.

Matériel et prise en charge des cartes

  • OpenMV N6 — Ethernet activé (réseau filaire) ; la SRAM AXI du NPU (1,75 Mo) fusionnée dans un pool transitoire partagé pour plus de RAM entre les inférences ; réveil après sommeil profond/veille ; modèles TFLite et cascades de Haar fournis dans ROMFS.

  • OpenMV AE3 — modèles et cascades fournis dans ROMFS ; cbor2 figé dans le micrologiciel.

  • Alif (AE3, N6) — réveil machine.RTC basse consommation.

  • AprilTags haute résolutionfind_apriltags() en pleine résolution du capteur sur l’AE3, l’Arduino Giga et l’Arduino Portenta H7.

  • Cibles simulateur — MPS2_AN500 / MPS3_AN547 (Arm FVP / QEMU), avec émulation du NPU, de ROMFS et de la PSRAM.

Changements d’API non rétrocompatibles

Ruptures d’API visibles par l’utilisateur entre la v4.8.1 et la v5.0.0. Périmètre : modules C Python dans modules/ et bibliothèques Python dans scripts/libraries/.

Chaque changement est étiqueté selon son impact :

  • majeur — la plupart des scripts nécessitent des modifications.

  • mineur — API restreinte ; n’affecte que les scripts qui l’utilisaient.

  • comportement — même API, résultats différents ; revérifiez les scripts réglés finement.

  • outillage — n’affecte que la compilation depuis les sources / les forks en aval.

Les changements sont regroupés par impact dans cet ordre — majeur d’abord, puis mineur, comportement et outillage. Si vous voulez simplement porter votre code, passez à la liste de contrôle de migration à la fin pour une liste de tâches condensée. Chaque hash de commit pointe vers son diff sur GitHub.

sensor remplacé par csi (majeur)

Chaque exemple officiel a été réécrit pour abandonner import sensor au profit de import csi. L’ancienne API fonctionnelle au niveau du module (sensor.reset(), sensor.set_pixformat(), …) est remplacée par l’API csi.CSI basée sur les classes, qui s’adapte naturellement aux cartes dotées de plusieurs caméras (csi0, csi1, …) et est requise pour toutes les nouvelles fonctionnalités (l’argument nommé stream=, le streaming multi-capteurs, …).

Le qstr sensor est toujours câblé dans modules/py_csi.c pour les builds de micrologiciel rétrocompatibles, mais il ne recevra pas de nouvelles fonctionnalités, et tous les exemples, la documentation et le code des bibliothèques supposent désormais csi.

Commits : 945c5853c, 61f835b7e

Du module à la classe

Avant (sensor) :

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

Après (csi) :

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

Paires setter/getter regroupées en accesseurs combinés

Dans la nouvelle API, une méthode appelée sans argument renvoie la valeur courante ; appelée avec une valeur, elle la définit. Les préfixes set_*/get_* ont disparu. Les noms de méthodes ont également perdu le suffixe ing là où il était redondant (windowingwindow). La colonne de la nouvelle API pointe vers la documentation de référence.

sensor (ancien)

csi.CSI (nouveau)

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

Fonctions sans équivalent direct

sensor (supprimé)

Que utiliser à la place

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

image.Image (w, h, pixfmt) — une image ordinaire allouée sur le tas. Le tampon d’image n’est plus découpé pour les tampons utilisateur.

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

csi.CSI.snapshot() — le saut de trames est intégré à snapshot via ses arguments time= / frames=.

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

Déplacé dans le constructeur de csi.CSI : csi.CSI(delays=False) / csi.CSI(fflush=False).

sensor.get_frame_available()

csi.CSI.readable()

sensor.get_fb()

Supprimé. L’image renvoyée par csi.CSI.snapshot() est le handle canonique.

sensor.set_framebuffers(n, expand=True)

csi.CSI.framebuffers() — l’argument expand a été supprimé (voir les compléments csi).

Nouveautés sur csi.CSI

  • csi.CSI(stream=True|False) — un sélecteur défini à la construction qui choisit quel CSI alimente le tampon d’image d’aperçu (remplace l’argument nommé update= par capture, voir les compléments csi).

  • csi.CSI(cid=N) / csi.devices() — prise en charge multi-CSI pour les cartes dotées de plusieurs capteurs d’image.

module image — refonte des signatures (majeur)

Le module image a connu le changement d’API le plus important après csi — les signatures de dessin, les objets de résultat et plusieurs détecteurs ont tous changé.

Les arguments de coordonnées doivent être des tuples

modules/py_image.c a été réécrit au-dessus de mp_arg_parse_all. Toutes les méthodes de dessin / pixel qui prenaient auparavant des arguments positionnels x, y, ... distincts requièrent désormais que ces coordonnées soient regroupées dans un seul tuple.

Commits : d18bbc472, 0c60c94b9 (PR #3061)

Avant

Après

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)

Ce sont toutes des méthodes de image.Image.

Objets de résultat convertis en attrtuple

Ces types sont désormais des objets attrtuple de MicroPython : similarity, statistics, percentile, threshold, line, circle, rect, qrcode, apriltag, datamatrix, barcode, displacement, kptmatch. L’accès aux attributs sans parenthèses est désormais la forme canonique.

Commit : 3399d302e

Avant (style méthode) :

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

Après (style attribut) :

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

blob et histogram sont inchangés — ils conservent leurs types existants et leurs accesseurs () (un attrtuple ne peut pas exprimer les valeurs calculées paresseusement d’un blob ni les accesseurs prenant des arguments d’un histogramme).

Renommage du paramètre haar de find_features

image.Image.find_features()scale_factor= a été renommé en scale=.

Commit : be4c5cd73

get_regression — désormais toujours robuste, ajout de target_size

image.Image.get_regression() utilise désormais toujours la régression robuste (Theil-Sen). L’ancien chemin rapide des moindres carrés a été supprimé, donc le mot-clé robust= a disparu — ce qui nécessitait auparavant robust=True est désormais le seul comportement. Un nouvel argument nommé target_size=(w, h) (par défaut (80, 60)) réduit la taille de la ROI par mise à l’échelle de surface avant l’ajustement Theil-Sen en O(N^2) afin qu’il s’exécute toujours sur une taille d’image raisonnable ; les extrémités de la ligne ajustée sont remappées vers les coordonnées source. L’exemple linear_regression_robust.py a été supprimé et linear_regression_fast.py a été renommé en linear_regression.py.

Commits : c7c2e69a0, 0ff2afa72

find_line_segments — nouvel algorithme

image.Image.find_line_segments() — l’ancien détecteur LSD a été remplacé par ED-Lines, et il a gagné un nouvel argument nommé threshold=50. La sortie des scripts réglés précédemment différera.

Commits : 87da2a7b7, 2c47b5735

Bibliothèque AprilTag remplacée

image.Image.find_apriltags() — le détecteur AprilTag a été remplacé par une nouvelle implémentation. L’ensemble des familles a changé :

Commit : e813bada7

complément du module csi (mineur)

Compléments csi plus modestes s’ajoutant à la migration vers csi.

snapshot(update=…) supprimé

L’argument nommé update de csi.CSI.snapshot() a disparu. Pour empêcher un périphérique CSI d’alimenter le tampon d’image d’aperçu, désactivez-le à la construction :

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

Commits : 9a8077827, 26b79a2c5

Argument expand de framebuffers() supprimé

csi.CSI.framebuffers() — le troisième argument positionnel (expand) a disparu ; la signature est désormais framebuffers([count]).

Commit : 86cb3a5de

module protocol (mineur)

N’affecte que les scripts qui pilotaient directement la liaison hôte. Voir protocol.

timer_ms renommé en poll_ms

protocol.init() — l’argument timer_ms a été renommé en poll_ms.

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

Commits : 8a0635e8c, 95a290607

protocol.poll() supprimé

La tâche de protocole est désormais planifiée en interne. Les appels à protocol.poll() lèveront AttributeError.

Commit : 8a0635e8c

Argument de configuration soft_reboot supprimé

protocol.init() — l’argument soft_reboot a disparu. Tous les transports actuels tolèrent les redémarrages logiciels, donc le comportement est désormais inconditionnel.

Commit : 0bf766aa2

modules display (mineur)

La sortie TV passe désormais par un objet display.TVDisplay au lieu du module autonome tv. display a également gagné un ioctl() générique.

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

module tof (comportement)

Même API qu’auparavant ; les valeurs par défaut et la gestion des erreurs ont changé. Voir tof.

Délai d’expiration par défaut modifié

tof.read_depth() et tof.snapshot() (appelés avec timeout=-1) ont désormais par défaut 100 ms au lieu d’attendre indéfiniment. Passez une valeur explicite plus grande si vous avez besoin de l’ancien comportement.

Commit : b6772b80d

Récupération automatique

Le pilote réinitialise désormais matériellement le bus I2C et le capteur lors d’erreurs de télémétrie/d’expiration. Les exemples n’appellent plus tof.reset() dans leurs gestionnaires d’exceptions — le code utilisateur effectuant une récupération manuelle devrait le retirer (il entrerait en conflit avec la nouvelle récupération automatique).

Commits : b6772b80d, 80ffaa5c3

Bibliothèque ML (comportement)

Même API, chiffres différents — revérifiez tout pipeline ML réglé finement.

Le prétraitement étire désormais au lieu d’ajouter des bandes

Normalization utilise désormais image.SCALE_ASPECT_IGNORE (étirement) au lieu de image.SCALE_ASPECT_EXPAND (bandes noires). Le post-traitement NMS est également passé à une mise à l’échelle x/y indépendante.

Note

Impact. Les détecteurs de type YOLO et les régresseurs de points clés s’améliorent généralement. Les exemples BlazeFace, BlazePalm, FaceLandmarks et HandLandmarks nécessitent désormais un recadrage carré manuel sur la ROI d’entrée — les scripts d’exemple ont été mis à jour ; le code utilisateur personnalisé doit faire de même.

Commit : 68dc29a33

Utilitaire ml.utils.mod() supprimé

ulab 6.12.0 prend en charge nativement % sur les ndarrays. Le code qui importait mod depuis ml.utils doit utiliser a % b.

Commits : 35ece5728, 82fbd858c

Build / outillage (outillage)

Rien de tout cela n’affecte les scripts MicroPython. La compilation du micrologiciel depuis les sources nécessite désormais le OpenMV SDK externe (1.6.0, précédemment intégré à l’arborescence). Plusieurs outils de build intégrés à l’arborescence ont été supprimés et le N6 est passé à la pile TinyUSB ; les forks en aval devraient examiner l’historique du dépôt de micrologiciel — notamment la signature de file_open() qui abandonne son argument buffered.

Liste de contrôle de migration

Pour un portage propre vers la v5.0.0, le travail habituel consiste à :

  1. Remplacer import sensor par import csi; csi0 = csi.CSI() et traduire chaque appel set_*/get_* vers son accesseur csi.CSI (la migration vers csi).

  2. Encapsuler les arguments de coordonnées de img.draw_*, get_pixel() et set_pixel() dans des tuples (les changements du module image).

  3. Abandonner les () des accesseurs de résultat attrtuple si vous voulez la nouvelle forme idiomatique, ou laisser l’ancien style tel quel puisque les attrtuples prennent toujours en charge les accesseurs appelables (les changements du module image).

  4. Auditer find_line_segments(), get_regression() et tout choix de famille find_apriltags() (les changements du module image).

  5. Renommer timer_mspoll_ms dans les appels à protocol.init() ; supprimer protocol.poll() et soft_reboot= (les changements du module protocol).

  6. Pour les workflows ML : réexaminer tout modèle qui nécessitait une entrée avec bandes (les changements de la bibliothèque ML).