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

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

Informacje o tym ćwiczeniu (w Codelabs)

subjectOstatnia aktualizacja: paź 12, 2023
account_circleAutorzy: Jen Person

1. Zanim zaczniesz

MediaPipe Solutions umożliwia stosowanie w aplikacjach rozwiązań wykorzystujących systemy uczące się. Udostępnia ona ramy, które umożliwiają konfigurowanie gotowych przepływów przetwarzania, które dostarczają użytkownikom natychmiastowych, atrakcyjnych i przydatnych wyników. Możesz nawet dostosować te rozwiązania za pomocą Model Makera, aby zaktualizować modele domyślne.

Wykrywanie obiektów to jedno z kilku zadań dotyczących widzenia AI, które oferuje MediaPipe Solutions. MediaPipe Tasks jest dostępny w wersji na Androida, w Pythonie i w internecie.

W tym laboratorium kodu dodasz do aplikacji internetowej wykrywanie obiektów, aby wykrywać psy na zdjęciach i w filmach z kamery internetowej.

Czego się nauczysz

  • Jak uwzględnić zadanie wykrywania obiektów w aplikacji internetowej za pomocą MediaPipe Tasks.

Co utworzysz

  • Aplikacja internetowa, która wykrywa 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ą
  • podstawy JavaScriptu, CSS i HTML;

2. Konfiguracja

Ten warsztat programistyczny uruchamia kod w CodePen, czyli środowisku programistycznym, które umożliwia pisanie kodu w przeglądarce i sprawdzanie wyników w miarę tworzenia.

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

  1. Na koncie CodePen otwórz CodePen. Użyj tego kodu jako podstawy do utworzenia własnego wykrywacza obiektów.
  2. W dolnej części CodePen w menu nawigacyjnym kliknij Fork (Fork), aby utworzyć kopię kodu startowego.

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

  1. Na karcie JS kliknij strzałkę b15acb07e6357dce.png i wybierz Maksymalizacja edytora JavaScript. W tym ćwiczeniu możesz edytować tylko kod na karcie JS, więc nie musisz wyświetlać kart HTML ani CSS.

Sprawdzanie aplikacji inicjującej

  1. W panelu podglądu zobaczysz 2 zdjęcia psów i opcję włączenia kamery internetowej. Model, którego używasz w tym samouczku, został wytrenowany na 3 psach widocznych na 2 obrazach.

Podgląd aplikacji internetowej utworzonej na podstawie kodu startowego

  1. Na karcie JS widać, że w kodzie znajduje się kilka komentarzy. Na przykład w wierszu 15 możesz znaleźć taki 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 połączeniu z CodePen znajdziesz w artykule Skypack + CodePen.

W swoich projektach możesz używać Node.js z npm lub wybranego menedżera pakietów albo CDN. Więcej informacji o wymaganym pakiecie, który należy 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 ma wartość "IMAGE", gdy wykryjesz obiekty na zdjęciach, lub wartość "VIDEO", gdy wykryjesz obiekty w filmie.

4. Inicjalizacja 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 wykrytego obiektu 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ć tę i inne opcje.

5. Przeprowadzanie prognoz na obrazach

  • Aby przeprowadzić przewidywania na podstawie obrazów, otwórz funkcję handleClick() i dodaj do jej treści ten kod:
// 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 do funkcji handleClick() ten kod:
// 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 ciała funkcji handleClick() wywołaj funkcję displayImageDetections():
// Call the displayImageDetections() function.
displayImageDetections
(detections, event.target);
  1. Aby wyświetlić wyniki wykrywania obiektów, dodaj do treści funkcji displayImageDetections() 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 wokół obiektów wykrytych na obrazach. Usuwa wcześniejsze 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, po zapisaniu panel podglądu zostanie automatycznie odświeżony. Jeśli automatyczne zapisywanie jest włączone, aplikacja prawdopodobnie została już odświeżona, ale warto ją odświeżyć jeszcze raz.

Aby przetestować aplikację:

  1. W okienku podglądu kliknij po kolei wszystkie obrazy, aby wyświetlić prognozy. Pole ograniczające zawiera nazwę psa i poziom ufności modelu.
  2. Jeśli nie ma ramki, otwórz Narzędzia deweloperskie w Chrome, a potem sprawdź panel Konsola pod kątem błędów. Możesz też sprawdzić poprzednie kroki, aby upewnić się, że niczego nie pominięto.

Podgląd aplikacji internetowej z ramkami wokół psów wykrytych na zdjęciach

6. Wykonywanie prognoz na podstawie obrazu z kamery internetowej

Wykrywanie obiektów

  • Aby wykrywać obiekty na bieżąco w filmie z kamery internetowej, otwórz funkcję predictWebcam() i dodaj do niej 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 filmie wykorzystuje te same metody niezależnie od tego, czy wykonujesz wnioskowanie na danych strumieniowych, czy na całym filmie. Metoda detectForVideo() jest podobna do metody detect() używanej w przypadku zdjęć, ale zawiera dodatkowy parametr dla sygnatury czasowej powiązanej z bieżącą ramką. Funkcja wykonuje wykrywanie na żywo, więc jako sygnatury czasowej używasz bieżącego czasu.

Przetwarzanie i wyświetlanie prognoz

  • Aby przetworzyć i wyświetlić wyniki wykrywania, otwórz funkcję displayVideoDetections() i dodaj do niej ten kod:
//  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 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 obiektów na żywo, warto mieć obraz jednego z psów, na których model został wytrenowany.

Aby przetestować aplikację:

  1. Pobierz na telefon jedno ze zdjęć psa.
  2. W okienku podglądu kliknij Włącz kamerę.
  3. Jeśli przeglądarka wyświetli okno z prośbą o dostęp do kamery internetowej, przyznaj go.
  4. Trzymaj zdjęcie psa na telefonie przed kamerą internetową. Boks ograniczający zawiera nazwę psa i poziom ufności modelu.
  5. Jeśli nie ma ramki, otwórz Narzędzia deweloperskie w Chrome, a potem sprawdź panel Konsola pod kątem błędów. Możesz też sprawdzić poprzednie kroki, aby upewnić się, że niczego nie pominięto.

Ramka ograniczająca na obrazie przedstawiającym psa trzymanego przed kamerą internetową