v5.0.1#

v5.0.1 是建立在 v5.0.0 之上的維護版本——舊有的 sensor 模組變成建立在 csi 之上的 Python 相容層、載入影格緩衝區的影像現在會像相機影格一樣預覽、JPEG 編碼器不再有 1 MB 的輸出限制並能正確處理溢位,此外還有一批相機、協定、網路與 ML 函式庫的修正。對於針對 csi 撰寫的指令碼,本版本未引入任何破壞性 API 變更;少數行為變更列於 破壞性 API 變更 之下。

重點亮點#

  • 舊有的 sensor 模組現在是一個凍結的 Python 模組,建立於 csi 之上。匯入時會印出棄用警告;少數 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,以及一個 具備網路功能的 simulator 目標。

新功能#

  • 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(1D 時間序列,具有 sample_rate、series 與 typecode 引數;指派交錯的樣本位元組即可串流)。(8016d29ba)

  • csi.CUSTOM —— 在設定自訂 (w, h) 解析度之後,csi.CSI.framesize() 現在會回傳一個可用的常數,而非匿名整數。(af8841654)

  • IMU 連續讀取 —— imu.__read_reg() 接受一個選用的可寫入緩衝區,並在單一交易中以連續暫存器的內容填滿它。(244ca480a)

  • FLIR Lepton 3.1R 與 Lepton UW 現在能被 Lepton 驅動程式辨識,包括其輻射測溫增益模式。(0fc356632)

  • Simulator 網路功能 —— MPS2_AN500 QEMU 目標現在具備 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,因此本模組與純(非 TLS)連線在不支援 SSL 的建置上也能運作。(c2e0899e8)

  • JPEG 輸出緩衝區大小依可用記憶體決定,而非固定的 1 MB 上限;編碼器會在影像寫出之前將緩衝區修剪為編碼後的大小,因此大型感測器的高品質擷取不再失敗。(aa1ca6776)

  • ML 後處理整理 —— 邊界框的產生方式在 Darknet、Edge Impulse 與 Ultralytics 後處理器之間已標準化,且 YOLOv8 的輸出會在閾值篩選後轉置,使其如同其他模型一樣以每個偵測一列的方式儲存。(b5c7853f2、c45f99cad)

  • PAG7936 安全關機 —— 新的感測器停止旗標會在切換 RESET/PWDN 之前讓 PAG7936 進入睡眠,修正了感測器透過延長排線使用時的當機問題。驅動程式現在也會在執行階段依感測器的 I2C 位址選擇其 MIPI CSI-2 或平行介面暫存器組,而非在建置時決定。(10026530c、f6acf14ec、5f0251c74)

  • ImageIO 的播放節奏控制現在會在等待影格間隔時處理待處理的事件,而非在 WFI 中休眠。(a54790193)

  • MicroPython 子模組更新 —— QEMU 移植版的完整網路支援、STM32 上透過備援 SRAM/BKP 暫存器實作的 machine.mem_backup、STM32F4 上維持停用的 SDIO 硬體流量控制,以及不可快取區域的 MPU 屬性重用。(31ada5626、ab61d27a6、06bddf13a)

  • differential-translation.py 現在透過其 csi.CSI 物件擷取影像,而非使用已棄用的 sensor 模組;範例中的 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 的子取樣現在會回退到支援它的硬體編解碼器。(71f2be7f2)

  • 以 image.Image.save() 將 PNG 影像存成 .jpg 會寫出最多 1 MB 未初始化的堆積內容,而將 JPEG 影像存成 .png 則會寫出空檔案。兩者現在都會引發例外;已是目標格式的影像仍會原樣複製。(6c1fdf822)

  • png_write 現在會檢查壓縮器的回傳值,並在建立檔案之前先進行壓縮,因此失敗時不再留下空檔案。(557f52d66)

影像模組:

  • 在 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 解除初始化。(7cb9d3dc2)

