v5.0.1#

v5.0.1 é uma versão de manutenção sobre a v5.0.0 — o módulo legado sensor se torna uma camada de compatibilidade em Python sobre csi, imagens carregadas no frame buffer agora são pré-visualizadas como quadros da câmera, os codificadores JPEG perdem seu limite de saída de 1 MB e tratam o estouro corretamente, e há um conjunto de correções de câmera, protocolo, rede e biblioteca de ML. Ela não introduz nenhuma mudança incompatível de API para scripts escritos com base em csi; as poucas mudanças de comportamento estão listadas em mudanças incompatíveis de API.

Destaques#

  • O módulo sensor agora é um módulo Python congelado construído sobre csi. Ele imprime um aviso de obsolescência na importação; algumas funções que o módulo csi não consegue suportar agora levantam OSError. Veja as mudanças no módulo sensor.

  • Imagens carregadas são pré-visualizadas como quadros da câmera. Uma imagem colocada no frame buffer com copy_to_fb=True (image.Image, image.ImageIO.read(), fir.snapshot(), tof.snapshot()) é descarregada para a IDE — com qualquer coisa desenhada nela — quando a próxima imagem sobrescreve o frame buffer, em vez de imediatamente. Veja as mudanças na pré-visualização.

  • Reformulação do codificador JPEG. O limite de 1 MB do buffer de saída desapareceu (o buffer é dimensionado a partir da memória livre), o estouro tanto no caminho de software quanto no de hardware é tratado em vez de gravar arquivos truncados, e salvar uma imagem comprimida com a outra extensão comprimida levanta uma exceção em vez de gravar lixo.

  • Novo protocol.poll() e seis novos widgets CBOR (text, lineedit, pushbutton, spinbox, radio, waveform) para protocol.CBORChannel.

  • Pós-processador YOLO Pro, suporte a FLIR Lepton 3.1R / UW, leituras em rajada do IMU, CAN na OpenMV N6 e um alvo de simulador com suporte a rede.

Novos recursos#

  • YoloPro — um novo pós-processador para modelos de detecção de objetos YOLO Pro da Edge Impulse, mais um exemplo yolo_pro_detector.py. (f3f150ebd, ea7bbb398)

  • protocol.poll() — executa uma iteração da tarefa do protocolo sob demanda, para transportes personalizados que não são acionados pela interrupção USB nem pelo timer poll_ms. protocol.init() também pode ser chamado novamente para reinicializar a pilha. (c00c215f9, f849ffb1b)

  • Mais widgets de canal CBOR — protocol.CBORChannel.add() ganha text (string estática), lineedit (string gravável), pushbutton (ação momentânea), spinbox (entrada numérica em passos), radio (grupo de opções) e waveform (série temporal 1D com os argumentos sample_rate, series e typecode; atribua bytes de amostras intercaladas para transmiti-la). (8016d29ba)

  • csi.CUSTOM — csi.CSI.framesize() agora retorna uma constante utilizável depois que uma resolução (w, h) personalizada foi definida, em vez de um inteiro anônimo. (af8841654)

  • Leitura em rajada do IMU — imu.__read_reg() aceita um buffer gravável opcional e o preenche a partir de registradores consecutivos em uma única transação. (244ca480a)

  • FLIR Lepton 3.1R e Lepton UW são reconhecidos pelo driver do Lepton, incluindo seus modos de ganho radiométrico. (0fc356632)

  • Rede no simulador — o alvo QEMU MPS2_AN500 agora tem lwIP e uma NIC em modo usuário, com requests, mqtt e sensor congelados no firmware, e um teste unitário de rede. (23546dfb1, 61d187305, 15096c3a2)

  • Exemplo de API compatível com OpenAI — openai_compatible.py captura um JPEG e o envia para um endpoint de chat-completions para descrição da cena. (79033c6aa)

  • Exemplos LoRa SX126x — o driver lora-sx126x da micropython-lib (com lora-sync / lora-async) está congelado no firmware da OpenMV RT1062, com exemplos de emissor/receptor/ping-pong/streaming de imagem para ligar um módulo SX1261 ou SX1262 ao barramento SPI. Este é um suporte contribuído pela comunidade; a OpenMV não vende hardware LoRa. (19576e1b1)

