v5.0.1#
v5.0.1은 v5.0.0 위에 올라간 유지 보수 릴리스입니다 — 레거시 sensor 모듈이 csi 위의 Python 호환 계층이 되고, 프레임 버퍼에 불러온 이미지가 이제 카메라 프레임처럼 미리보기에 표시되며, JPEG 인코더의 1 MB 출력 제한이 사라지고 오버플로가 올바르게 처리되며, 카메라, 프로토콜, 네트워킹, ML 라이브러리 수정이 다수 포함되었습니다. csi를 기준으로 작성된 스크립트에 대해서는 호환성을 깨는 API 변경이 없습니다. 몇 가지 동작 변경은 호환성을 깨는 API 변경 아래에 정리되어 있습니다.
주요 내용#
이제
sensor모듈은csi위에 구축된 프로즌 Python 모듈입니다. 임포트 시 사용 중단 경고를 출력하며,csi모듈이 지원할 수 없는 몇몇 함수는 이제OSError를 발생시킵니다. sensor 모듈 변경 사항을 참고하세요.불러온 이미지가 카메라 프레임처럼 미리보기에 표시됩니다.
copy_to_fb=True로 프레임 버퍼에 놓인 이미지(image.Image,image.ImageIO.read(),fir.snapshot(),tof.snapshot())는 즉시가 아니라 다음 이미지가 프레임 버퍼를 덮어쓸 때 — 그 위에 그린 내용과 함께 — IDE로 플러시됩니다. 미리보기 변경 사항을 참고하세요.JPEG 인코더 정비. 1 MB 출력 버퍼 상한이 사라졌고(버퍼 크기는 여유 메모리에 따라 결정됨), 소프트웨어 및 하드웨어 경로 모두에서 오버플로가 잘린 파일을 쓰는 대신 제대로 처리되며, 압축된 이미지를 다른 압축 확장자로 저장하면 쓰레기 데이터를 쓰는 대신 예외가 발생합니다.
새로운
protocol.poll()및protocol.CBORChannel을 위한 여섯 가지 새 CBOR 위젯(text,lineedit,pushbutton,spinbox,radio,waveform).YOLO Pro 후처리기, FLIR Lepton 3.1R / UW 지원, IMU 버스트 읽기, OpenMV N6의 CAN, 그리고 네트워킹이 가능한 시뮬레이터 타깃.
새로운 기능#
YoloPro— Edge Impulse YOLO Pro 객체 검출 모델을 위한 새로운 후처리기와yolo_pro_detector.py예제. (f3f150ebd, ea7bbb398)protocol.poll()— USB 인터럽트나poll_ms타이머로 구동되지 않는 사용자 정의 전송 방식을 위해, 필요할 때 프로토콜 태스크를 한 번 실행합니다.protocol.init()을 다시 호출해 스택을 재초기화할 수도 있습니다. (c00c215f9, f849ffb1b)더 많은 CBOR 채널 위젯 —
protocol.CBORChannel.add()에text(정적 문자열),lineedit(쓰기 가능한 문자열),pushbutton(순간 동작),spinbox(단계별 숫자 입력),radio(옵션 그룹),waveform(sample_rate,series,typecode인자를 갖는 1D 시계열. 인터리브된 샘플 바이트를 할당하면 스트리밍됨)이 추가되었습니다. (8016d29ba)csi.CUSTOM— 사용자 정의(w, h)해상도가 설정된 후csi.CSI.framesize()가 이름 없는 정수 대신 사용 가능한 상수를 반환합니다. (af8841654)IMU 버스트 읽기 —
imu.__read_reg()가 선택적 쓰기 가능 버퍼를 받아 연속된 레지스터에서 한 번의 트랜잭션으로 채웁니다. (244ca480a)FLIR Lepton 3.1R 및 Lepton UW를 Lepton 드라이버가 인식하며, 이들의 방사 측정 게인 모드도 포함됩니다. (0fc356632)
시뮬레이터 네트워킹 —
MPS2_AN500QEMU 타깃에 이제 lwIP와 사용자 모드 NIC가 있으며,requests,mqtt,sensor가 프로즌으로 포함되고 네트워킹 단위 테스트가 추가되었습니다. (23546dfb1, 61d187305, 15096c3a2)OpenAI 호환 API 예제 —
openai_compatible.py는 JPEG을 스냅샷하여 장면 설명을 위해 chat-completions 엔드포인트로 전송합니다. (79033c6aa)SX126x LoRa 예제 — micropython-lib의
lora-sx126x드라이버(lora-sync/lora-async포함)가 OpenMV RT1062 펌웨어에 프로즌으로 포함되었으며, SX1261 또는 SX1262 모듈을 SPI 버스에 연결하기 위한 송신기/수신기/핑퐁/이미지 스트림 예제가 함께 제공됩니다. 이는 커뮤니티가 기여한 지원이며, OpenMV는 LoRa 하드웨어를 판매하지 않습니다. (19576e1b1)
기타 변경 및 개선 사항#
requests라이브러리 재작성 — 청크 전송 응답이 디코딩되고,timeout인자(기본값 5초)가 노출되며, JSON 및 문자열 본문이 올바르게 직렬화/인코딩되고, 헤더는 대소문자를 구분하지 않고 상태 줄은 위치 기준으로 파싱되며, 호출자의headers딕셔너리가 복사되고(따라서auth가 더 이상 이후 요청으로 새어 나가지 않음), 본문은 블록 단위로bytearray에 읽혀 들어옵니다. (889f0b096)mqtt가ssl을 지연 임포트하므로, SSL을 지원하지 않는 빌드에서도 모듈과 일반(비 TLS) 연결이 동작합니다. (c2e0899e8)JPEG 출력 버퍼 크기를 여유 메모리에 따라 결정 — 고정 1 MB 상한 대신 여유 메모리에 맞춰 크기가 정해지며, 인코더가 이미지를 기록하기 전에 버퍼를 인코딩된 크기로 잘라 내므로 대형 센서의 고품질 캡처가 더 이상 실패하지 않습니다. (aa1ca6776)
ML 후처리 정리 — Darknet, Edge Impulse, Ultralytics 후처리기 전반에서 바운딩 박스 생성이 표준화되었고, YOLOv8 출력은 임계값 적용 후 전치되어 다른 모델과 마찬가지로 검출당 한 행으로 저장됩니다. (b5c7853f2, c45f99cad)
PAG7936 안전 종료 — 새로운 센서 정지(halt) 플래그가 RESET/PWDN 토글 전에 PAG7936을 절전 상태로 전환하여, 센서를 연장 케이블로 사용할 때 발생하던 멈춤 현상을 수정합니다. 또한 드라이버는 MIPI CSI-2 또는 병렬 레지스터 세트를 빌드 시점이 아니라 런타임에 센서의 I2C 주소로부터 선택합니다. (10026530c, f6acf14ec, 5f0251c74)
ImageIO재생 페이싱이 이제 프레임 간 간격을 기다리는 동안WFI로 잠드는 대신 대기 중인 이벤트를 처리합니다. (a54790193)MicroPython 서브모듈 업데이트 — QEMU 포트의 완전한 네트워킹 지원, 백업 SRAM/BKP 레지스터를 통한 STM32의
machine.mem_backup, STM32F4에서 SDIO 하드웨어 흐름 제어 비활성 유지, 비캐시 영역에 대한 MPU 속성 재사용. (31ada5626, ab61d27a6, 06bddf13a)differential-translation.py가 사용 중단된sensor모듈 대신 자신의csi.CSI객체를 통해 캡처하며, 예제의 import 간격이 정규화되었습니다. (68c866e7f, 9ceff4513)
버그 수정#
카메라 및 센서:
사용자 정의
(w, h)해상도를 연달아 두 번 설정하면 센서는 첫 번째 크기에 머무는데csi.CSI.width()/height()는 두 번째 크기를 보고했습니다. 이제 “변경 없음” 빠른 경로에서 사용자 정의 크기는 제외됩니다. (cfbb70156)csi.CSI.lens_correction()이radi와coef를 불리언으로 파싱하여, 드라이버에 전달되는 값이 지정한 값과 달랐습니다. (ab44b3a77)PAG7936: 노출과 게인을 연달아 설정하면 서로를 덮어썼습니다(둘은 하나의 수동 모드를 공유하고 읽기 레지스터가 한 프레임 지연됨). 이제 드라이버는 수동 모드에 진입할 때만 수동 레지스터를 초기화하고, 설정 중인 컨트롤만 기록합니다. (e7a18c0a0)
OpenMV N6에서 PAG7936 및 PS5520 BAYER 캡처가 전체 해상도가 아닌 크기에서는 “Failed to initialize the CSI interface” 오류로 실패했습니다. N6 ISP가 원시 Bayer를 리스케일할 수 없기 때문입니다. 이제 BAYER의 경우 센서가 요청된 크기에 맞는 네이티브 모드로 동작합니다(PS5520: VGA, HD, SXGA-M, FHD, QHD, WQXGA2. QVGA는 네이티브 모드가 없어 지원되지 않음). (fe6790055, b7622b245)
이미지 인코딩 및 저장:
소프트웨어 JPEG 인코더: realloc 경로가 비활성화되어 있어 출력 버퍼 오버플로가 항상 치명적이었습니다. 이제 버퍼를 소유한 경우 버퍼를 (한 번에 절반 크기씩) 늘리고, 메모리가 부족하면 깔끔하게 되돌리며, 결과를 잘라 냅니다.
jpeg_write/mjpeg_write는 인코딩 실패 후 더 이상 버퍼를 기록하지 않습니다. (28e1110be)하드웨어 JPEG 인코더(STM32): 오버플로 시 할당 크기와 함께 부분적으로 인코딩된 이미지를 반환하여, EOI 마커가 없는 잘린 파일이 만들어졌습니다(예: 품질 100의 5 MP 캡처에서 아래쪽 절반이 비어 있음). 이제 오버플로를 보고하고, 실패 시 버퍼를 해제하며, 성공 시 버퍼를 잘라 냅니다. (22ce9619c)
VC8000 인코더가 모든 요청에 대해 조용히 4:2:0 크로마를 생성했습니다. 이제 4:2:0이 아닌 서브샘플링은 이를 지원하는 HW 코덱으로 대체됩니다. (71f2be7f2)
PNG 이미지를
.jpg로image.Image.save()하면 최대 1 MB의 초기화되지 않은 힙이 기록되었고, JPEG 이미지를.png로 저장하면 빈 파일이 기록되었습니다. 이제 둘 다 예외를 발생시키며, 이미 대상 형식인 이미지는 여전히 그대로 복사됩니다. (6c1fdf822)png_write가 이제 압축기의 반환값을 확인하고 파일을 만들기 전에 압축하므로, 실패해도 더 이상 빈 파일이 남지 않습니다. (557f52d66)
Image 모듈:
BAYER 및 YUV 이미지에서
rgbtuple=True로image.Image.get_pixel()을 호출하면 변환된 픽셀이 호출자가 제어하는 오프셋으로 스택 지역 변수 너머에 기록되었습니다. (13f2a17b6)gif.Gif.add_frame()에서 도달 불가능한 Bayer/YUV 변환 분기를 제거했습니다. Python API가 이미 강제하던 대로 GRAYSCALE 및 RGB565 이미지만 허용됩니다. (f20d99d96)
프로토콜:
모든 슬롯이 이미 사용 중인 상태에서 동적 채널을 등록하면 범위를 벗어난 쓰기가 발생했습니다. 이제 채널 ID를 먼저 검사하며, 예약된 채널 ID가 채널 테이블에 들어맞는지 정적으로 단언합니다. (68f635d1f)
동적 채널 객체가 루트 포인터에 남아 소프트 리셋 후에도 살아남았고, 그 결과 GC가 이전 실행의 오래된 힙 블록을 계속 스캔했습니다. 이제 초기화 시 테이블이 비워집니다. (ef0ebb03b, e23641145)
포트:
i.MX RT: 소프트 리셋 시 누락되어 있던 CAN 및 Encoder 해제(de-initialization)를 추가했습니다. (7cb9d3dc2)
하드웨어 및 보드 지원#
OpenMV N6 — 이제 CAN이 활성화되었습니다(
machine.CAN). (294f0febd, 91e1c9573)OpenMV AE3 — AE3 배터리 실드의 microSD 소켓을 위해
sdcardSPI 드라이버가 프로즌으로 포함되었습니다. (a258f4814)OpenMV RT1062 —
lora-sx126x/lora-sync/lora-async가 프로즌으로 포함되었습니다(새로운 기능 참고).FLIR Lepton 3.1R / UW — Lepton을 지원하는 모든 보드에서 Lepton 드라이버가 인식합니다.
PAG7936 — 안전 종료 정지, 런타임 인터페이스 선택, 노출/게인 수정, N6에서의 BAYER 캡처.
PS5520 — N6에서 네이티브 크기의 BAYER 캡처.
시뮬레이터(MPS2_AN500) — 네트워킹.
모든 보드 —
sensor호환 모듈이 모든 보드의 매니페스트에 프로즌으로 포함되었습니다.
호환성을 깨는 API 변경#
v5.0.1은 csi 또는 image API에 호환성을 깨는 변경을 도입하지 않습니다. v5.0.0에서 실행되던 스크립트는 다음 동작 변경만 제외하면 수정 없이 실행됩니다.
sensor 모듈 (behavior)#
네이티브 sensor 모듈(modules/py_csi.c)이 제거되고, csi 위에 동일한 API를 구현하는 프로즌 Python 모듈로 대체되었습니다. sensor를 참고하세요.
커밋: 5e3d40631
import sensor는 터미널에WARNING: The sensor module is deprecated and will be removed in a future release. Please use the csi module instead.를 출력합니다.숨겨진
csi.CSI객체가 임포트 시 생성되므로, 카메라가 없으면 이제sensor.reset()이 아니라import sensor에서 오류가 발생합니다.다음 함수들은
csi에 대응하는 기능이 없으므로 이제OSError를 발생시킵니다:get_fb(),alloc_extra_fb(),dealloc_extra_fb(),set_auto_rotation(),get_auto_rotation(),disable_delays(),disable_full_flush(). (두*_extra_fb함수는 v5.0.0에서 이미 예외를 발생시켰습니다.) 마지막 두 함수 대신csi.CSI(delays=False)/csi.CSI(fflush=False)를 사용하세요.csi가 내보내지 않는 프레임 크기(QQCIF,QQSIF,QQQQVGA,HQQQQVGA,HQQQVGA,HQQVGA,B64X32,B64X64,B128X64,B128X128,B160X160,B320X320,LCD,QQVGA2)는 이제 사용자 정의 해상도로 전달되는(w, h)튜플입니다.get_framesize()는 카메라가 아직 그 크기에 있는 동안 설정된 튜플을 반환하므로, 상수와의 동등 비교가 계속 동작합니다.ioctl()은 요청 뒤의 인자를 최대 네 개까지만 전달합니다.sleep()/shutdown()은 이전과 마찬가지로 실패 시OSError를 발생시킵니다(csi의RuntimeError가 변환됨).
csi로 마이그레이션하세요 — v5.0.0 마이그레이션 표를 참고하세요.
프레임 버퍼 이미지 로딩 (behavior)#
프레임 버퍼에 이미지를 불러오는 함수들 — copy_to_fb=True를 지정한 image.Image, copy_to_fb=True를 지정한 image.Image.copy() / image.Image.scale() 및 to_* 변환, image.ImageIO.read(), copy_to_fb=True를 지정한 fir.snapshot() 및 tof.snapshot() — 는 예전에는 새 이미지를 IDE 미리보기로 즉시 전송했기 때문에 반환된 이미지에 그린 내용을 전혀 볼 수 없었습니다. 이제 이들은 프레임 버퍼를 대기 중으로 표시하고, 다음 이미지가 덮어쓰기 직전에 그 위에 그린 모든 내용과 함께 플러시합니다 — csi.CSI.snapshot()과 같은 동작입니다.
커밋: 87b6db5ee, 7b1a35c2f, f773c740d
이미지 스트림을 읽는 루프는 수정할 필요가 없으며 이제 그린 내용이 표시됩니다. 단일 이미지를 불러오고 멈추는 스크립트는 명시적으로 플러시해야 합니다:
img = image.Image("example.bmp", copy_to_fb=True)
img.flush() # new: send it to the IDE preview now
time.sleep_ms(1000)
ML 라이브러리 (behavior)#
제공되는 후처리기를 서브클래싱하거나 복사한 코드에만 영향을 줍니다. YoloV8은 이제 임계값 적용 후 모델 출력을 전치하므로, 살아남은 검출이 Darknet 및 Edge Impulse 후처리기와 마찬가지로 박스당 한 열(bb[4:, :])이 아니라 박스당 한 행(bb[:, 4:])으로 저장됩니다. 공개 ((x, y, w, h), score) 결과는 변경되지 않았습니다.
protocol 모듈 (minor)#
protocol.poll()이 돌아왔습니다. v5.0.0에서 프로토콜 태스크가 타이머로 옮겨가면서 제거되었으나, 사용자 정의 전송 방식에서 태스크를 명시적으로 구동하는 수단으로 다시 추가되었습니다. 그 외에는 변경된 것이 없으며, 이 함수를 호출한 적이 없는 스크립트는 영향을 받지 않습니다.
커밋: c00c215f9
빌드 / 툴링 (tooling)#
이 중 어느 것도 MicroPython 스크립트에는 영향을 주지 않습니다. py_image.c가 분할되어, 디스크립터 객체(cascade, keypoints, LBP, keypoint match)는 py_image_descriptor.c로, 통계 객체(similarity, statistics, percentile, threshold, histogram)는 py_image_stats.c로 옮겨졌습니다. imlib 인코더 API가 imlib의 나머지 부분과 일관되게 정리되었습니다: jpeg_compress / png_compress는 성공 시 0, 오류 시 -1을 반환하며, jpeg_compress의 realloc 인자는 사라졌습니다(크기 조정은 버퍼 소유 여부에 따라 결정됨). omv_protocol_channel.h에서 OMV_PROTOCOL_MAX_CHANNELS가 OMV_PROTOCOL_CHANNEL_MAX로 바뀌었고, 포트는 이제 초기화 시 py_protocol_init0()을 호출합니다. OMV_PAG7936_MIPI_CSI2 보드 정의는 사라졌습니다(인터페이스는 런타임에 선택됨). CI 의존성 업데이트와 빈 릴리스 체인지로그 수정으로 마무리됩니다. 포크와 관련된 세부 사항은 펌웨어 저장소 이력을 참고하세요.
마이그레이션 체크리스트#
아직
import sensor를 사용 중인가요? 경고와 함께 동작합니다.csi로 옮기고(v5.0.0 마이그레이션),disable_delays/disable_full_flush를csi.CSI()생성자 인자로 교체하고,get_fb/ 자동 회전 호출은 제거하세요.copy_to_fb=True로 단일 이미지를 불러오고 그것이 보이길 기대하나요? 불러온 후img.flush()를 추가하세요.YOLOv8 후처리기를 복사했나요? 임계값 적용된 출력을 열이 아니라 행(
bb[:, 4:])으로 인덱싱하세요.튜플을 설정한 후
csi0.framesize()를 비교하나요? 이제csi.CUSTOM을 반환합니다.그 외 모든 것: 다시 플래시하고 실행하세요.