v5.0.1#

v5.0.1 là bản phát hành bảo trì trên nền v5.0.0 — module sensor cũ trở thành một lớp tương thích Python trên nền csi, các ảnh được nạp vào bộ đệm khung hình giờ đây xem trước giống như khung hình camera, các bộ mã hóa JPEG bỏ giới hạn đầu ra 1 MB và xử lý tràn bộ đệm đúng cách, cùng một loạt sửa lỗi cho camera, giao thức, mạng và thư viện ML. Bản này không có thay đổi API không tương thích ngược đối với các tập lệnh viết cho csi; một vài thay đổi hành vi được liệt kê trong thay đổi API không tương thích ngược.

Điểm nổi bật#

  • Module sensor giờ là một module Python đóng băng xây dựng trên csi. Nó in cảnh báo ngừng hỗ trợ khi import; một vài hàm mà module csi không thể hỗ trợ giờ ném ra OSError. Xem các thay đổi module sensor.

  • Ảnh được nạp xem trước giống như khung hình camera. Một ảnh được đặt vào bộ đệm khung hình với copy_to_fb=True (image.Image, image.ImageIO.read(), fir.snapshot(), tof.snapshot()) được flush tới IDE — cùng với bất cứ thứ gì đã vẽ lên nó — khi ảnh tiếp theo ghi đè lên bộ đệm khung hình, thay vì ngay lập tức. Xem các thay đổi xem trước.

  • Đại tu bộ mã hóa JPEG. Giới hạn 1 MB của bộ đệm đầu ra đã được bỏ (bộ đệm được định cỡ theo bộ nhớ trống), tràn bộ đệm trên cả đường phần mềm lẫn phần cứng đều được xử lý thay vì ghi ra tệp bị cắt cụt, và việc lưu một ảnh đã nén dưới phần mở rộng nén còn lại sẽ ném ra lỗi thay vì ghi dữ liệu rác.

  • Hàm mới protocol.poll() và sáu widget CBOR mới (text, lineedit, pushbutton, spinbox, radio, waveform) cho protocol.CBORChannel.

  • Bộ xử lý hậu kỳ YOLO Pro, hỗ trợ FLIR Lepton 3.1R / UW, đọc theo khối IMU, CAN trên OpenMV N6, và mục tiêu simulator có khả năng kết nối mạng.

Tính năng mới#

  • YoloPro — bộ xử lý hậu kỳ mới cho các mô hình phát hiện đối tượng YOLO Pro của Edge Impulse, cùng với ví dụ yolo_pro_detector.py. (f3f150ebd, ea7bbb398)

  • protocol.poll() — chạy một vòng lặp của tác vụ giao thức theo yêu cầu, dành cho các transport tùy chỉnh không được điều khiển bởi ngắt USB hay bộ hẹn giờ poll_ms. protocol.init() cũng có thể được gọi lại để khởi tạo lại ngăn xếp. (c00c215f9, f849ffb1b)

  • Thêm widget cho kênh CBOR — protocol.CBORChannel.add() có thêm text (chuỗi tĩnh), lineedit (chuỗi có thể ghi), pushbutton (hành động tức thời), spinbox (nhập số theo bước), radio (nhóm tùy chọn) và waveform (chuỗi thời gian 1D với các đối số sample_rate, series và typecode; gán các byte mẫu xen kẽ để truyền luồng). (8016d29ba)

  • csi.CUSTOM — csi.CSI.framesize() giờ trả về một hằng số dùng được sau khi một độ phân giải (w, h) tùy chỉnh đã được đặt, thay vì một số nguyên vô danh. (af8841654)

  • Đọc theo khối IMU — imu.__read_reg() chấp nhận một bộ đệm ghi được tùy chọn và điền vào đó từ các thanh ghi liên tiếp trong một giao dịch. (244ca480a)

  • FLIR Lepton 3.1R và Lepton UW được trình điều khiển Lepton nhận diện, bao gồm cả các chế độ gain đo bức xạ của chúng. (0fc356632)

  • Kết nối mạng cho simulator — mục tiêu QEMU MPS2_AN500 giờ có lwIP và NIC chế độ người dùng, với requests, mqtt và sensor được đóng băng kèm theo, cùng một bài kiểm thử đơn vị về mạng. (23546dfb1, 61d187305, 15096c3a2)

  • Ví dụ API tương thích OpenAI — openai_compatible.py chụp một ảnh JPEG và gửi nó tới một endpoint chat-completions để mô tả cảnh. (79033c6aa)

  • Ví dụ LoRa SX126x — trình điều khiển lora-sx126x của micropython-lib (cùng lora-sync / lora-async) được đóng băng vào firmware OpenMV RT1062, kèm các ví dụ gửi/nhận/ping-pong/truyền luồng ảnh để nối một module SX1261 hoặc SX1262 vào bus SPI. Đây là hỗ trợ do cộng đồng đóng góp; OpenMV không bán phần cứng LoRa. (19576e1b1)

