7.3. Hello BlazeFace¶
BlazeFace là mạng nơ-ron phát hiện khuôn mặt từ bộ sưu tập MediaPipe của Google. Một lần gọi suy luận trả về hình chữ nhật hộp giới hạn xung quanh mỗi khuôn mặt được phát hiện cùng với sáu điểm đặc trưng trên khuôn mặt -- mắt phải, mắt trái, mũi, miệng, tai phải, tai trái. Mỗi OpenMV Cam được xuất xưởng có hỗ trợ mạng nơ-ron đều mang mô hình blazeface_front_128.tflite trên bộ nhớ flash, vì vậy việc chạy bộ phát hiện khuôn mặt đầu cuối đến đầu cuối chỉ mất vài dòng Python.
7.3.1. Tập lệnh đầy đủ¶
import csi
import ml
from ml.postprocessing.mediapipe import BlazeFace
csi0 = csi.CSI()
csi0.reset()
csi0.pixformat(csi.RGB565)
csi0.framesize(csi.VGA)
csi0.window((400, 400))
model = ml.Model("/rom/blazeface_front_128.tflite",
postprocess=BlazeFace(threshold=0.4))
while True:
img = csi0.snapshot()
for (x, y, w, h), score, keypoints in model.predict([img]):
img.draw_rectangle((x, y, w, h), color=(0, 255, 0))
ml.utils.draw_keypoints(img, keypoints, color=(255, 0, 0))
Đó là toàn bộ bộ phát hiện khuôn mặt. Không có gì khác; tập lệnh chụp một khung hình, đưa nó cho mô hình, duyệt qua danh sách kết quả phát hiện được trả về, và vẽ hình chữ nhật hộp giới hạn cùng sáu điểm đặc trưng của mỗi khuôn mặt trở lại khung hình. Xem trước trong IDE hiển thị các hộp và điểm đặc trưng theo thời gian thực.
7.3.2. Ý nghĩa từng dòng¶
Ba dòng đầu tiên nhập các module mà tập lệnh cần. csi là giao diện cảm biến camera; ml là module học máy mà phần còn lại của chương này đề cập; BlazeFace là bộ xử lý hậu kỳ chuyển đổi tensor đầu ra thô của BlazeFace thành danh sách hộp giới hạn và điểm đặc trưng mà tập lệnh lặp qua.
Năm dòng tiếp theo cấu hình cảm biến. Camera được đặt lại về trạng thái đã biết, được đặt sang màu sắc RGB565, được đặt thành độ phân giải VGA, và sau đó được cắt cửa sổ thành hình vuông 400 nhân 400. Cửa sổ quan trọng: BlazeFace được huấn luyện trên các ảnh cắt hình vuông, và việc cung cấp đầu vào hình vuông sẽ căn chỉnh tỷ lệ khung hình mà mạng mong đợi với những gì nó thấy trong khung hình được chụp.
Dòng tải mô hình mở tệp mô hình:
model = ml.Model("/rom/blazeface_front_128.tflite",
postprocess=BlazeFace(threshold=0.4))
ml.Model đọc tệp tại đường dẫn đã cho -- /rom/ là hệ thống tệp trú ngụ trên flash được đề cập sau -- và trả về một đối tượng mô hình mà tập lệnh sẽ chạy suy luận dựa trên. Từ khóa postprocess= đăng ký bộ xử lý hậu kỳ BlazeFace; nếu không có nó, predict sẽ trả về tensor đầu ra thô của mạng và ứng dụng sẽ phải giải mã chúng thủ công. Với nó, predict trả về kết quả đã giải mã trực tiếp. Đối số threshold=0.4 trên bộ xử lý hậu kỳ đặt độ tin cậy tối thiểu mà mạng phải báo cáo trước khi một kết quả phát hiện được giữ lại; các giá trị thấp hơn bắt được các khuôn mặt mờ hơn nhưng tốn nhiều kết quả dương tính giả hơn.
Bốn dòng còn lại là vòng lặp chính. Mỗi lần qua nó chụp một khung hình và hỏi mô hình về những gì nó thấy:
img = csi0.snapshot()
for (x, y, w, h), score, keypoints in model.predict([img]):
img.draw_rectangle((x, y, w, h), color=(0, 255, 0))
ml.utils.draw_keypoints(img, keypoints, color=(255, 0, 0))
predict() nhận một danh sách đầu vào (ở đây là một ảnh đã chụp) và trả về danh sách các bộ kết quả phát hiện. Mỗi bộ chứa hình chữ nhật hộp giới hạn (x, y, w, h), điểm tin cậy score từ không đến một, và một ndarray (6, 2) chứa tọa độ điểm đặc trưng -- mắt phải, mắt trái, mũi, miệng, tai phải và tai trái theo thứ tự đó. Lệnh vẽ sử dụng draw_rectangle() -- cùng một primitive mà mọi bộ phát hiện cổ điển trong chương ảnh đã kết thúc bằng nó -- để phác thảo khuôn mặt. ml.utils.draw_keypoints() là một helper nhỏ từ các tiện ích ml đánh dấu mỗi điểm đặc trưng bằng một dấu thập tại vị trí (x, y) của nó.
7.3.3. Những gì tập lệnh không nói¶
Tập lệnh có bảy dòng chạy được về công việc suy luận sau phần nhập và thiết lập cảm biến, nhưng rất nhiều phép tính xảy ra bên trong bảy dòng đó. Khung hình RGB565 400 nhân 400 đã chụp trở thành tensor 8-bit lượng tử hóa 128 nhân 128 trước khi đến mạng; mạng chạy hàng trăm phép tính dựa trên hàng chục nghìn trọng số; các tensor điểm tin cậy và độ lệch hộp kết quả trở thành danh sách xếp hạng các hộp giới hạn không chồng chéo kèm điểm đặc trưng gắn kèm trước khi predict trả về. Mỗi một trong số những phép biến đổi đó là thứ mà ứng dụng có thể kiểm soát nếu cần, và một số trong số chúng phải được điều chỉnh cho bất kỳ mô hình nào không phải mặc định.
Bốn mục tiếp theo sẽ duyệt qua những phép biến đổi đó. Theo thứ tự:
Module ml -- những gì
ml.Modelhiển thị sau khi mô hình được tải, và tệp mô hình thực sự nằm ở đâu trên camera.Đường ống suy luận -- bốn giai đoạn của mỗi lần gọi
predict().Các engine suy luận -- các đường CPU và NPU chạy phép tính của mạng.
Giải mã đầu ra -- các bộ xử lý hậu kỳ chuyển đổi tensor đầu ra thô thành các kết quả phát hiện mà tập lệnh này đã lặp qua.
Đến cuối chương, người đọc có thể viết tập lệnh tương đương cho một mô hình không được xuất xưởng cùng camera, giải mã một tensor mà bộ xử lý hậu kỳ chưa tồn tại, và lý giải tại sao một mô hình cụ thể chạy ở 30 FPS trên camera này và 3 FPS trên camera kia.