Outras mudanças e melhorias#

  • Reescrita da biblioteca requests — respostas com transferência em chunks são decodificadas, um argumento timeout (padrão 5 s) é exposto, corpos JSON e string são serializados/codificados corretamente, os cabeçalhos são analisados sem distinção entre maiúsculas e minúsculas e a linha de status por posição, o dicionário headers do chamador é copiado (de modo que auth não vaza mais para requisições posteriores) e o corpo é lido em blocos para um bytearray. (889f0b096)

  • mqtt importa ssl sob demanda, de modo que o módulo e as conexões simples (sem TLS) funcionam em builds sem suporte a SSL. (c2e0899e8)

  • Buffer de saída JPEG dimensionado a partir da memória livre em vez de um limite fixo de 1 MB; os codificadores reduzem o buffer ao tamanho codificado antes de a imagem ser gravada, de modo que capturas de sensores grandes em alta qualidade não falham mais. (aa1ca6776)

  • Limpeza do pós-processamento de ML — a geração de bounding boxes foi padronizada entre os pós-processadores Darknet, Edge Impulse e Ultralytics, e a saída do YOLOv8 é transposta após a aplicação do limiar, de modo que é armazenada uma linha por detecção, como nos outros modelos. (b5c7853f2, c45f99cad)

  • Desligamento seguro do PAG7936 — uma nova flag de parada do sensor coloca o PAG7936 em repouso antes de alternar RESET/PWDN, corrigindo travamentos quando o sensor é usado com um cabo de extensão. O driver também seleciona seu conjunto de registradores MIPI CSI-2 ou paralelo a partir do endereço I2C do sensor em tempo de execução, em vez de em tempo de compilação. (10026530c, f6acf14ec, 5f0251c74)

  • O ritmo de reprodução do ImageIO agora atende aos eventos pendentes enquanto aguarda o intervalo entre quadros, em vez de dormir em WFI. (a54790193)

  • Atualizações do submódulo MicroPython — suporte completo a rede no port QEMU, machine.mem_backup no STM32 via SRAM de backup/registradores BKP, controle de fluxo de hardware do SDIO mantido desabilitado no STM32F4 e reutilização de atributos da MPU para regiões não cacheáveis. (31ada5626, ab61d27a6, 06bddf13a)

  • differential-translation.py captura por meio de seu objeto csi.CSI em vez do módulo sensor obsoleto, e o espaçamento das importações nos exemplos foi normalizado. (68c866e7f, 9ceff4513)

Correções de bugs#

Câmera e sensores:

  • Definir duas resoluções (w, h) personalizadas em sequência deixava o sensor no primeiro tamanho enquanto csi.CSI.width() / height() informavam o segundo; o caminho rápido de “sem mudança” agora exclui tamanhos personalizados. (cfbb70156)

  • csi.CSI.lens_correction() interpretava radi e coef como booleanos, de modo que os valores passados ao driver não eram os fornecidos. (ab44b3a77)

  • PAG7936: definir exposição e ganho em sequência fazia um sobrescrever o outro (ambos compartilham um único modo manual e os registradores de leitura ficam um quadro atrasados); o driver agora inicializa os registradores manuais apenas ao entrar no modo manual e escreve somente o controle que está sendo definido. (e7a18c0a0)

  • A captura BAYER do PAG7936 e do PS5520 na OpenMV N6 falhava com “Failed to initialize the CSI interface” em qualquer tamanho diferente da resolução completa, porque o ISP da N6 não consegue redimensionar Bayer bruto. Os sensores agora operam em um modo nativo correspondente ao tamanho solicitado para BAYER (PS5520: VGA, HD, SXGA-M, FHD, QHD, WQXGA2; QVGA não tem modo nativo e não é suportado). (fe6790055, b7622b245)

