v5.0.1#

v5.0.1 est une version de maintenance au-dessus de la v5.0.0 — l’ancien module sensor devient une couche de compatibilité Python au-dessus de csi, les images chargées dans le tampon d’image s’affichent désormais dans l’aperçu comme des trames caméra, les encodeurs JPEG perdent leur limite de sortie de 1 Mo et gèrent correctement le dépassement, et un lot de correctifs concerne la caméra, le protocole, le réseau et la bibliothèque ML. Elle n’introduit aucun changement d’API non rétrocompatible pour les scripts écrits pour csi ; les quelques changements de comportement sont listés sous changements d’API non rétrocompatibles.

Points forts#

  • Le module sensor est désormais un module Python gelé construit sur csi. Il affiche un avertissement d’obsolescence à l’import ; quelques fonctions que le module csi ne peut pas prendre en charge lèvent désormais OSError. Voir les changements du module sensor.

  • Les images chargées s’affichent dans l’aperçu comme des trames caméra. Une image placée dans le tampon d’image avec copy_to_fb=True (image.Image, image.ImageIO.read(), fir.snapshot(), tof.snapshot()) est envoyée à l’IDE — avec tout ce qui a été dessiné dessus — lorsque l’image suivante écrase le tampon d’image, au lieu de l’être immédiatement. Voir les changements de l’aperçu.

  • Refonte de l’encodeur JPEG. Le plafond de 1 Mo du tampon de sortie a disparu (le tampon est dimensionné d’après la mémoire libre), le dépassement sur les chemins logiciel et matériel est géré au lieu d’écrire des fichiers tronqués, et l’enregistrement d’une image compressée sous l’autre extension compressée lève une exception au lieu d’écrire des données incohérentes.

  • Nouveau protocol.poll() et six nouveaux widgets CBOR (text, lineedit, pushbutton, spinbox, radio, waveform) pour protocol.CBORChannel.

  • Post-traitement YOLO Pro, prise en charge des FLIR Lepton 3.1R / UW, lectures en rafale de l’IMU, CAN sur l’OpenMV N6 et une cible simulateur avec réseau.

Nouvelles fonctionnalités#

  • YoloPro — un nouveau post-traitement pour les modèles de détection d’objets YOLO Pro d’Edge Impulse, plus un exemple yolo_pro_detector.py. (f3f150ebd, ea7bbb398)

  • protocol.poll() — exécute une itération de la tâche du protocole à la demande, pour les transports personnalisés qui ne sont pilotés ni par l’interruption USB ni par le minuteur poll_ms. protocol.init() peut également être appelé à nouveau pour réinitialiser la pile. (c00c215f9, f849ffb1b)

  • Plus de widgets pour le canal CBOR — protocol.CBORChannel.add() gagne text (chaîne statique), lineedit (chaîne modifiable), pushbutton (action momentanée), spinbox (saisie numérique par pas), radio (groupe d’options) et waveform (série temporelle 1D avec les arguments sample_rate, series et typecode ; affectez des octets d’échantillons entrelacés pour la diffuser). (8016d29ba)

  • csi.CUSTOM — csi.CSI.framesize() renvoie désormais une constante utilisable après la définition d’une résolution (w, h) personnalisée, au lieu d’un entier anonyme. (af8841654)

  • Lecture en rafale de l’IMU — imu.__read_reg() accepte un tampon inscriptible facultatif et le remplit à partir de registres consécutifs en une seule transaction. (244ca480a)

  • Les FLIR Lepton 3.1R et Lepton UW sont reconnues par le pilote Lepton, y compris leurs modes de gain radiométriques. (0fc356632)

  • Réseau dans le simulateur — la cible QEMU MPS2_AN500 dispose désormais de lwIP et d’une carte réseau en mode utilisateur, avec requests, mqtt et sensor gelés, ainsi qu’un test unitaire réseau. (23546dfb1, 61d187305, 15096c3a2)

  • Exemple d’API compatible OpenAI — openai_compatible.py capture un JPEG et l’envoie à un point de terminaison chat-completions pour obtenir une description de la scène. (79033c6aa)

  • Exemples LoRa SX126x — le pilote lora-sx126x de micropython-lib (avec lora-sync / lora-async) est gelé dans le micrologiciel de l’OpenMV RT1062, avec des exemples émetteur/récepteur/ping-pong/flux d’images pour câbler un module SX1261 ou SX1262 sur le bus SPI. Il s’agit d’une prise en charge contribuée par la communauté ; OpenMV ne vend pas de matériel LoRa. (19576e1b1)

