v5.0.0

v5.0.0 es una versión principal. Lo más destacado: el enlace con el host OpenMV Protocol V2 reconstruido, una API de cámara csi basada en clases que escala a placas multicámara, un objetivo de simulador ejecutable, la estimación de pose única MoveNet, MicroPython 1.28 y un gran lote de correcciones de cámara, ML y ToF. También incorpora una serie de cambios de API incompatibles: a continuación se enumeran todos los cambios visibles para el usuario desde la v4.8.1, junto con la forma exacta de migrar.

Aspectos destacados

  • OpenMV Protocol V2. El enlace host/IDE se reconstruyó desde cero: con tramas, secuenciado, verificado con CRC y con canales multiplexados para stdio, la vista previa del flujo y los datos del usuario. Un nuevo módulo protocol permite a los scripts crear sus propios transportes y canales de datos. Consulte los cambios del módulo protocol.

  • API de cámara csi basada en clases. import sensor pasa a ser import csi / csi.CSI, con soporte nativo multicámara. Consulte la migración a csi.

  • Objetivo de simulador. El firmware ahora se compila y ejecuta bajo el simulador Arm FVP / QEMU (MPS2/MPS3), incluida la emulación de NPU, ROMFS y PSRAM: los scripts de visión y ML pueden ejecutarse sin hardware conectado.

  • Estimación de pose MoveNet. Un nuevo posprocesador MoveNet más un modelo movenet_singlepose_192.tflite incluido en la OpenMV AE3 y la N6.

  • MicroPython 1.28 y ulab 6.12.0, herramientas ST Edge AI 4.0 y el OpenMV SDK externalizado (consulte los cambios de compilación / herramientas).

Nuevas características

Otros cambios y mejoras

  • MicroPython actualizado a 1.28.0 desde la base v4.8.1. Añade el modo de tarjeta SD de alta velocidad en H5/H7/N6, el reloj AHB5 en modo de bajo consumo y pines JTAG controlables como GPIO en la OPENMV_AE3.

  • ulab actualizado a 6.12.0: operador % nativo en ndarrays (se elimina el ayudante ml.utils.mod(); consulte los cambios de la biblioteca ML).

  • Herramientas ST Edge AI actualizadas a 4.0: afecta a la compilación y el despliegue de modelos ST en el dispositivo.

  • ml.Model: se eliminó el argumento de palabra clave load_to_fb; la memoria del modelo la gestiona automáticamente el asignador unificado.

  • image.Image.scale() en el lugar: ampliar una imagen en el lugar (por ejemplo img.scale(x_scale=2.0, y_scale=2.0)) ahora hace crecer el búfer de fotogramas (frame buffer) para que quepa en lugar de fallar.

  • Búfer de stdio más grande: el búfer de texto predeterminado hacia el IDE creció de 512 a 1024 bytes en OpenMV 2/3/4, Nicla Vision, AE3 y N6, de modo que las ráfagas de print() más grandes no se truncan.

  • Flujo de eventos del host más fluido: los eventos NOTIFY de stdout hacia el host se limitan a como máximo uno por lectura del host, en lugar de uno por cada print() que cruza la marca de agua del búfer circular.

  • Operaciones largas interrumpibles: los bucles de espera largos de dibujo de imágenes, GPU (Nema/Dave2D) y NPU ahora atienden eventos en un intervalo determinista, de modo que los scripts siguen respondiendo al botón Detener del IDE durante el trabajo intensivo.

Corrección de errores

Cámara y sensores:

  • find_apriltags() ya no corrompe los resultados en placas con caché de datos/GPU (N6, AE3), y ahora funciona en la AE3.

  • Se corrigió la salida de imagen Bayer del ISP de la STM32 N6 tras cambiar de formato de píxel.

  • Se corrigió la sobreexposición verde del balance de blancos automático en escenas brillantes y un caso de estadísticas de AWB sin inicializar en el primer fotograma; se elevó el límite de gamma del ISP de STM32 (de 32 a 63) para un rango más amplio de gamma/contraste/brillo.

  • La exposición automática del PS5520 ya no oscila con luz brillante; se rediseñó el comportamiento de AEC/AGC del PAG7936 (control combinado, techo de ganancia corregido).

  • Se restauró la carga del firmware de enfoque automático del OV5640 en Portenta/Nicla (corrección de I2C SUSPEND de MIMXRT).

  • Se corrigió un bloqueo en la captura de la cámara cuando un límite de tasa de fotogramas se combina con la captura JPEG (STM32).

  • Las lecturas de csi.IOCTL_GENX320_READ_EVENTS_RAW del GenX320 ya no distorsionan la vista previa del IDE.

  • csi.IOCTL_LEPTON_SET_MODE del FLIR Lepton mediante csi.CSI.ioctl() ahora funciona cuando se llama con un solo argumento.