Các thay đổi và cải tiến khác#

  • Viết lại thư viện requests — các phản hồi truyền tải chunked được giải mã, đối số timeout (mặc định 5 giây) được cung cấp, nội dung JSON và chuỗi được tuần tự hóa/mã hóa đúng cách, các header được phân tích không phân biệt chữ hoa chữ thường và dòng trạng thái được phân tích theo vị trí, dict headers của bên gọi được sao chép (nên auth không còn rò rỉ sang các yêu cầu sau), và nội dung được đọc theo từng khối vào một bytearray. (889f0b096)

  • mqtt import ssl theo kiểu lazy, nên module này và các kết nối thường (không TLS) hoạt động trên các bản build không hỗ trợ SSL. (c2e0899e8)

  • Bộ đệm đầu ra JPEG được định cỡ theo bộ nhớ trống thay vì giới hạn cố định 1 MB; các bộ mã hóa cắt bộ đệm về đúng kích thước đã mã hóa trước khi ảnh được ghi ra, nên các ảnh chụp từ cảm biến lớn ở chất lượng cao không còn thất bại. (aa1ca6776)

  • Dọn dẹp xử lý hậu kỳ ML — việc tạo hộp giới hạn được chuẩn hóa trên các bộ xử lý hậu kỳ Darknet, Edge Impulse và Ultralytics, và đầu ra YOLOv8 được chuyển vị sau bước ngưỡng để được lưu mỗi hàng một phát hiện giống như các mô hình khác. (b5c7853f2, c45f99cad)

  • Tắt an toàn PAG7936 — một cờ dừng cảm biến mới đưa PAG7936 vào chế độ ngủ trước khi chuyển đổi RESET/PWDN, khắc phục hiện tượng treo khi cảm biến được dùng qua cáp nối dài. Trình điều khiển cũng chọn bộ thanh ghi MIPI CSI-2 hoặc song song dựa trên địa chỉ I2C của cảm biến lúc chạy thay vì lúc build. (10026530c, f6acf14ec, 5f0251c74)

  • Việc điều tiết tốc độ phát lại của ImageIO giờ xử lý các sự kiện đang chờ trong khi đợi khoảng thời gian giữa các khung hình thay vì ngủ trong WFI. (a54790193)

  • Cập nhật submodule MicroPython — hỗ trợ mạng đầy đủ trên port QEMU, machine.mem_backup trên STM32 thông qua backup SRAM/thanh ghi BKP, giữ tắt điều khiển luồng phần cứng SDIO trên STM32F4, và tái sử dụng thuộc tính MPU cho các vùng không cache. (31ada5626, ab61d27a6, 06bddf13a)

  • differential-translation.py chụp ảnh thông qua đối tượng csi.CSI của nó thay vì module sensor đã ngừng hỗ trợ, và khoảng cách giữa các dòng import trong ví dụ được chuẩn hóa. (68c866e7f, 9ceff4513)

Sửa lỗi#