Autres changements et améliorations#

  • Réécriture de la bibliothèque requests — les réponses en transfert fragmenté sont décodées, un argument timeout (5 s par défaut) est exposé, les corps JSON et chaîne sont sérialisés/encodés correctement, les en-têtes sont analysés sans distinction de casse et la ligne d’état par position, le dictionnaire headers de l’appelant est copié (de sorte que auth ne fuit plus dans les requêtes ultérieures), et le corps est lu par blocs dans un bytearray. (889f0b096)

  • mqtt importe ssl paresseusement, de sorte que le module et les connexions simples (non TLS) fonctionnent sur les builds sans prise en charge SSL. (c2e0899e8)

  • Tampon de sortie JPEG dimensionné d’après la mémoire libre au lieu d’un plafond fixe de 1 Mo ; les encodeurs réduisent le tampon à la taille encodée avant l’écriture de l’image, de sorte que les captures de grands capteurs en haute qualité n’échouent plus. (aa1ca6776)

  • Nettoyage du post-traitement ML — la génération des boîtes englobantes est standardisée entre les post-traitements Darknet, Edge Impulse et Ultralytics, et la sortie YOLOv8 est transposée après le seuillage afin d’être stockée une ligne par détection comme pour les autres modèles. (b5c7853f2, c45f99cad)

  • Arrêt sûr du PAG7936 — un nouvel indicateur d’arrêt du capteur met le PAG7936 en veille avant le basculement de RESET/PWDN, ce qui corrige les blocages lorsque le capteur est utilisé sur un câble d’extension. Le pilote sélectionne également son jeu de registres MIPI CSI-2 ou parallèle d’après l’adresse I2C du capteur à l’exécution plutôt qu’à la compilation. (10026530c, f6acf14ec, 5f0251c74)

  • La cadence de lecture ImageIO traite désormais les événements en attente pendant l’attente de l’intervalle inter-trames au lieu de dormir en WFI. (a54790193)

  • Mises à jour du sous-module MicroPython — prise en charge réseau complète sur le port QEMU, machine.mem_backup sur STM32 via la SRAM de sauvegarde/les registres BKP, contrôle de flux matériel SDIO maintenu désactivé sur STM32F4, et réutilisation des attributs MPU pour les régions non cachables. (31ada5626, ab61d27a6, 06bddf13a)

  • differential-translation.py capture via son objet csi.CSI au lieu du module sensor obsolète, et l’espacement des imports dans les exemples a été normalisé. (68c866e7f, 9ceff4513)

Corrections de bugs#

Caméra et capteurs :

  • Définir deux résolutions (w, h) personnalisées d’affilée laissait le capteur à la première taille tandis que csi.CSI.width() / height() rapportaient la seconde ; le chemin rapide « aucun changement » exclut désormais les tailles personnalisées. (cfbb70156)

  • csi.CSI.lens_correction() interprétait radi et coef comme des booléens, de sorte que les valeurs transmises au pilote n’étaient pas celles fournies. (ab44b3a77)

  • PAG7936 : définir l’exposition et le gain coup sur coup les faisait s’écraser mutuellement (les deux partagent un même mode manuel et les registres relus ont une trame de retard) ; le pilote n’initialise désormais les registres manuels qu’à l’entrée en mode manuel et n’écrit que le contrôle en cours de réglage. (e7a18c0a0)

  • La capture BAYER des PAG7936 et PS5520 sur l’OpenMV N6 échouait avec « Failed to initialize the CSI interface » à toute taille autre que la pleine résolution, car l’ISP du N6 ne peut pas redimensionner le Bayer brut. Les capteurs fonctionnent désormais dans un mode natif correspondant à la taille demandée pour BAYER (PS5520 : VGA, HD, SXGA-M, FHD, QHD, WQXGA2 ; QVGA n’a pas de mode natif et n’est pas pris en charge). (fe6790055, b7622b245)