Procesamiento de imágenes:

  • Se corrigió la mezcla alfa de draw_image() / blend() cuando se proporciona una máscara.

  • Se corrigió el orden de bits de la codificación/decodificación de PNG de 1 bit (BINARY) y la decodificación de escala de grises a partir de 1 bit.

  • Se corrigieron los metadatos de duración/FPS de la grabación de mjpeg.Mjpeg.

  • Se corrigió un desbordamiento de pila en la decodificación JPEG por software en placas con pila pequeña (OpenMV M7).

  • Se corrigió la detección automática del formato de archivo JPEG/PNG en hosts no ARM (simulador).

Time-of-Flight:

  • tof.read_depth() ya no genera una excepción en errores de medición transitorios y se recupera automáticamente de fallos del bus; el tiempo de espera predeterminado de tof.read_depth() / tof.snapshot() ahora es de 100 ms (consulte los cambios de tof).

  • Se corrigió la corrupción de datos de profundidad multizona en VL53L5CX / VL53L8CX.

ML y sistema:

  • La NPU se limpia correctamente cuando se interrumpe la inferencia en la N6.

  • Se restauró el despertar desde sueño profundo / espera en la N6; se corrigió el bloqueo al saltar al gestor de arranque (bootloader) de la AE3.

  • Se corrigieron fugas de memoria en el reinicio por software (GPU Nema de STM32) y un búfer de fotogramas (frame buffer) auxiliar recolectado prematuramente.

  • Los canales de protocolo Python personalizados ahora sobreviven a un reinicio por software, el transporte USB se recupera del reinicio del bus / endpoints bloqueados, y se corrigió la inundación de interrupciones SOF de USB.

Hardware y soporte de placas

  • OpenMV N6: Ethernet habilitado (red por cable); la SRAM AXI de la NPU (1,75 MB) fusionada en un grupo transitorio compartido para más RAM entre inferencias; despertar desde sueño profundo/espera; modelos TFLite y cascadas Haar incluidos en ROMFS.

  • OpenMV AE3: modelos y cascadas incluidos en ROMFS; cbor2 congelado en el firmware.

  • Alif (AE3, N6): despertar de bajo consumo con machine.RTC.

  • AprilTags de alta resolución: find_apriltags() a resolución completa del sensor en la AE3, la Arduino Giga y la Arduino Portenta H7.

  • Objetivos de simulador: MPS2_AN500 / MPS3_AN547 (Arm FVP / QEMU), con emulación de NPU, ROMFS y PSRAM.

Cambios de API incompatibles

Cambios de API visibles para el usuario entre la v4.8.1 y la v5.0.0. Alcance: módulos C de Python en modules/ y bibliotecas de Python en scripts/libraries/.

Cada cambio está etiquetado con su impacto:

  • major: la mayoría de los scripts necesitan ediciones.

  • minor: API limitada; solo afecta a los scripts que la usaban.

  • behavior: misma API, resultados diferentes; vuelva a comprobar los scripts ajustados.

  • tooling: solo afecta a la compilación desde el código fuente / forks derivados.

Los cambios se agrupan por impacto en ese orden: primero major, luego minor, behavior y tooling. Si solo desea portar su código, salte a la lista de verificación de migración al final para obtener una lista de tareas condensada. Cada hash de commit enlaza con su diff en GitHub.

sensor reemplazado por csi (major)

Todos los ejemplos oficiales se reescribieron para eliminar import sensor en favor de import csi. La antigua API funcional a nivel de módulo (sensor.reset(), sensor.set_pixformat(), …) queda sustituida por la API basada en clases csi.CSI, que escala de forma natural a placas con múltiples cámaras (csi0, csi1, …) y es obligatoria para todas las nuevas características (el argumento stream=, la transmisión multisensor, …).

El qstr sensor sigue conectado en modules/py_csi.c para compilaciones de firmware retrocompatibles, pero no recibirá nuevas características, y todos los ejemplos, la documentación y el código de las bibliotecas ahora asumen csi.

Commits: 945c5853c, 61f835b7e

De módulo a clase

Antes (sensor):

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

Después (csi):

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

Pares setter/getter colapsados en accesores combinados