Camera và cảm biến:

  • Đặt hai độ phân giải (w, h) tùy chỉnh liên tiếp khiến cảm biến vẫn ở kích thước đầu tiên trong khi csi.CSI.width() / height() báo kích thước thứ hai; đường tắt "không thay đổi" giờ loại trừ các kích thước tùy chỉnh. (cfbb70156)

  • csi.CSI.lens_correction() phân tích radi và coef như các giá trị boolean, nên các giá trị truyền tới trình điều khiển không phải là giá trị đã cho. (ab44b3a77)

  • PAG7936: đặt phơi sáng và gain liên tiếp nhau khiến chúng ghi đè lẫn nhau (cả hai dùng chung một chế độ thủ công và các thanh ghi đọc lại trễ một khung hình); trình điều khiển giờ chỉ khởi tạo các thanh ghi thủ công khi vào chế độ thủ công và chỉ ghi đúng điều khiển đang được đặt. (e7a18c0a0)

  • Chụp BAYER với PAG7936 và PS5520 trên OpenMV N6 thất bại với lỗi "Failed to initialize the CSI interface" ở mọi kích thước khác độ phân giải đầy đủ, vì ISP của N6 không thể thay đổi tỷ lệ Bayer thô. Các cảm biến giờ chạy ở chế độ gốc khớp với kích thước được yêu cầu cho BAYER (PS5520: VGA, HD, SXGA-M, FHD, QHD, WQXGA2; QVGA không có chế độ gốc và không được hỗ trợ). (fe6790055, b7622b245)

Mã hóa và lưu ảnh:

  • Bộ mã hóa JPEG phần mềm: tràn bộ đệm đầu ra luôn gây lỗi nghiêm trọng vì đường realloc bị vô hiệu hóa; giờ nó mở rộng bộ đệm (mỗi lần thêm một nửa kích thước) khi nó sở hữu bộ đệm, lùi về một cách sạch sẽ khi hết bộ nhớ, và cắt gọn kết quả. jpeg_write / mjpeg_write không còn ghi bộ đệm ra sau một lần mã hóa thất bại. (28e1110be)

  • Bộ mã hóa JPEG phần cứng (STM32): khi tràn, nó trả về ảnh được mã hóa dở dang với kích thước cấp phát, tạo ra các tệp bị cắt cụt không có dấu EOI (ví dụ ảnh chụp 5 MP ở chất lượng 100 với nửa dưới trống). Giờ chúng báo tràn, giải phóng bộ đệm khi thất bại, và cắt gọn bộ đệm khi thành công. (22ce9619c)

  • Bộ mã hóa VC8000 âm thầm tạo ra chroma 4:2:0 cho mọi yêu cầu; lấy mẫu con khác 4:2:0 giờ lùi về codec phần cứng hỗ trợ nó. (71f2be7f2)

  • image.Image.save() với ảnh PNG lưu dưới dạng .jpg ghi ra tới 1 MB heap chưa khởi tạo, và với ảnh JPEG lưu dưới dạng .png ghi ra tệp rỗng. Cả hai giờ đều ném ra lỗi; ảnh đã ở đúng định dạng đích vẫn được sao chép nguyên trạng. (6c1fdf822)

  • png_write giờ kiểm tra giá trị trả về của bộ nén và nén trước khi tạo tệp, nên một lần thất bại không còn để lại tệp rỗng. (557f52d66)

Module image:

  • image.Image.get_pixel() với rgbtuple=True trên ảnh BAYER và YUV ghi điểm ảnh đã chuyển đổi ra ngoài một biến cục bộ trên stack tại một độ lệch do bên gọi kiểm soát. (13f2a17b6)

  • gif.Gif.add_frame() bỏ một nhánh chuyển đổi Bayer/YUV không bao giờ đạt tới; chỉ chấp nhận ảnh GRAYSCALE và RGB565, như API Python vốn đã bắt buộc. (f20d99d96)

