7.3. Merhaba BlazeFace

BlazeFace, Google’ın MediaPipe koleksiyonundan bir yüz tespiti sinir ağıdır. Tek bir çıkarım çağrısı, tespit edilen her yüzün etrafında bir sınırlayıcı dikdörtgen ile birlikte altı yüz işaret noktası döndürür – sağ göz, sol göz, burun, ağız, sağ kulak, sol kulak. Sinir ağı desteğiyle sevk edilen her OpenMV Cam, flash bellekte blazeface_front_128.tflite modelini taşır, bu nedenle baştan sona bir yüz tespit ediciyi çalıştırmak birkaç satır Python alır.

7.3.1. Tam betik

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))

İşte tüm yüz tespit edici budur. Başka bir şey yoktur; betik bir çerçeve yakalar, onu modele verir, döndürülen tespit listesini gezer ve her yüzün sınırlayıcı dikdörtgenini artı altı işaret noktasını çerçeveye geri çizer. IDE önizlemesi kutuları ve işaret noktalarını gerçek zamanlı olarak gösterir.

7.3.2. Her satırın yaptığı

İlk üç satır, betiğin ihtiyaç duyduğu modülleri içe aktarır. csi, kamera-sensör arabirimidir; ml, bu bölümün geri kalanının konusu olan makine öğrenmesi modülüdür; BlazeFace, BlazeFace’in ham çıktı tensörlerini, betiğin üzerinde döngü yaptığı sınırlayıcı kutu ve işaret noktası listesine dönüştüren son işlemcidir.

Sonraki beş satır sensörü yapılandırır. Kamera bilinen bir duruma sıfırlanır, RGB565 renge ayarlanır, VGA çözünürlüğüne ayarlanır ve ardından 400’e 400’lük bir kareye pencerelenir (windowed). Pencere önemlidir: BlazeFace kare kırpmalar üzerinde eğitilmiştir ve ona kare bir girdi vermek, ağın beklediği en boy oranını yakalanan çerçevede gördüğüyle hizalar.

Model yükleme satırı model dosyasını açar:

model = ml.Model("/rom/blazeface_front_128.tflite",
                 postprocess=BlazeFace(threshold=0.4))

ml.Model, verilen yoldaki dosyayı okur – /rom/ daha sonra ele alınan flash bellekte yerleşik bir dosya sistemidir – ve betiğin üzerinde çıkarımlar çalıştıracağı bir model nesnesi döndürür. postprocess= anahtar sözcüğü BlazeFace son işlemcisini kaydeder; o olmadan predict ağın ham çıktı tensörlerini döndürür ve uygulamanın bunları elle çözmesi gerekirdi. Onunla birlikte predict çözülmüş sonucu doğrudan döndürür. Son işlemci üzerindeki threshold=0.4 argümanı, bir tespit tutulmadan önce ağın bildirmesi gereken minimum güveni belirler; daha düşük değerler daha fazla yanlış pozitif pahasına daha soluk yüzleri yakalar.

Kalan dört satır ana döngüdür. Bundan geçen her tur bir çerçeve yakalar ve modele ne gördüğünü sorar:

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(), bir girdi listesi alır (burada, yakalanan bir görüntü) ve bir tespit demetleri listesi döndürür. Her demet, sınırlayıcı dikdörtgeni (x, y, w, h), sıfır ile bir arasında bir güven score değerini ve işaret noktası koordinatlarından oluşan bir (6, 2) ndarray tutar – sağ göz, sol göz, burun, ağız, sağ kulak ve sol kulak, bu sırayla. Çizim çağrısı yüzü çerçevelemek için draw_rectangle() kullanır – görüntü bölümündeki her klasik tespit edicinin bittiği aynı temel işlev. ml.utils.draw_keypoints(), her anahtar noktayı (x, y) konumunda bir çarpı ile işaretleyen, ml yardımcı araçlarından küçük bir yardımcıdır.

7.3.3. Betiğin söylemediği

Betik, içe aktarmalar ve sensör kurulumunun ötesinde yedi çalıştırılabilir satır çıkarım işidir, ancak o yedi satırın içinde çok büyük miktarda aritmetik gerçekleşir. Yakalanan 400’e 400 RGB565 çerçeve, ağa ulaşmadan önce 128’e 128’lik kuantize edilmiş 8 bitlik bir tensöre dönüşür; ağ, on binlerce ağırlığa karşı yüzlerce işlem çalıştırır; ortaya çıkan güven skorları ve kutu kaymaları tensörleri, predict döndürmeden önce eklenmiş işaret noktalarına sahip, sıralanmış, çakışmayan bir sınırlayıcı kutu listesine dönüşür. Bu dönüşümlerin her biri, uygulamanın ihtiyaç duyarsa kontrol edebileceği bir şeydir ve birkaçının varsayılan olmayan herhangi bir model için ayarlanması gerekir.

Sonraki dört alt bölüm bu dönüşümleri açar. Sırayla:

  • ml modülü – bir model yüklendikten sonra ml.Model‘in neyi açığa çıkardığı ve model dosyasının kamerada gerçekte nerede yaşadığı.

  • Çıkarım boru hattı – her predict() çağrısının dört aşaması.

  • Çıkarım motorları – ağın aritmetiğini çalıştıran CPU ve NPU yolları.

  • Çıktının çözülmesi – ham çıktı tensörlerini bu betiğin üzerinde döngü yaptığı tespitlere dönüştüren son işlemciler.

Bölümün sonunda okuyucu, kamerayla birlikte sevk edilmeyen bir model için eşdeğer betiği yazabilir, son işlemcisi henüz var olmayan bir tensörü çözebilir ve belirli bir modelin neden bir kamerada 30 FPS ve bir başkasında 3 FPS çalıştığı hakkında akıl yürütebilir.