硬體與板卡支援#

  • OpenMV N6 —— 現已啟用 CAN(machine.CAN)。(294f0febd、91e1c9573)

  • OpenMV AE3 —— 為 AE3 電池擴充板 上的 microSD 插槽凍結了 sdcard SPI 驅動程式。(a258f4814)

  • OpenMV RT1062 —— 已凍結 lora-sx126x / lora-sync / lora-async(請參閱「新功能」)。

  • FLIR Lepton 3.1R / UW —— 在所有支援 Lepton 的板卡上都能被 Lepton 驅動程式辨識。

  • PAG7936 —— 安全關機停止、執行階段介面選擇、曝光/增益修正,以及 N6 上的 BAYER 擷取。

  • PS5520 —— N6 上以原生大小進行 BAYER 擷取。

  • Simulator (MPS2_AN500) —— 網路功能。

  • 所有板卡 —— sensor 相容模組已凍結進每塊板卡的 manifest 中。

破壞性 API 變更#

v5.0.1 未對 csi 或 image API 引入任何破壞性變更。在 v5.0.0 上能執行的指令碼無需修改即可執行,僅有下列行為變更。

sensor 模組 (behavior)#

原生的 sensor 模組(modules/py_csi.c)已移除,改由一個凍結的 Python 模組取代,該模組在 csi 之上實作相同的 API。請參閱 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 物件會在匯入時建立,因此缺少相機時現在會在 import sensor 時就引發錯誤,而非在 sensor.reset() 時。

  • 由於 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 現在會在閾值篩選後轉置模型輸出,使保留下來的偵測以每個框一 列 的方式儲存(bb[:, 4:]),與 Darknet 及 Edge Impulse 後處理器一致,而非每個框一欄(bb[4:, :])。公開的 ((x, y, w, h), score) 結果不變。

提交: c45f99cad、b5c7853f2

protocol 模組 (minor)#

protocol.poll() 回歸了。v5.0.0 在協定任務移至計時器時將其移除;它現在以明確方式回歸,供自訂傳輸驅動該任務。其他一切不變——從未呼叫過它的指令碼不受影響。

提交: c00c215f9

建置/工具鏈 (tooling)#

這些都不影響 MicroPython 指令碼。py_image.c 已被拆分:描述元物件(級聯、關鍵點、LBP、關鍵點比對)移至 py_image_descriptor.c,統計物件(相似度、統計、百分位數、閾值、直方圖)移至 py_image_stats.c。imlib 編碼器 API 已與 imlib 的其餘部分對齊:jpeg_compress / png_compress 成功時回傳 0、錯誤時回傳 -1,且 jpeg_compress 移除了其 realloc 引數(是否重新調整大小取決於緩衝區的擁有權)。OMV_PROTOCOL_MAX_CHANNELS 更名為 OMV_PROTOCOL_CHANNEL_MAX(位於 omv_protocol_channel.h),且各移植版現在會在初始化時呼叫 py_protocol_init0()。OMV_PAG7936_MIPI_CSI2 板卡定義已移除(介面在執行階段選擇)。此外還有 CI 相依套件的版本更新,以及空白版本變更記錄的修正。與分支相關的細節請參閱 韌體儲存庫 的歷史。

遷移檢查清單#

  • 仍在使用 import sensor 嗎?它仍可運作,但會出現警告。請移至 csi(v5.0.0 遷移);以 csi.CSI() 建構式引數取代 disable_delays / disable_full_flush,並移除 get_fb / 自動旋轉的呼叫。

  • 以 copy_to_fb=True 載入單一影像並期望看到它? 請在載入後加上 img.flush()。

  • 複製了 YOLOv8 後處理器? 請以列(bb[:, 4:])而非欄來索引閾值篩選後的輸出。

  • 在設定元組之後比較 csi0.framesize() 的結果? 它現在會回傳 csi.CUSTOM。

  • 其他一切:重新燒錄韌體並執行即可。