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

1. Zanim zaczniesz

MediaPipe Solutions umożliwia stosowanie w aplikacjach rozwiązań wykorzystujących uczenie maszynowe. Zapewnia ona platformę, która umożliwia konfigurowanie gotowych potoków przetwarzania, które dostarczają użytkownikom natychmiastowe, angażujące i przydatne wyniki. Możesz nawet dostosować te rozwiązania za pomocą narzędzia Model Maker, aby zaktualizować modele domyślne.

Wykrywanie obiektów to jedno z kilku zadań związanych z uczeniem maszynowym w zakresie widzenia, które oferuje MediaPipe Solutions. MediaPipe Tasks jest dostępny na Androida, Pythona i w przeglądarce.

W tym ćwiczeniu dodasz do aplikacji internetowej funkcję wykrywania obiektów, która będzie rozpoznawać psy na zdjęciach i w filmach z kamery internetowej.

Czego się nauczysz

  • Jak włączyć 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 do wykrywania wybranej klasy obiektów za pomocą MediaPipe Model Maker.

Czego potrzebujesz

  • konto CodePen,
  • Urządzenie z przeglądarką
  • Podstawowa znajomość języków JavaScript, CSS i HTML

2. Konfiguracja

To ćwiczenie wykorzystuje CodePen, czyli środowisko programistyczne, które umożliwia pisanie kodu w przeglądarce i sprawdzanie wyników w trakcie tworzenia.

Aby przeprowadzić konfigurację, wykonaj te czynności:

  1. Na koncie CodePen otwórz ten CodePen. Ten kod będzie punktem wyjścia do utworzenia własnego detektora obiektów.
  2. W dolnej części CodePen w menu nawigacyjnym kliknij Fork, aby utworzyć kopię kodu startowego.

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

  1. Na karcie JS kliknij strzałkę rozwijającą b15acb07e6357dce.png, a następnie wybierz Zmaksymalizuj edytor JavaScript. W tym ćwiczeniu będziesz edytować kod tylko na karcie JS, więc nie musisz otwierać kart HTML ani CSS.

Sprawdzanie aplikacji startowej

  1. W okienku podglądu zobaczysz 2 zdjęcia psów i opcję uruchomienia kamery internetowej. Model użyty w tym samouczku został wytrenowany na podstawie 3 psów widocznych na 2 obrazach.

Podgląd aplikacji internetowej z kodu startowego

  1. Na karcie JS zauważysz, że w kodzie jest kilka komentarzy. Na przykład w wierszu 15 możesz znaleźć ten komentarz:
// Import the required package.

Te komentarze 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 używa sieci dostarczania treści (CDN) Skypack do importowania pakietu. Więcej informacji o korzystaniu z Skypack w CodePen znajdziesz w artykule Skypack + CodePen.

W projektach możesz używać Node.js z npm lub wybranym menedżerem pakietów bądź 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 działania:
// Create required variables.
let objectDetector = null;
let runningMode = "IMAGE";

Zmienna runningMode to ciąg znaków, który przyjmuje wartość "IMAGE", gdy wykrywasz obiekty na obrazach, lub wartość "VIDEO", gdy wykrywasz obiekty w filmie.

4. Inicjowanie detektora 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ę binarnego pliku 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 obiektu wykrytego z poziomem ufności co najmniej 30%. Możesz dostosować ten próg do potrzeb swojej aplikacji.

Właściwość runningMode jest ustawiana podczas inicjowania obiektu ObjectDetector. W razie potrzeby możesz później zmienić to i inne ustawienia.

5. Uruchamianie prognoz na podstawie obrazów

  • Aby uruchomić prognozy dotyczące obrazów, przejdź do funkcji handleClick(), a następnie dodaj ten kod do treści funkcji:
// 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 zapewnia, że tryb działania jest ustawiony dla obrazów.

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 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. W treści funkcji displayImageDetections() dodaj ten kod, aby wyświetlać wyniki wykrywania obiektów:
// 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 wokół obiektów wykrytych na obrazach. Usuwa poprzednie wyróżnienia, a następnie tworzy i wyświetla tagi <p>, aby wyróżnić każdy wykryty obiekt.

Testowanie aplikacji

Gdy wprowadzisz zmiany w kodzie w CodePen, panel podglądu odświeży się automatycznie po zapisaniu. Jeśli automatyczne zapisywanie jest włączone, aplikacja prawdopodobnie została już odświeżona, ale warto odświeżyć ją jeszcze raz.

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

  1. W okienku podglądu kliknij poszczególne obrazy, aby wyświetlić prognozy. Ramka ograniczająca pokazuje imię psa wraz z poziomem ufności modelu.
  2. Jeśli nie ma ramki ograniczającej, otwórz Narzędzia deweloperskie w Chrome, a potem sprawdź, czy w panelu Konsola nie ma błędów. Możesz też przejrzeć poprzednie kroki, aby się upewnić, że niczego nie pominąłeś(-aś).

Podgląd aplikacji internetowej z ramkami ograniczającymi wokół psów wykrytych na obrazach

6. Przeprowadzanie prognoz na podstawie obrazu z kamery internetowej na żywo

Wykrywanie obiektów

  • Aby wykrywać obiekty w obrazie na żywo z kamery internetowej, przejdź do funkcji predictWebcam(), a następnie dodaj ten kod do treści funkcji:
// 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 wykorzystuje te same metody niezależnie od tego, czy wnioskowanie jest przeprowadzane na danych strumieniowych, czy na całym filmie. 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 zdarzenia na żywo, więc jako sygnaturę czasową przekazujesz bieżący czas.

Przetwarzanie i wyświetlanie prognoz

  • Aby przetworzyć i wyświetlić wyniki wykrywania, przejdź do funkcji displayVideoDetections(), a następnie dodaj ten kod do treści funkcji:
//  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 poprzednie wyróżnienia, a następnie tworzy i wyświetla tagi <p>, aby wyróżnić każdy wykryty obiekt.

Testowanie aplikacji

Aby przetestować wykrywanie obiektów na żywo, warto mieć obraz jednego z psów, na którym wytrenowano model.

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

  1. Pobierz jedno ze zdjęć psa na telefon.
  2. W okienku podglądu kliknij Włącz kamerę.
  3. Jeśli w przeglądarce pojawi się okno z prośbą o przyznanie dostępu do kamery internetowej, zezwól na dostęp.
  4. Przytrzymaj zdjęcie psa na telefonie przed kamerą internetową. Ramka ograniczająca zawiera imię psa i poziom ufności modelu.
  5. Jeśli nie ma ramki ograniczającej, otwórz Narzędzia deweloperskie w Chrome, a potem sprawdź, czy w panelu Konsola nie ma błędów. Możesz też przejrzeć poprzednie kroki, aby się upewnić, że niczego nie pominąłeś(-aś).

Ramka ograniczająca na obrazie psa, który jest trzymany przed kamerą internetową

7. Gratulacje

Gratulacje! Masz aplikację internetową, która wykrywa obiekty na obrazach. Więcej informacji znajdziesz w ukończonej wersji aplikacji w CodePen.

Więcej informacji