Tworzenie niestandardowej aplikacji internetowej do wykrywania obiektów za pomocą MediaPipe

1. Zanim zaczniesz

MediaPipe Solutions umożliwia stosowanie w aplikacjach rozwiązań systemów uczących się. Udostępnia on platformę, która umożliwia konfigurowanie gotowych potoków przetwarzania, które dostarczają użytkownikom natychmiastowe, angażujące i przydatne dane wyjściowe. Możesz nawet dostosować te rozwiązania w Kreatorze modeli, aby zaktualizować modele domyślne.

Wykrywanie obiektów to jedno z kilku zadań opartych na ML, które są dostępne w rozwiązaniach MediaPipe. Lista zadań MediaPipe jest dostępna na Androida oraz w Pythonie i w internecie.

Dzięki temu ćwiczeniu w Codelabs dowiesz się, jak dodać wykrywanie obiektów do aplikacji internetowej, aby wykrywać psy na zdjęciach i nagrywać filmy z kamery internetowej.

Czego się nauczysz

  • Jak dodać zadanie wykrywania obiektów w aplikacji internetowej za pomocą zadań MediaPipe.

Co utworzysz

  • Aplikacja internetowa wykrywająca obecność psów. Możesz też dostosować model tak, aby wykrywał klasę wybranych obiektów za pomocą Kreatora modeli MediaPipe.

Czego potrzebujesz

  • Konto CodePen
  • Urządzenie z przeglądarką
  • Podstawowa znajomość języka JavaScript, CSS i HTML

2. Konfiguracja

To ćwiczenia w programie uruchamiają kod w CodePen – środowisku społecznościowych,które pozwala pisać kod w przeglądarce i sprawdzać wyniki podczas kompilacji.

Aby to zrobić:

  1. Na koncie CodePen przejdź do tego CodePen. Możesz użyć tego kodu jako podstawy do utworzenia własnego wzorca do wykrywania obiektów.
  2. W menu nawigacyjnym u dołu okna CodePen kliknij Fork, aby utworzyć kopię kodu startowego.

Menu nawigacyjne w CodePen, w którym znajduje się przycisk rozwidlenia

  1. Na karcie JS kliknij strzałkę rozwijania b15acb07e6357dce.png, a następnie wybierz Maksymalizuj edytor JavaScript. W ramach tego ćwiczenia z programowania możesz edytować materiały tylko na karcie JS, więc nie musisz wyświetlać kart HTML ani CSS.

Sprawdź aplikację startową

  1. W oknie podglądu zwróć uwagę na dwa zdjęcia psów i opcję uruchomienia kamery internetowej. Model używany w tym samouczku został wytrenowany na 3 psach wyświetlanych na 2 obrazach.

Podgląd aplikacji internetowej z kodu startowego

  1. Na karcie JS znajdziesz w kodzie kilka komentarzy. Możesz na przykład znaleźć taki komentarz w wierszu 15:
// Import the required package.

Komentarze te wskazują, gdzie należy wstawić fragmenty kodu.

3. Zaimportuj pakiet MediaPipe Tasks-vision i dodaj wymagane zmienne

  1. Na karcie JS zaimportuj pakiet MediaPipe tasks-vision:
// Import the required package.
​​import { ObjectDetector, FilesetResolver, Detection } from "https://cdn.skypack.dev/@mediapipe/tasks-vision@latest";

Ten kod importuje pakiet przy użyciu sieci dostarczania treści (CDN) Skypack. Aby dowiedzieć się więcej o tym, jak używać Skypack z kodem CodePen, zobacz Skypack + CodePen.

W swoich projektach możesz używać Node.js z npm, menedżerem pakietów lub wybraną siecią CDN. Więcej informacji o wymaganym pakiecie, który musisz zainstalować, znajdziesz w artykule Pakiety JavaScript.

  1. Zadeklaruj zmienne dla detektora obiektów i trybu uruchamiania:
// Create required variables.
let objectDetector = null;
let runningMode = "IMAGE";

Zmienna runningMode to ciąg znaków, który jest ustawiany na wartość "IMAGE" w przypadku wykrycia obiektów na obrazach lub wartość "VIDEO", gdy wykrywane są obiekty w filmie.

4. Zainicjuj detektor obiektów

  • Aby zainicjować detektor obiektów, dodaj ten kod po odpowiednim komentarzu na karcie JS:
// Initialize the object detector.
async function initializeObjectDetector() {
  const visionFilesetResolver = await FilesetResolver.forVisionTasks(
    "https://cdn.jsdelivr.net/npm/@mediapipe/tasks-vision@latest/wasm"
  );
  objectDetector = await ObjectDetector.createFromOptions(visionFilesetResolver, {
    baseOptions: {
      modelAssetPath: "https://storage.googleapis.com/mediapipe-assets/dogs.tflite"
    },
    scoreThreshold: 0.3,
    runningMode: runningMode
  });
}
initializeObjectDetector();