Codificação e salvamento de imagens:

  • Codificador JPEG de software: o estouro do buffer de saída era sempre fatal porque o caminho de realloc estava desabilitado; agora ele aumenta o buffer (metade do seu tamanho por vez) quando é o proprietário dele, recua de forma limpa quando a memória acaba e reduz o resultado ao tamanho final. jpeg_write / mjpeg_write não gravam mais o buffer após uma codificação com falha. (28e1110be)

  • Codificadores JPEG de hardware (STM32): o estouro retornava uma imagem parcialmente codificada com o tamanho da alocação, produzindo arquivos truncados sem marcador EOI (por exemplo, uma captura de 5 MP com qualidade 100 e a metade inferior em branco). Agora eles informam o estouro, liberam o buffer em caso de falha e o reduzem em caso de sucesso. (22ce9619c)

  • O codificador VC8000 produzia silenciosamente croma 4:2:0 para toda requisição; a subamostragem diferente de 4:2:0 agora recorre ao codec de HW que a suporta. (71f2be7f2)

  • image.Image.save() de uma imagem PNG como .jpg gravava até 1 MB de heap não inicializado, e de uma imagem JPEG como .png gravava um arquivo vazio. Ambos agora levantam uma exceção; uma imagem que já está no formato de destino continua sendo copiada como está. (6c1fdf822)

  • png_write agora verifica o valor de retorno do compressor e comprime antes de criar o arquivo, de modo que uma falha não deixa mais um arquivo vazio para trás. (557f52d66)

Módulo image:

  • image.Image.get_pixel() com rgbtuple=True em imagens BAYER e YUV gravava o pixel convertido além de uma variável local da pilha, em um deslocamento controlado pelo chamador. (13f2a17b6)

  • gif.Gif.add_frame() teve um ramo inalcançável de conversão Bayer/YUV removido; apenas imagens GRAYSCALE e RGB565 são aceitas, como a API Python já impunha. (f20d99d96)

Protocolo:

  • Registrar um canal dinâmico com todos os slots já em uso causava uma escrita fora dos limites; o ID do canal agora é verificado primeiro, e os IDs de canal reservados são verificados estaticamente para caber na tabela de canais. (68f635d1f)

  • Objetos de canal dinâmico sobreviviam a um soft reset nos root pointers, de modo que o GC continuava varrendo blocos de heap obsoletos da execução anterior; a tabela agora é limpa na inicialização. (ef0ebb03b, e23641145)

Ports:

  • i.MX RT: adicionada a desinicialização de CAN e Encoder que faltava no soft reset. (7cb9d3dc2)

Suporte a hardware e placas#

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

  • OpenMV AE3 — o driver SPI sdcard está congelado no firmware para o soquete microSD do AE3 Battery Shield. (a258f4814)

  • OpenMV RT1062 — lora-sx126x / lora-sync / lora-async congelados no firmware (veja Novos recursos).

  • FLIR Lepton 3.1R / UW — reconhecidos pelo driver do Lepton em todas as placas compatíveis com Lepton.

  • PAG7936 — parada para desligamento seguro, seleção de interface em tempo de execução, correção de exposição/ganho e captura BAYER na N6.

  • PS5520 — captura BAYER na N6 em tamanhos nativos.

  • Simulador (MPS2_AN500) — rede.

  • Todas as placas — o módulo de compatibilidade sensor está congelado no manifesto de todas as placas.

Mudanças incompatíveis de API#

A v5.0.1 não introduz nenhuma mudança incompatível nas APIs csi ou image. Scripts que rodavam na v5.0.0 rodam sem alterações, com as seguintes mudanças de comportamento.

módulo sensor (behavior)#

O módulo nativo sensor (modules/py_csi.c) foi removido e substituído por um módulo Python congelado que implementa a mesma API sobre csi. Veja 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. no terminal.

  • O objeto csi.CSI oculto é criado na importação, de modo que uma câmera ausente agora levanta um erro em import sensor em vez de em sensor.reset().

  • Estas funções agora levantam OSError porque csi não tem equivalente: get_fb(), alloc_extra_fb(), dealloc_extra_fb(), set_auto_rotation(), get_auto_rotation(), disable_delays(), disable_full_flush(). (As duas funções *_extra_fb já levantavam exceção na v5.0.0.) Use csi.CSI(delays=False) / csi.CSI(fflush=False) para as duas últimas.

  • Os framesizes que csi não exporta (QQCIF, QQSIF, QQQQVGA, HQQQQVGA, HQQQVGA, HQQVGA, B64X32, B64X64, B128X64, B128X128, B160X160, B320X320, LCD, QQVGA2) agora são tuplas (w, h) repassadas como resoluções personalizadas. get_framesize() retorna a tupla que foi definida enquanto a câmera ainda estiver nesse tamanho, de modo que as verificações de igualdade com as constantes continuam funcionando.

  • ioctl() repassa no máximo quatro argumentos após a requisição.

  • sleep() / shutdown() levantam OSError em caso de falha, como antes (o RuntimeError de csi é traduzido).