En la nueva API, un método llamado sin argumentos devuelve el valor actual; llamado con un valor, lo establece. Los prefijos set_*/get_* desaparecen. Los nombres de los métodos también perdieron el sufijo ing donde resultaba redundante (windowingwindow). La columna de la nueva API enlaza con la documentación de referencia.

sensor (antiguo)

csi.CSI (nuevo)

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

Funciones sin equivalente directo

sensor (eliminado)

Qué usar en su lugar

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

image.Image (w, h, pixfmt): una imagen normal asignada en el montículo. El framebuffer ya no se reparte para búferes de usuario.

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

csi.CSI.snapshot(): el salto de fotogramas se integró en snapshot mediante sus argumentos time= / frames=.

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

Trasladado al constructor de csi.CSI: csi.CSI(delays=False) / csi.CSI(fflush=False).

sensor.get_frame_available()

csi.CSI.readable()

sensor.get_fb()

Eliminado. La imagen devuelta por csi.CSI.snapshot() es el manejador canónico.

sensor.set_framebuffers(n, expand=True)

csi.CSI.framebuffers(): se eliminó el argumento expand (consulte las mejoras posteriores de csi).

Novedades en csi.CSI

  • csi.CSI(stream=True|False): un selector en tiempo de construcción que elige qué CSI alimenta el framebuffer de vista previa (reemplaza al argumento update= por captura, consulte las mejoras posteriores de csi).

  • csi.CSI(cid=N) / csi.devices(): soporte multi-CSI para placas con más de un sensor de imagen.

módulo image: revisión de las firmas (major)

El módulo image experimentó el mayor cambio de API después de csi: cambiaron las firmas de dibujo, los objetos de resultado y varios detectores.

Los argumentos de coordenadas deben ser tuplas

modules/py_image.c se reescribió sobre mp_arg_parse_all. Todos los métodos de dibujo / píxel que antes tomaban argumentos posicionales separados x, y, ... ahora requieren que esas coordenadas se empaqueten en una única tupla.

Commits: d18bbc472, 0c60c94b9 (PR #3061)

Antes

Despué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)

Todos son métodos de image.Image.

Objetos de resultado convertidos a attrtuple

Estos tipos son ahora objetos attrtuple de MicroPython: similarity, statistics, percentile, threshold, line, circle, rect, qrcode, apriltag, datamatrix, barcode, displacement, kptmatch. El acceso a atributos sin paréntesis es ahora la forma canónica.

Commit: 3399d302e

Antes (estilo método):

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

Después (estilo atributo):

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

blob e histogram no han cambiado: conservan sus tipos existentes y sus accesores () (un attrtuple no puede expresar los valores calculados de forma diferida de una mancha (blob) ni los accesores con argumentos de un histograma).

Cambio de nombre del parámetro haar de find_features

image.Image.find_features(): scale_factor= se renombró a scale=.

Commit: be4c5cd73

get_regression: ahora siempre robusto, se añadió target_size

image.Image.get_regression() ahora usa siempre la regresión robusta (Theil-Sen). Se eliminó la antigua ruta rápida de mínimos cuadrados, por lo que la palabra clave robust= desaparece: lo que antes requería robust=True es ahora el único comportamiento. Un nuevo argumento target_size=(w, h) (predeterminado (80, 60)) escala el área de la ROI hacia abajo antes del ajuste Theil-Sen de O(N^2), de modo que siempre se ejecute con un tamaño de imagen razonable; los puntos extremos de la línea ajustada se reasignan a las coordenadas de origen. Se eliminó el ejemplo linear_regression_robust.py y se renombró linear_regression_fast.py a linear_regression.py.

Commits: c7c2e69a0, 0ff2afa72

find_line_segments: nuevo algoritmo

image.Image.find_line_segments(): el antiguo detector LSD se reemplazó por ED-Lines, y ganó un nuevo argumento threshold=50. La salida de los scripts ajustados anteriormente será diferente.

Commits: 87da2a7b7, 2c47b5735

Biblioteca de AprilTag reemplazada

image.Image.find_apriltags(): el detector de AprilTag se reemplazó por una nueva implementación. El conjunto de familias cambió:

Commit: e813bada7

Seguimiento del módulo csi (minor)

Pequeñas mejoras posteriores de csi sobre la migración a csi.

snapshot(update=…) eliminado

El argumento update de csi.CSI.snapshot() desaparece. Para evitar que un dispositivo CSI alimente el framebuffer de vista previa, deshabilítelo en el momento de la construcción:

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