Metoda FilesetResolver.forVisionTasks() określa lokalizację pliku binarnego WebAssembly (Wasm) dla zadania.

Metoda ObjectDetector.createFromOptions() tworzy instancję detektora obiektów. Musisz podać ścieżkę do modelu używanego do wykrywania. W tym przypadku model wykrywania psów jest hostowany w Cloud Storage.

Właściwość scoreThreshold ma wartość 0.3. Oznacza to, że model zwraca wyniki dla każdego wykrytego obiektu z poziomem ufności wynoszącym co najmniej 30%. Możesz dostosować próg do potrzeb swojej aplikacji.

Właściwość runningMode jest ustawiana podczas inicjowania obiektu ObjectDetector. Tę i inne opcje możesz później zmienić.

5. Uruchamianie prognoz na obrazach

  • Aby uruchamiać prognozy dotyczące obrazów, przejdź do funkcji handleClick(), a następnie dodaj ten kod do jej treści:
// Verify object detector is initialized and choose the correct running mode.
if (!objectDetector) {
    alert("Object Detector still loading. Please try again");
    return;
  }

  if (runningMode === "VIDEO") {
    runningMode = "IMAGE";
    await objectDetector.setOptions({ runningMode: runningMode });
  }

Ten kod określa, czy detektor obiektów jest zainicjowany, i gwarantuje, że dla obrazów ustawiony jest tryb działania.

Wykrywanie obiektów

  • Aby wykrywać obiekty na obrazach, dodaj ten kod do treści funkcji handleClick():
// Run object detection.
  const detections = objectDetector.detect(event.target);

Ten fragment kodu zawiera przykład danych wyjściowych z tego zadania:

ObjectDetectionResult:
 Detection #0:
  Box: (x: 355, y: 133, w: 190, h: 206)
  Categories:
   index       : 17
   score       : 0.73828
   class name  : aci
 Detection #1:
  Box: (x: 103, y: 15, w: 138, h: 369)
  Categories:
   index       : 17
   score       : 0.73047
   class name  : tikka

Przetwarzanie i wyświetlanie prognoz

  1. Na końcu treści funkcji handleClick() wywołaj funkcję displayImageDetections():
// Call the displayImageDetections() function.
displayImageDetections(detections, event.target);
  1. Aby wyświetlić wyniki wykrywania obiektów w treści funkcji displayImageDetections(), dodaj ten kod:
// Display object detection results.
  
  const ratio = resultElement.height / resultElement.naturalHeight;

  for (const detection of result.detections) {
    // Description text
    const p = document.createElement("p");
    p.setAttribute("class", "info");
    p.innerText =
      detection.categories[0].categoryName +
      " - with " +
      Math.round(parseFloat(detection.categories[0].score) * 100) +
      "% confidence.";
    // Positioned at the top-left of the bounding box.
    // Height is that of the text.
    // Width subtracts text padding in CSS so that it fits perfectly.
    p.style =
      "left: " +
      detection.boundingBox.originX * ratio +
      "px;" +
      "top: " +
      detection.boundingBox.originY * ratio +
      "px; " +
      "width: " +
      (detection.boundingBox.width * ratio - 10) +
      "px;";
    const highlighter = document.createElement("div");
    highlighter.setAttribute("class", "highlighter");
    highlighter.style =
      "left: " +
      detection.boundingBox.originX * ratio +
      "px;" +
      "top: " +
      detection.boundingBox.originY * ratio +
      "px;" +
      "width: " +
      detection.boundingBox.width * ratio +
      "px;" +
      "height: " +
      detection.boundingBox.height * ratio +
      "px;";

    resultElement.parentNode.appendChild(highlighter);
    resultElement.parentNode.appendChild(p);
  }

Ta funkcja wyświetla ramki ograniczające na obiektach wykrytych na obrazach. Usuwa poprzednie podświetlenia, a potem tworzy i wyświetla tagi <p>, by wyróżnić każdy wykryty obiekt.

Testowanie aplikacji

Gdy wprowadzisz zmiany w kodzie w CodePen, okienko podglądu będzie automatycznie odświeżane po zapisaniu. Jeśli autozapis jest włączony, aplikacja prawdopodobnie została już odświeżona, ale warto zrobić to jeszcze raz.

