v5.0.1#

v5.0.1 es una versión de mantenimiento sobre v5.0.0: el módulo sensor heredado pasa a ser una capa de compatibilidad de Python sobre csi, las imágenes cargadas en el búfer de fotogramas (frame buffer) ahora se previsualizan como los fotogramas de cámara, los codificadores JPEG pierden su límite de salida de 1 MB y gestionan correctamente el desbordamiento, y hay un lote de correcciones de cámara, protocolo, red y biblioteca ML. No introduce ningún cambio de API incompatible para los scripts escritos contra csi; los pocos cambios de comportamiento se enumeran en cambios de API incompatibles.

Aspectos destacados#

  • El módulo sensor es ahora un módulo de Python congelado construido sobre csi. Imprime un aviso de obsolescencia al importarlo; algunas funciones que el módulo csi no puede admitir ahora generan OSError. Consulte los cambios del módulo sensor.

  • Las imágenes cargadas se previsualizan como los fotogramas de cámara. Una imagen colocada en el búfer de fotogramas (frame buffer) con copy_to_fb=True (image.Image, image.ImageIO.read(), fir.snapshot(), tof.snapshot()) se vuelca al IDE — junto con todo lo dibujado sobre ella — cuando la siguiente imagen sobrescribe el búfer de fotogramas, en lugar de inmediatamente. Consulte los cambios de la vista previa.

  • Renovación del codificador JPEG. Desaparece el límite de 1 MB del búfer de salida (el búfer se dimensiona según la memoria libre), el desbordamiento en las rutas por software y por hardware se gestiona en lugar de escribir archivos truncados, y guardar una imagen comprimida con la otra extensión comprimida genera una excepción en lugar de escribir basura.

  • Nuevo protocol.poll() y seis nuevos widgets CBOR (text, lineedit, pushbutton, spinbox, radio, waveform) para protocol.CBORChannel.

  • Posprocesador YOLO Pro, soporte para FLIR Lepton 3.1R / UW, lecturas en ráfaga de la IMU, CAN en la OpenMV N6 y un objetivo de simulador con capacidad de red.

Nuevas características#

  • YoloPro: un nuevo posprocesador para los modelos de detección de objetos YOLO Pro de Edge Impulse, además de un ejemplo yolo_pro_detector.py. (f3f150ebd, ea7bbb398)

  • protocol.poll(): ejecuta una iteración de la tarea del protocolo bajo demanda, para transportes personalizados que no son controlados por la interrupción USB ni por el temporizador poll_ms. protocol.init() también se puede llamar de nuevo para reinicializar la pila. (c00c215f9, f849ffb1b)

  • Más widgets de canal CBOR: protocol.CBORChannel.add() incorpora text (cadena estática), lineedit (cadena escribible), pushbutton (acción momentánea), spinbox (entrada numérica por pasos), radio (grupo de opciones) y waveform (serie temporal 1D con argumentos sample_rate, series y typecode; asigne bytes de muestras intercaladas para transmitirla). (8016d29ba)

  • csi.CUSTOM: csi.CSI.framesize() ahora devuelve una constante utilizable después de establecer una resolución (w, h) personalizada, en lugar de un entero anónimo. (af8841654)

  • Lectura en ráfaga de la IMU: imu.__read_reg() acepta un búfer escribible opcional y lo rellena a partir de registros consecutivos en una sola transacción. (244ca480a)

  • FLIR Lepton 3.1R y Lepton UW son reconocidos por el controlador Lepton, incluidos sus modos de ganancia radiométricos. (0fc356632)

  • Red en el simulador: el objetivo QEMU MPS2_AN500 ahora cuenta con lwIP y una NIC en modo usuario, con requests, mqtt y sensor congelados en el firmware, además de una prueba unitaria de red. (23546dfb1, 61d187305, 15096c3a2)

  • Ejemplo de API compatible con OpenAI: openai_compatible.py captura un JPEG y lo envía a un punto de conexión de chat-completions para obtener una descripción de la escena. (79033c6aa)

  • Ejemplos LoRa SX126x: el controlador lora-sx126x de micropython-lib (con lora-sync / lora-async) está congelado en el firmware de la OpenMV RT1062, con ejemplos de emisor/receptor/ping-pong/transmisión de imágenes para conectar un módulo SX1261 o SX1262 al bus SPI. Se trata de soporte aportado por la comunidad; OpenMV no vende hardware LoRa. (19576e1b1)