Giao thức:

  • Đăng ký một kênh động khi mọi khe đã được sử dụng gây ra ghi ngoài phạm vi; ID kênh giờ được kiểm tra trước, và các ID kênh dành riêng được kiểm tra tĩnh để đảm bảo vừa với bảng kênh. (68f635d1f)

  • Các đối tượng kênh động vẫn tồn tại trong các root pointer sau soft reset, nên GC tiếp tục quét các khối heap cũ từ lần chạy trước; bảng này giờ được xóa khi khởi tạo. (ef0ebb03b, e23641145)

Các port:

  • i.MX RT: bổ sung phần hủy khởi tạo CAN và Encoder còn thiếu khi soft reset. (7cb9d3dc2)

Phần cứng và hỗ trợ bo mạch#

  • OpenMV N6 — CAN giờ đã được bật (machine.CAN). (294f0febd, 91e1c9573)

  • OpenMV AE3 — trình điều khiển SPI sdcard được đóng băng kèm theo cho khe microSD trên AE3 Battery Shield. (a258f4814)

  • OpenMV RT1062 — lora-sx126x / lora-sync / lora-async được đóng băng kèm theo (xem Tính năng mới).

  • FLIR Lepton 3.1R / UW — được trình điều khiển Lepton nhận diện trên mọi bo mạch hỗ trợ Lepton.

  • PAG7936 — dừng tắt an toàn, chọn giao diện lúc chạy, sửa lỗi phơi sáng/gain, và chụp BAYER trên N6.

  • PS5520 — chụp BAYER trên N6 ở các kích thước gốc.

  • Simulator (MPS2_AN500) — kết nối mạng.

  • Tất cả các bo mạch — module tương thích sensor được đóng băng vào manifest của mọi bo mạch.

Thay đổi API không tương thích ngược#

v5.0.1 không đưa ra thay đổi không tương thích ngược nào cho API csi hoặc image. Các tập lệnh đã chạy trên v5.0.0 vẫn chạy không cần sửa đổi, với các thay đổi hành vi sau đây.

Module sensor (behavior)#

Module sensor gốc (modules/py_csi.c) đã bị gỡ bỏ và thay bằng một module Python đóng băng triển khai cùng API trên nền csi. Xem sensor.

Commit: 5e3d40631

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

  • Đối tượng csi.CSI ẩn được tạo khi import, nên việc thiếu camera giờ ném ra lỗi tại import sensor thay vì tại sensor.reset().

  • Các hàm sau giờ ném ra OSError vì csi không có hàm tương đương: get_fb(), alloc_extra_fb(), dealloc_extra_fb(), set_auto_rotation(), get_auto_rotation(), disable_delays(), disable_full_flush(). (Hai hàm *_extra_fb vốn đã ném ra lỗi từ v5.0.0.) Dùng csi.CSI(delays=False) / csi.CSI(fflush=False) cho hai hàm cuối.

  • Các framesize mà csi không xuất ra (QQCIF, QQSIF, QQQQVGA, HQQQQVGA, HQQQVGA, HQQVGA, B64X32, B64X64, B128X64, B128X128, B160X160, B320X320, LCD, QQVGA2) giờ là các tuple (w, h) được truyền qua dưới dạng độ phân giải tùy chỉnh. get_framesize() trả về tuple đã được đặt khi camera vẫn ở kích thước đó, nên các phép so sánh bằng với các hằng số vẫn hoạt động.

  • ioctl() chuyển tiếp tối đa bốn đối số sau yêu cầu.

  • sleep() / shutdown() ném ra OSError khi thất bại như trước (RuntimeError của csi được chuyển đổi).

Hãy di chuyển sang csi — xem bảng di chuyển v5.0.0.

Nạp ảnh vào bộ đệm khung hình (behavior)#