Commits: 9a8077827, 26b79a2c5

Argumento expand de framebuffers() eliminado

csi.CSI.framebuffers(): el tercer argumento posicional (expand) desaparece; la firma es ahora framebuffers([count]).

Commit: 86cb3a5de

módulo protocol (minor)

Solo afecta a los scripts que controlaban el enlace con el host directamente. Consulte protocol.

timer_ms renombrado a poll_ms

protocol.init(): el argumento timer_ms se renombró a poll_ms.

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

Commits: 8a0635e8c, 95a290607

protocol.poll() eliminado

La tarea de protocolo ahora se programa internamente. Las llamadas a protocol.poll() generarán AttributeError.

Commit: 8a0635e8c

Argumento de configuración soft_reboot eliminado

protocol.init(): el argumento soft_reboot desaparece. Todos los transportes actuales toleran los reinicios por software, por lo que el comportamiento es ahora incondicional.

Commit: 0bf766aa2

módulos display (minor)

La salida de TV ahora pasa por un objeto display.TVDisplay en lugar del módulo independiente tv. display también ganó un ioctl() genérico.

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

módulo tof (behavior)

Misma API que antes; cambiaron los valores predeterminados y el manejo de errores. Consulte tof.

Tiempo de espera predeterminado cambiado

tof.read_depth() y tof.snapshot() (llamados con timeout=-1) ahora tienen un valor predeterminado de 100 ms en lugar de esperar indefinidamente. Pase un valor mayor explícito si necesita el comportamiento antiguo.

Commit: b6772b80d

Recuperación automática

El controlador ahora reinicia por completo el bus I2C y el sensor en errores de medición/tiempo de espera. Los ejemplos ya no llaman a tof.reset() en sus manejadores de excepciones: el código de usuario que hacía recuperación manual debería eliminarlo (entrará en conflicto con la nueva recuperación automática).

Commits: b6772b80d, 80ffaa5c3

Biblioteca ML (behavior)

Misma API, números diferentes: vuelva a comprobar cualquier pipeline de ML ajustado.

El preprocesamiento ahora estira en lugar de añadir bandas

Normalization ahora usa image.SCALE_ASPECT_IGNORE (estirar) en lugar de image.SCALE_ASPECT_EXPAND (bandas negras). El posprocesamiento de NMS también cambió a un escalado x/y independiente.

Nota

Impacto. Los detectores de estilo YOLO y los regresores de puntos clave generalmente mejoran. Los ejemplos de BlazeFace, BlazePalm, FaceLandmarks y HandLandmarks ahora requieren un recorte cuadrado manual en la ROI de entrada: los scripts de ejemplo se actualizaron; el código de usuario personalizado debe hacer lo mismo.

Commit: 68dc29a33

Ayudante ml.utils.mod() eliminado

ulab 6.12.0 admite % en ndarrays de forma nativa. El código que importaba mod de ml.utils debe usar a % b.

Commits: 35ece5728, 82fbd858c

Compilación / herramientas (tooling)

Nada de esto afecta a los scripts de MicroPython. Compilar el firmware desde el código fuente ahora requiere el OpenMV SDK externo (1.6.0, antes dentro del árbol). Se eliminaron varias herramientas de compilación del árbol y la N6 pasó a la pila TinyUSB; los forks derivados deberían revisar el historial del repositorio de firmware, en particular la firma de file_open() que elimina su argumento buffered.

Lista de verificación de migración

Para un porte limpio a la v5.0.0, el trabajo típico es:

  1. Reemplace import sensor por import csi; csi0 = csi.CSI() y traduzca cada llamada set_*/get_* a su accesor de csi.CSI (la migración a csi).

  2. Envuelva en tuplas los argumentos de coordenadas de img.draw_*, get_pixel() y set_pixel() (los cambios del módulo image).

  3. Elimine los () de los accesores de resultado attrtuple si desea la nueva forma idiomática, o deje el estilo antiguo tal cual, ya que los attrtuples siguen admitiendo accesores invocables (los cambios del módulo image).

  4. Audite find_line_segments(), get_regression() y cualquier elección de familia de find_apriltags() (los cambios del módulo image).

  5. Renombre timer_mspoll_ms en las llamadas a protocol.init(); elimine protocol.poll() y soft_reboot= (los cambios del módulo protocol).

  6. Para flujos de trabajo de ML: revise cualquier modelo que necesitara entrada con bandas negras (los cambios de la biblioteca ML).