Otros cambios y mejoras#

  • Reescritura de la biblioteca requests: se decodifican las respuestas con transferencia por fragmentos, se expone un argumento timeout (5 s de forma predeterminada), los cuerpos JSON y de cadena se serializan/codifican correctamente, las cabeceras se analizan sin distinguir mayúsculas de minúsculas y la línea de estado por posición, el diccionario headers del llamador se copia (de modo que auth ya no se filtra a solicitudes posteriores) y el cuerpo se lee por bloques en un bytearray. (889f0b096)

  • mqtt importa ssl de forma diferida, por lo que el módulo y las conexiones sin cifrar (sin TLS) funcionan en compilaciones sin soporte SSL. (c2e0899e8)

  • Búfer de salida JPEG dimensionado según la memoria libre en lugar de un límite fijo de 1 MB; los codificadores recortan el búfer al tamaño codificado antes de escribir la imagen, de modo que las capturas de sensores grandes con alta calidad ya no fallan. (aa1ca6776)

  • Limpieza del posprocesamiento de ML: la generación de cajas delimitadoras se estandariza en los posprocesadores Darknet, Edge Impulse y Ultralytics, y la salida de YOLOv8 se transpone después de aplicar el umbral para almacenarla con una fila por detección, como en los demás modelos. (b5c7853f2, c45f99cad)

  • Apagado seguro del PAG7936: un nuevo indicador de parada del sensor pone el PAG7936 en reposo antes de conmutar RESET/PWDN, lo que corrige los bloqueos cuando el sensor se usa con un cable de extensión. El controlador también selecciona su conjunto de registros MIPI CSI-2 o paralelo a partir de la dirección I2C del sensor en tiempo de ejecución, en lugar de en tiempo de compilación. (10026530c, f6acf14ec, 5f0251c74)

  • El ritmo de reproducción de ImageIO ahora atiende los eventos pendientes mientras espera el intervalo entre fotogramas, en lugar de dormir en WFI. (a54790193)

  • Actualizaciones del submódulo MicroPython: soporte de red completo en el port QEMU, machine.mem_backup en STM32 mediante la SRAM de respaldo/registros BKP, control de flujo por hardware de SDIO mantenido desactivado en STM32F4 y reutilización de atributos de la MPU para regiones no cacheables. (31ada5626, ab61d27a6, 06bddf13a)

  • differential-translation.py captura a través de su objeto csi.CSI en lugar del módulo sensor obsoleto, y se normalizó el espaciado de las importaciones en los ejemplos. (68c866e7f, 9ceff4513)

Corrección de errores#

Cámara y sensores:

  • Establecer dos resoluciones (w, h) personalizadas seguidas dejaba el sensor en el primer tamaño mientras csi.CSI.width() / height() informaban del segundo; la ruta rápida de «sin cambios» ahora excluye los tamaños personalizados. (cfbb70156)

  • csi.CSI.lens_correction() interpretaba radi y coef como booleanos, por lo que los valores pasados al controlador no eran los indicados. (ab44b3a77)

  • PAG7936: establecer la exposición y la ganancia una tras otra hacía que se sobrescribieran mutuamente (ambas comparten un único modo manual y los registros de lectura van un fotograma por detrás); el controlador ahora inicializa los registros manuales solo al entrar en modo manual y escribe únicamente el control que se está estableciendo. (e7a18c0a0)

  • La captura BAYER con PAG7936 y PS5520 en la OpenMV N6 fallaba con «Failed to initialize the CSI interface» en cualquier tamaño distinto de la resolución completa, porque el ISP de la N6 no puede reescalar Bayer sin procesar. Los sensores ahora funcionan en un modo nativo que coincide con el tamaño solicitado para BAYER (PS5520: VGA, HD, SXGA-M, FHD, QHD, WQXGA2; QVGA no tiene modo nativo y no se admite). (fe6790055, b7622b245)