Migre para csi — veja a tabela de migração da v5.0.0.

Carregamento de imagens no frame buffer (behavior)#

As funções que carregam uma imagem no frame buffer — image.Image com copy_to_fb=True, image.Image.copy() / image.Image.scale() e as conversões to_* com copy_to_fb=True, image.ImageIO.read(), fir.snapshot() e tof.snapshot() com copy_to_fb=True — costumavam enviar a nova imagem para a prévia da IDE imediatamente, de modo que qualquer coisa desenhada na imagem retornada nunca era vista. Agora elas marcam o frame buffer como pendente e o descarregam, com tudo o que foi desenhado nele, logo antes de a próxima imagem sobrescrevê-lo — o mesmo comportamento de csi.CSI.snapshot().

Commits: 87b6db5ee, 7b1a35c2f, f773c740d

Loops que leem um fluxo de imagens não precisam de nenhuma mudança e agora mostram seus desenhos. Um script que carrega uma única imagem e para deve descarregá-la explicitamente:

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

Biblioteca de ML (behavior)#

Afeta apenas código que herda de ou copia os pós-processadores fornecidos. YoloV8 agora transpõe a saída do modelo após a aplicação do limiar, de modo que as detecções sobreviventes são armazenadas uma linha por caixa (bb[:, 4:]), em consonância com os pós-processadores Darknet e Edge Impulse, em vez de uma coluna por caixa (bb[4:, :]). Os resultados públicos ((x, y, w, h), score) não mudaram.

Commits: c45f99cad, b5c7853f2

módulo protocol (minor)#

protocol.poll() está de volta. A v5.0.0 o removeu quando a tarefa do protocolo passou para o timer; ele retorna como uma forma explícita de acionar a tarefa para transportes personalizados. Nada mais mudou — scripts que nunca o chamaram não são afetados.

Commit: c00c215f9

Compilação / ferramentas (tooling)#

Nada disto afeta scripts MicroPython. py_image.c foi dividido, com os objetos descritores (cascade, keypoints, LBP, keypoint match) movidos para py_image_descriptor.c e os objetos de estatísticas (similarity, statistics, percentile, threshold, histogram) para py_image_stats.c. A API de codificadores do imlib foi alinhada com o restante do imlib: jpeg_compress / png_compress retornam 0 em caso de sucesso e -1 em caso de erro, e jpeg_compress perdeu seu argumento realloc (o redimensionamento é condicionado à propriedade do buffer). OMV_PROTOCOL_MAX_CHANNELS passou a ser OMV_PROTOCOL_CHANNEL_MAX em omv_protocol_channel.h, e os ports agora chamam py_protocol_init0() na inicialização. O define de placa OMV_PAG7936_MIPI_CSI2 desapareceu (a interface é selecionada em tempo de execução). Atualizações de dependências do CI e uma correção para changelog de release vazio completam o conjunto. Veja o histórico do repositório do firmware para detalhes relevantes a forks.

Checklist de migração#

  • Ainda usa import sensor? Funciona, com um aviso. Migre para csi (migração da v5.0.0); substitua disable_delays / disable_full_flush pelos argumentos do construtor csi.CSI() e remova as chamadas a get_fb / rotação automática.

  • Carrega uma única imagem com copy_to_fb=True e espera vê-la? Adicione img.flush() após o carregamento.

  • Copiou o pós-processador YOLOv8? Indexe a saída filtrada pelo limiar por linha (bb[:, 4:]) em vez de por coluna.

  • Compara csi0.framesize() depois de definir uma tupla? Agora ele retorna csi.CUSTOM.

  • Todo o resto: regrave o firmware e execute.