Aby przetestować aplikację, wykonaj te czynności:

  1. W okienku podglądu klikaj poszczególne obrazy, aby wyświetlić podpowiedzi. Ramka ograniczająca zawiera imię psa z poziomem ufności modelu.
  2. Jeśli nie widzisz ramki ograniczającej, otwórz Narzędzia deweloperskie w Chrome, a następnie sprawdź, czy w panelu Konsola nie ma błędów, lub przejrzyj poprzednie kroki, aby upewnić się, że nic nie zostało pominięte.

Podgląd aplikacji internetowej z ramkami ograniczającymi psy wykryte na obrazach

6. Uruchamianie prognoz na filmie z kamery internetowej

Wykrywanie obiektów

  • Aby wykrywać obiekty w filmie z kamery internetowej na żywo, przejdź do funkcji predictWebcam(), a następnie dodaj do jej treści ten kod:
// Run video object detection.
  // If image mode is initialized, create a classifier with video runningMode.
  if (runningMode === "IMAGE") {
    runningMode = "VIDEO";
    await objectDetector.setOptions({ runningMode: runningMode });
  }
  let nowInMs = performance.now();

  // Detect objects with the detectForVideo() method.
  const result = await objectDetector.detectForVideo(video, nowInMs);

  displayVideoDetections(result.detections);

Wykrywanie obiektów w filmach korzysta z tych samych metod niezależnie od tego, czy wnioskowanie dotyczy danych strumieniowanych, czy całego filmu. Metoda detectForVideo() jest podobna do metody detect() używanej w przypadku zdjęć, ale zawiera dodatkowy parametr sygnatury czasowej powiązanej z bieżącą klatką. Funkcja wykrywa na bieżąco czas, więc jako sygnaturę czasową przekazujesz bieżącą godzinę.

Przetwarzanie i wyświetlanie prognoz

  • Aby przetworzyć i wyświetlić wyniki wykrywania, przejdź do funkcji displayVideoDetections(), a następnie dodaj ten kod do jej treści:
//  Display video object detection results.
  for (let child of children) {
    liveView.removeChild(child);
  }
  children.splice(0);

  // Iterate through predictions and draw them to the live view.
  for (const detection of result.detections) {
    const p = document.createElement("p");
    p.innerText =
      detection.categories[0].categoryName +
      " - with " +
      Math.round(parseFloat(detection.categories[0].score) * 100) +
      "% confidence.";
    p.style =
      "left: " +
      (video.offsetWidth -
        detection.boundingBox.width -
        detection.boundingBox.originX) +
      "px;" +
      "top: " +
      detection.boundingBox.originY +
      "px; " +
      "width: " +
      (detection.boundingBox.width - 10) +
      "px;";

    const highlighter = document.createElement("div");
    highlighter.setAttribute("class", "highlighter");
    highlighter.style =
      "left: " +
      (video.offsetWidth -
        detection.boundingBox.width -
        detection.boundingBox.originX) +
      "px;" +
      "top: " +
      detection.boundingBox.originY +
      "px;" +
      "width: " +
      (detection.boundingBox.width - 10) +
      "px;" +
      "height: " +
      detection.boundingBox.height +
      "px;";

    liveView.appendChild(highlighter);
    liveView.appendChild(p);

    // Store drawn objects in memory so that they're queued to delete at next call.
    children.push(highlighter);
    children.push(p);
  }
}

Ten kod usuwa wszelkie wcześniejsze wyróżnienia, a następnie tworzy i wyświetla tagi <p>, aby wyróżnić każdy wykryty obiekt.

Testowanie aplikacji

Aby przetestować wykrywanie aktywnych obiektów, warto mieć obraz jednego z psów, na którym model został wytrenowany.

Aby przetestować aplikację, wykonaj te czynności:

  1. Pobierz na telefon jedno ze zdjęć psa.
  2. W okienku podglądu kliknij Włącz kamerę internetową.
  3. Jeśli w przeglądarce pojawi się okno z prośbą o przyznanie dostępu do kamery internetowej, przyznaj te uprawnienia.
  4. Trzymaj zdjęcie psa zrobione na telefonie przed kamerą internetową. Ramka ograniczająca zawiera imię psa i poziom ufności modelu.
  5. Jeśli nie widzisz ramki ograniczającej, otwórz Narzędzia deweloperskie w Chrome, a następnie sprawdź, czy w panelu Konsola nie ma błędów, lub przejrzyj poprzednie kroki, aby upewnić się, że nic nie zostało pominięte.

Ramka ograniczająca zdjęcie psa trzymanego przed kamerą

7. Gratulacje

Gratulacje! Masz stworzoną przez Ciebie aplikację internetową, która wykrywa obiekty na obrazach. Więcej informacji znajdziesz w pełnej wersji aplikacji CodePen.

Więcej informacji