Encodage et enregistrement d’images :

  • Encodeur JPEG logiciel : le dépassement du tampon de sortie était toujours fatal car le chemin de realloc était désactivé ; il agrandit désormais le tampon (de la moitié de sa taille à chaque fois) lorsqu’il en est propriétaire, se replie proprement lorsque la mémoire est épuisée, et réduit le résultat. jpeg_write / mjpeg_write n’écrivent plus le tampon après un échec d’encodage. (28e1110be)

  • Encodeurs JPEG matériels (STM32) : le dépassement renvoyait une image partiellement encodée avec la taille d’allocation, produisant des fichiers tronqués sans marqueur EOI (par ex. une capture 5 MP en qualité 100 avec la moitié inférieure vide). Ils signalent désormais le dépassement, libèrent le tampon en cas d’échec et le réduisent en cas de succès. (22ce9619c)

  • L’encodeur VC8000 produisait silencieusement une chrominance 4:2:0 pour chaque requête ; le sous-échantillonnage non 4:2:0 se replie désormais sur le codec matériel qui le prend en charge. (71f2be7f2)

  • image.Image.save() d’une image PNG en .jpg écrivait jusqu’à 1 Mo de tas non initialisé, et d’une image JPEG en .png écrivait un fichier vide. Les deux lèvent désormais une exception ; une image déjà dans le format cible est toujours copiée telle quelle. (6c1fdf822)

  • png_write vérifie désormais la valeur de retour du compresseur et compresse avant de créer le fichier, de sorte qu’un échec ne laisse plus de fichier vide derrière lui. (557f52d66)

Module image :

  • image.Image.get_pixel() avec rgbtuple=True sur des images BAYER et YUV écrivait le pixel converti au-delà d’une variable locale de pile, à un décalage contrôlé par l’appelant. (13f2a17b6)

  • gif.Gif.add_frame() a perdu une branche de conversion Bayer/YUV inaccessible ; seules les images GRAYSCALE et RGB565 sont acceptées, comme l’API Python l’imposait déjà. (f20d99d96)

Protocole :

  • L’enregistrement d’un canal dynamique alors que tous les emplacements étaient déjà utilisés provoquait une écriture hors limites ; l’ID de canal est désormais vérifié en premier, et une assertion statique garantit que les ID de canal réservés tiennent dans la table des canaux. (68f635d1f)

  • Les objets de canal dynamique survivaient à une réinitialisation logicielle dans les pointeurs racine, de sorte que le GC continuait de parcourir des blocs de tas périmés de l’exécution précédente ; la table est désormais vidée à l’initialisation. (ef0ebb03b, e23641145)

Ports :

  • i.MX RT : ajout de la désinitialisation manquante du CAN et de l’Encoder lors d’une réinitialisation logicielle. (7cb9d3dc2)

Matériel et prise en charge des cartes#

  • OpenMV N6 — le CAN est désormais activé (machine.CAN). (294f0febd, 91e1c9573)

  • OpenMV AE3 — le pilote SPI sdcard est gelé pour le connecteur microSD du AE3 Battery Shield. (a258f4814)

  • OpenMV RT1062 — lora-sx126x / lora-sync / lora-async gelés (voir Nouvelles fonctionnalités).

  • FLIR Lepton 3.1R / UW — reconnues par le pilote Lepton sur toutes les cartes compatibles Lepton.

  • PAG7936 — arrêt sûr, sélection de l’interface à l’exécution, correctif exposition/gain et capture BAYER sur le N6.

  • PS5520 — capture BAYER sur le N6 aux tailles natives.

  • Simulateur (MPS2_AN500) — réseau.

  • Toutes les cartes — le module de compatibilité sensor est gelé dans le manifeste de chaque carte.

Changements d’API non rétrocompatibles#

La v5.0.1 n’introduit aucun changement non rétrocompatible dans les API csi ou image. Les scripts qui fonctionnaient sur la v5.0.0 fonctionnent sans modification, avec les changements de comportement suivants.

module sensor (comportement)#

Le module sensor natif (modules/py_csi.c) a été supprimé et remplacé par un module Python gelé qui implémente la même API au-dessus de csi. Voir sensor.

Commit : 5e3d40631

  • import sensor affiche WARNING: The sensor module is deprecated and will be removed in a future release. Please use the csi module instead. dans le terminal.

  • L’objet csi.CSI caché est créé à l’import, de sorte qu’une caméra absente lève désormais une erreur à import sensor plutôt qu’à sensor.reset().

  • Ces fonctions lèvent désormais OSError car csi n’a pas d’équivalent : get_fb(), alloc_extra_fb(), dealloc_extra_fb(), set_auto_rotation(), get_auto_rotation(), disable_delays(), disable_full_flush(). (Les deux fonctions *_extra_fb levaient déjà une exception en v5.0.0.) Utilisez csi.CSI(delays=False) / csi.CSI(fflush=False) pour les deux dernières.

  • Les résolutions que csi n’exporte pas (QQCIF, QQSIF, QQQQVGA, HQQQQVGA, HQQQVGA, HQQVGA, B64X32, B64X64, B128X64, B128X128, B160X160, B320X320, LCD, QQVGA2) sont désormais des tuples (w, h) transmis comme résolutions personnalisées. get_framesize() renvoie le tuple qui a été défini tant que la caméra est toujours à cette taille, de sorte que les tests d’égalité avec les constantes continuent de fonctionner.

  • ioctl() transmet au plus quatre arguments après la requête.

  • sleep() / shutdown() lèvent OSError en cas d’échec comme auparavant (la RuntimeError de csi est traduite).