Các hàm nạp ảnh vào bộ đệm khung hình — image.Image với copy_to_fb=True, image.Image.copy() / image.Image.scale() và các phép chuyển đổi to_* với copy_to_fb=True, image.ImageIO.read(), fir.snapshot() và tof.snapshot() với copy_to_fb=True — trước đây đẩy ảnh mới tới bản xem trước của IDE ngay lập tức, nên bất cứ thứ gì vẽ lên ảnh trả về đều không bao giờ được nhìn thấy. Giờ chúng đánh dấu bộ đệm khung hình là đang chờ và flush nó, cùng mọi thứ đã vẽ lên, ngay trước khi ảnh tiếp theo ghi đè lên — cùng hành vi như csi.CSI.snapshot().

Commits: 87b6db5ee, 7b1a35c2f, f773c740d

Các vòng lặp đọc một luồng ảnh không cần thay đổi gì và giờ hiển thị được hình vẽ của chúng. Một tập lệnh nạp một ảnh duy nhất rồi dừng lại phải flush nó một cách tường minh:

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

Thư viện ML (behavior)#

Chỉ ảnh hưởng tới mã kế thừa hoặc sao chép các bộ xử lý hậu kỳ đi kèm. YoloV8 giờ chuyển vị đầu ra của mô hình sau bước ngưỡng để các phát hiện còn lại được lưu mỗi hàng một hộp (bb[:, 4:]), khớp với các bộ xử lý hậu kỳ Darknet và Edge Impulse, thay vì mỗi cột một hộp (bb[4:, :]). Kết quả công khai ((x, y, w, h), score) không thay đổi.

Commits: c45f99cad, b5c7853f2

Module protocol (minor)#

protocol.poll() đã trở lại. v5.0.0 đã gỡ bỏ nó khi tác vụ giao thức chuyển sang bộ hẹn giờ; nó quay lại như một cách tường minh để điều khiển tác vụ cho các transport tùy chỉnh. Không có gì khác thay đổi — các tập lệnh chưa từng gọi nó không bị ảnh hưởng.

Commit: c00c215f9

Build / tooling (tooling)#

Điều này không ảnh hưởng đến các tập lệnh MicroPython. py_image.c đã được tách ra, với các đối tượng mô tả (cascade, keypoints, LBP, keypoint match) chuyển sang py_image_descriptor.c và các đối tượng thống kê (similarity, statistics, percentile, threshold, histogram) sang py_image_stats.c. API bộ mã hóa imlib được đồng bộ với phần còn lại của imlib: jpeg_compress / png_compress trả về 0 khi thành công và -1 khi lỗi, và jpeg_compress bỏ đối số realloc (việc thay đổi kích thước phụ thuộc vào quyền sở hữu bộ đệm). OMV_PROTOCOL_MAX_CHANNELS trở thành OMV_PROTOCOL_CHANNEL_MAX trong omv_protocol_channel.h, và các port giờ gọi py_protocol_init0() khi khởi tạo. Define bo mạch OMV_PAG7936_MIPI_CSI2 đã bị bỏ (giao diện được chọn lúc chạy). Các cập nhật phụ thuộc CI và một bản sửa lỗi changelog phát hành rỗng hoàn tất phần này. Xem lịch sử firmware repository để biết chi tiết liên quan đến các fork.

Danh sách kiểm tra di chuyển#

  • Vẫn đang dùng import sensor? Nó vẫn hoạt động, kèm một cảnh báo. Hãy chuyển sang csi (hướng dẫn di chuyển v5.0.0); thay disable_delays / disable_full_flush bằng các đối số hàm tạo csi.CSI() và bỏ các lời gọi get_fb / tự động xoay.

  • Nạp một ảnh duy nhất với copy_to_fb=True và muốn nhìn thấy nó? Hãy thêm img.flush() sau khi nạp.

  • Đã sao chép bộ xử lý hậu kỳ YOLOv8? Hãy lập chỉ mục đầu ra sau bước ngưỡng theo hàng (bb[:, 4:]) thay vì theo cột.

  • So sánh csi0.framesize() sau khi đặt một tuple? Giờ nó trả về csi.CUSTOM.

  • Mọi thứ còn lại: nạp lại firmware và chạy.