Codificación y guardado de imágenes:

  • Codificador JPEG por software: el desbordamiento del búfer de salida siempre era fatal porque la ruta de realloc estaba desactivada; ahora amplía el búfer (la mitad de su tamaño cada vez) cuando es su propietario, retrocede limpiamente cuando se agota la memoria y recorta el resultado. jpeg_write / mjpeg_write ya no escriben el búfer tras una codificación fallida. (28e1110be)

  • Codificadores JPEG por hardware (STM32): el desbordamiento devolvía una imagen parcialmente codificada con el tamaño de la asignación, lo que producía archivos truncados sin marcador EOI (p. ej. una captura de 5 MP con calidad 100 y la mitad inferior en blanco). Ahora informan del desbordamiento, liberan el búfer en caso de fallo y lo recortan en caso de éxito. (22ce9619c)

  • El codificador VC8000 producía silenciosamente croma 4:2:0 para todas las solicitudes; el submuestreo distinto de 4:2:0 ahora recurre al códec de hardware que lo admite. (71f2be7f2)

  • image.Image.save() de una imagen PNG como .jpg escribía hasta 1 MB de montículo (heap) sin inicializar, y de una imagen JPEG como .png escribía un archivo vacío. Ahora ambos generan una excepción; una imagen que ya está en el formato de destino se sigue copiando tal cual. (6c1fdf822)

  • png_write ahora comprueba el valor de retorno del compresor y comprime antes de crear el archivo, de modo que un fallo ya no deja atrás un archivo vacío. (557f52d66)

Módulo image:

  • image.Image.get_pixel() con rgbtuple=True en imágenes BAYER y YUV escribía el píxel convertido más allá de una variable local de la pila, en un desplazamiento controlado por el llamador. (13f2a17b6)

  • gif.Gif.add_frame() eliminó una rama de conversión Bayer/YUV inalcanzable; solo se aceptan imágenes GRAYSCALE y RGB565, como ya exigía la API de Python. (f20d99d96)

Protocolo:

  • Registrar un canal dinámico con todas las ranuras ya en uso provocaba una escritura fuera de límites; ahora se comprueba primero el ID del canal, y se verifica estáticamente que los ID de canal reservados caben en la tabla de canales. (68f635d1f)

  • Los objetos de canal dinámico sobrevivían a un reinicio suave (soft reset) en los punteros raíz, por lo que el GC seguía escaneando bloques de montículo (heap) obsoletos de la ejecución anterior; la tabla ahora se limpia en la inicialización. (ef0ebb03b, e23641145)

Ports:

  • i.MX RT: se añadió la desinicialización de CAN y Encoder que faltaba en el reinicio suave (soft reset). (7cb9d3dc2)

Hardware y soporte de placas#

  • OpenMV N6: CAN ahora está habilitado (machine.CAN). (294f0febd, 91e1c9573)

  • OpenMV AE3: el controlador SPI sdcard está congelado en el firmware para el zócalo microSD del AE3 Battery Shield. (a258f4814)

  • OpenMV RT1062: lora-sx126x / lora-sync / lora-async congelados en el firmware (consulte Nuevas características).

  • FLIR Lepton 3.1R / UW: reconocidos por el controlador Lepton en todas las placas compatibles con Lepton.

  • PAG7936: parada de apagado seguro, selección de interfaz en tiempo de ejecución, corrección de exposición/ganancia y captura BAYER en la N6.

  • PS5520: captura BAYER en la N6 en tamaños nativos.

  • Simulador (MPS2_AN500): red.

  • Todas las placas: el módulo de compatibilidad sensor está congelado en el manifiesto de todas las placas.

Cambios de API incompatibles#

v5.0.1 no introduce cambios incompatibles en las API de csi ni de image. Los scripts que funcionaban en v5.0.0 funcionan sin cambios, con los siguientes cambios de comportamiento.

módulo sensor (behavior)#

El módulo nativo sensor (modules/py_csi.c) se eliminó y se reemplazó por un módulo de Python congelado que implementa la misma API sobre csi. Consulte sensor.

Commit: 5e3d40631

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

  • El objeto csi.CSI oculto se crea al importar, por lo que la ausencia de cámara ahora genera un error en import sensor en lugar de en sensor.reset().

  • Estas funciones ahora generan OSError porque csi no tiene equivalente: get_fb(), alloc_extra_fb(), dealloc_extra_fb(), set_auto_rotation(), get_auto_rotation(), disable_delays(), disable_full_flush(). (Las dos funciones *_extra_fb ya generaban una excepción en v5.0.0.) Use csi.CSI(delays=False) / csi.CSI(fflush=False) para las dos últimas.

  • Los framesizes que csi no exporta (QQCIF, QQSIF, QQQQVGA, HQQQQVGA, HQQQVGA, HQQVGA, B64X32, B64X64, B128X64, B128X128, B160X160, B320X320, LCD, QQVGA2) son ahora tuplas (w, h) que se pasan como resoluciones personalizadas. get_framesize() devuelve la tupla que se estableció mientras la cámara siga en ese tamaño, de modo que las comparaciones de igualdad con las constantes siguen funcionando.

  • ioctl() reenvía como máximo cuatro argumentos después de la solicitud.

  • sleep() / shutdown() generan OSError en caso de fallo, como antes (el RuntimeError de csi se traduce).