Migrez vers csi — voir la table de migration v5.0.0.

Chargement d’images dans le tampon d’image (comportement)#

Les fonctions qui chargent une image dans le tampon d’image — image.Image avec copy_to_fb=True, image.Image.copy() / image.Image.scale() et les conversions to_* avec copy_to_fb=True, image.ImageIO.read(), fir.snapshot() et tof.snapshot() avec copy_to_fb=True — poussaient auparavant la nouvelle image vers l’aperçu de l’IDE immédiatement, de sorte que tout ce qui était dessiné sur l’image renvoyée n’était jamais visible. Elles marquent désormais le tampon d’image comme en attente et le vident, avec tout ce qui a été dessiné dessus, juste avant que l’image suivante ne l’écrase — le même comportement que csi.CSI.snapshot().

Commits : 87b6db5ee, 7b1a35c2f, f773c740d

Les boucles qui lisent un flux d’images ne nécessitent aucun changement et affichent désormais leurs dessins. Un script qui charge une seule image puis s’arrête doit la vider explicitement :

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

Bibliothèque ML (comportement)#

N’affecte que le code qui sous-classe ou copie les post-traitements fournis. YoloV8 transpose désormais la sortie du modèle après le seuillage, de sorte que les détections retenues sont stockées une ligne par boîte (bb[:, 4:]), comme pour les post-traitements Darknet et Edge Impulse, au lieu d’une colonne par boîte (bb[4:, :]). Les résultats publics ((x, y, w, h), score) sont inchangés.

Commits : c45f99cad, b5c7853f2

module protocol (mineur)#

protocol.poll() est de retour. La v5.0.0 l’avait supprimé lorsque la tâche du protocole est passée au minuteur ; il revient comme moyen explicite de piloter la tâche pour les transports personnalisés. Rien d’autre n’a changé — les scripts qui ne l’appelaient jamais ne sont pas affectés.

Commit : c00c215f9

Build / outillage (outillage)#

Rien de tout cela n’affecte les scripts MicroPython. py_image.c a été scindé, les objets descripteurs (cascade, points clés, LBP, correspondance de points clés) passant dans py_image_descriptor.c et les objets statistiques (similarité, statistiques, percentile, seuil, histogramme) dans py_image_stats.c. L’API des encodeurs imlib a été alignée sur le reste d’imlib : jpeg_compress / png_compress renvoient 0 en cas de succès et -1 en cas d’erreur, et jpeg_compress a perdu son argument realloc (le redimensionnement est conditionné à la propriété du tampon). OMV_PROTOCOL_MAX_CHANNELS est devenu OMV_PROTOCOL_CHANNEL_MAX dans omv_protocol_channel.h, et les ports appellent désormais py_protocol_init0() à l’initialisation. La définition de carte OMV_PAG7936_MIPI_CSI2 a disparu (l’interface est sélectionnée à l’exécution). Des mises à jour de dépendances CI et un correctif pour les changelogs de version vides complètent le tout. Consultez l’historique du dépôt du micrologiciel pour les détails utiles aux forks.

Liste de contrôle de migration#

  • Toujours sur import sensor ? Cela fonctionne, avec un avertissement. Passez à csi (migration v5.0.0) ; remplacez disable_delays / disable_full_flush par les arguments du constructeur csi.CSI() et supprimez les appels à get_fb / à la rotation automatique.

  • Vous chargez une seule image avec copy_to_fb=True et vous vous attendez à la voir ? Ajoutez img.flush() après le chargement.

  • Vous avez copié le post-traitement YOLOv8 ? Indexez la sortie seuillée par ligne (bb[:, 4:]) plutôt que par colonne.

  • Vous comparez csi0.framesize() après avoir défini un tuple ? Il renvoie désormais csi.CUSTOM.

  • Tout le reste : reflashez et exécutez.