Migre a csi: consulte la tabla de migración de v5.0.0.

Carga de imágenes en el búfer de fotogramas (behavior)#

Las funciones que cargan una imagen en el búfer de fotogramas (frame buffer) — image.Image con copy_to_fb=True, image.Image.copy() / image.Image.scale() y las conversiones to_* con copy_to_fb=True, image.ImageIO.read(), fir.snapshot() y tof.snapshot() con copy_to_fb=True — antes enviaban la nueva imagen a la vista previa del IDE de inmediato, por lo que nunca se veía nada de lo dibujado sobre la imagen devuelta. Ahora marcan el búfer de fotogramas como pendiente y lo vuelcan, con todo lo dibujado sobre él, justo antes de que la siguiente imagen lo sobrescriba: el mismo comportamiento que csi.CSI.snapshot().

Commits: 87b6db5ee, 7b1a35c2f, f773c740d

Los bucles que leen un flujo de imágenes no necesitan cambios y ahora muestran lo que dibujan. Un script que carga una única imagen y se detiene debe volcarla explícitamente:

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

Biblioteca ML (behavior)#

Solo afecta al código que hereda de los posprocesadores incluidos o los copia. YoloV8 ahora transpone la salida del modelo después de aplicar el umbral, de modo que las detecciones que sobreviven se almacenan con una fila por caja (bb[:, 4:]), igual que los posprocesadores Darknet y Edge Impulse, en lugar de una columna por caja (bb[4:, :]). Los resultados públicos ((x, y, w, h), score) no cambian.

Commits: c45f99cad, b5c7853f2

módulo protocol (minor)#

protocol.poll() está de vuelta. v5.0.0 lo eliminó cuando la tarea del protocolo pasó al temporizador; regresa como una forma explícita de controlar la tarea para transportes personalizados. Nada más cambió: los scripts que nunca lo llamaron no se ven afectados.

Commit: c00c215f9

Compilación / herramientas (tooling)#

Nada de esto afecta a los scripts de MicroPython. py_image.c se dividió: los objetos descriptores (cascade, keypoints, LBP, keypoint match) pasan a py_image_descriptor.c y los objetos de estadísticas (similarity, statistics, percentile, threshold, histogram) a py_image_stats.c. La API del codificador de imlib se alineó con el resto de imlib: jpeg_compress / png_compress devuelven 0 en caso de éxito y -1 en caso de error, y jpeg_compress perdió su argumento realloc (el redimensionamiento depende de la propiedad del búfer). OMV_PROTOCOL_MAX_CHANNELS pasó a ser OMV_PROTOCOL_CHANNEL_MAX en omv_protocol_channel.h, y los ports ahora llaman a py_protocol_init0() en la inicialización. La definición de placa OMV_PAG7936_MIPI_CSI2 desapareció (la interfaz se selecciona en tiempo de ejecución). Lo completan actualizaciones de dependencias de CI y una corrección para el changelog de versiones vacío. Consulte el historial del repositorio del firmware para los detalles relevantes para forks.

Lista de verificación de migración#

  • ¿Sigue usando import sensor? Funciona, con un aviso. Pase a csi (migración a v5.0.0); reemplace disable_delays / disable_full_flush por los argumentos del constructor csi.CSI() y elimine las llamadas a get_fb / rotación automática.

  • ¿Carga una única imagen con copy_to_fb=True y espera verla? Añada img.flush() después de cargarla.

  • ¿Copió el posprocesador YOLOv8? Indexe la salida umbralizada por fila (bb[:, 4:]) en lugar de por columna.

  • ¿Compara csi0.framesize() después de establecer una tupla? Ahora devuelve csi.CUSTOM.

  • Todo lo demás: vuelva a flashear y ejecute.