Crea un'app web per il rilevamento di oggetti personalizzata con MediaPipe

1. Prima di iniziare

MediaPipe Solutions ti consente di applicare soluzioni di machine learning (ML) alle tue app. Fornisce un framework che ti consente di configurare pipeline di elaborazione predefinite che forniscono agli utenti output immediati, coinvolgenti e utili. Puoi persino personalizzare queste soluzioni con Model Maker per aggiornare i modelli predefiniti.

Il rilevamento di oggetti è una delle varie attività di visione ML offerte da MediaPipe Solutions. MediaPipe Tasks è disponibile per Android, Python e il web.

In questo codelab, aggiungerai il rilevamento di oggetti a un'app web per rilevare i cani nelle immagini e in un video della webcam in diretta.

Obiettivi didattici

  • Come incorporare un'attività di rilevamento di oggetti in un'app web con MediaPipe Tasks.

Che cosa creerai

  • Un'app web che rileva la presenza di cani. Puoi anche personalizzare un modello per rilevare una classe di oggetti a tua scelta con MediaPipe Model Maker.

Che cosa ti serve

  • Un account CodePen
  • Un dispositivo con un browser web
  • Conoscenze di base di JavaScript, CSS e HTML

2. Configurazione

Questo codelab esegue il codice in CodePen,un ambiente di sviluppo social che ti consente di scrivere codice nel browser e controllare i risultati durante la creazione.

Per la configurazione:

  1. Nel tuo account CodePen, vai a questo CodePen. Utilizza questo codice come base di partenza per creare il tuo rilevatore di oggetti.
  2. Nella parte inferiore di CodePen, nel menu di navigazione, fai clic su Fork per creare una copia del codice di avvio.

Il menu di navigazione in CodePen in cui si trova il pulsante Fork

  1. Nella scheda JS, fai clic sulla freccia di espansione b15acb07e6357dce.png e poi seleziona Maximize JavaScript editor (Massimizza editor JavaScript). Per questo codelab, devi modificare solo il lavoro nella scheda JS , quindi non devi visualizzare le schede HTML o CSS.

Esaminare l'app di base

  1. Nel riquadro di anteprima, nota che sono presenti due immagini di cani e un'opzione per eseguire la webcam. Il modello utilizzato in questo tutorial è stato addestrato sui tre cani mostrati nelle due immagini.

Un'anteprima dell'app web dal codice di avvio

  1. Nella scheda JS, nota che nel codice sono presenti diversi commenti. Ad esempio, puoi trovare il seguente commento alla riga 15:
// Import the required package.

Questi commenti indicano dove devi inserire gli snippet di codice.

3. Importare il pacchetto tasks-vision di MediaPipe e aggiungere le variabili richieste

  1. Nella scheda JS, importa il pacchetto tasks-vision di MediaPipe:
// Import the required package.
​​import { ObjectDetector, FilesetResolver, Detection } from "https://cdn.skypack.dev/@mediapipe/tasks-vision@latest";

Questo codice utilizza la rete CDN (Content Delivery Network) Skypack per importare il pacchetto. Per ulteriori informazioni su come utilizzare Skypack con CodePen, consulta Skypack + CodePen.

Nei tuoi progetti, puoi utilizzare Node.js con npm o il gestore di pacchetti o la rete CDN di tua scelta. Per ulteriori informazioni sul pacchetto richiesto che devi installare, consulta Pacchetti JavaScript.

  1. Dichiara le variabili per il rilevatore di oggetti e la modalità di esecuzione:
// Create required variables.
let objectDetector = null;
let runningMode = "IMAGE";

La variabile runningMode è una stringa impostata su un valore "IMAGE" quando rilevi oggetti nelle immagini o su un valore "VIDEO" quando rilevi oggetti nel video.

4. Inizializzare il rilevatore di oggetti

  • Per inizializzare il rilevatore di oggetti, aggiungi il seguente codice dopo il commento pertinente nella scheda 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();

Il metodo FilesetResolver.forVisionTasks() specifica la posizione del file binario WebAssembly (Wasm) per l'attività.

Il metodo ObjectDetector.createFromOptions() crea un'istanza del rilevatore di oggetti. Devi fornire un percorso al modello utilizzato per il rilevamento. In questo caso, il modello di rilevamento dei cani è ospitato su Cloud Storage.

La proprietà scoreThreshold è impostata su un valore 0.3. Ciò significa che il modello restituisce risultati per qualsiasi oggetto rilevato con un livello di confidenza pari o superiore al 30%. Puoi regolare questa soglia in base alle esigenze della tua app.

La proprietà runningMode viene impostata all'inizializzazione dell'oggetto ObjectDetector. Puoi modificare questa e altre opzioni in base alle esigenze in un secondo momento.

5. Eseguire previsioni sulle immagini

  • Per eseguire previsioni sulle immagini, vai alla funzione handleClick() e poi aggiungi il seguente codice al corpo della funzione:
// 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 });
  }

Questo codice determina se il rilevatore di oggetti è inizializzato e garantisce che la modalità di esecuzione sia impostata per le immagini.

Rilevare oggetti

  • Per rilevare gli oggetti nelle immagini, aggiungi il seguente codice al corpo della funzione handleClick():
// Run object detection.
  const detections = objectDetector.detect(event.target);

Il seguente snippet di codice include un esempio dei dati di output di questa attività:

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

Elaborare e visualizzare le previsioni

  1. Alla fine del corpo della funzione handleClick(), chiama la funzione displayImageDetections():
// Call the displayImageDetections() function.
displayImageDetections(detections, event.target);
  1. Nel corpo della funzione displayImageDetections(), aggiungi il seguente codice per visualizzare i risultati del rilevamento di oggetti:
// 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);
  }

Questa funzione visualizza i riquadri di delimitazione sugli oggetti rilevati nelle immagini. Rimuove qualsiasi evidenziazione precedente, quindi crea e visualizza i tag <p> per evidenziare ogni oggetto rilevato.

Testare l'app

Quando apporti modifiche al codice in CodePen, il riquadro di anteprima si aggiorna automaticamente al salvataggio. Se il salvataggio automatico è attivato, è probabile che l'app sia già stata aggiornata, ma è consigliabile aggiornarla di nuovo.

Per testare l'app:

  1. Nel riquadro di anteprima, fai clic su ogni immagine per visualizzare le previsioni. Un riquadro di delimitazione mostra il nome del cane con il livello di confidenza del modello.
  2. Se non è presente un riquadro di delimitazione, apri Chrome DevTools e controlla il riquadro Console per verificare la presenza di errori o rivedi i passaggi precedenti per assicurarti di non aver perso nulla.

Un&#39;anteprima dell&#39;app web con i riquadri di delimitazione sopra i cani rilevati nelle immagini

6. Eseguire previsioni su un video della webcam in diretta

Rilevare oggetti

  • Per rilevare gli oggetti in un video della webcam in diretta, vai alla funzione predictWebcam() e poi aggiungi il seguente codice al corpo della funzione:
// 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);

Il rilevamento di oggetti per i video utilizza gli stessi metodi, indipendentemente dal fatto che tu esegua l'inferenza sui dati di streaming o su un video completo. Il metodo detectForVideo() è simile al metodo detect() utilizzato per le foto, ma include un parametro aggiuntivo per il timestamp associato al frame corrente. La funzione esegue il rilevamento in diretta, quindi passi l'ora corrente come timestamp.

Elaborare e visualizzare le previsioni

  • Per elaborare e visualizzare i risultati del rilevamento, vai alla funzione displayVideoDetections() e poi aggiungi il seguente codice al corpo della funzione:
//  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);
  }
}

Questo codice rimuove qualsiasi evidenziazione precedente, quindi crea e visualizza i tag <p> per evidenziare ogni oggetto rilevato.

Testare l'app

Per testare il rilevamento di oggetti in diretta, è utile avere un'immagine di uno dei cani su cui è stato addestrato il modello.

Per testare l'app:

  1. Scarica una delle foto del cane sullo smartphone.
  2. Nel riquadro di anteprima, fai clic su Enable webcam (Attiva webcam).
  3. Se il browser mostra una finestra di dialogo che ti chiede di concedere l'accesso alla webcam, concedi l'autorizzazione.
  4. Tieni la foto del cane sullo smartphone di fronte alla webcam. Un riquadro di delimitazione mostra il nome del cane e il livello di confidenza del modello.
  5. Se non è presente un riquadro di delimitazione, apri Chrome DevTools e controlla il riquadro Console per verificare la presenza di errori o rivedi i passaggi precedenti per assicurarti di non aver perso nulla.

Un riquadro di delimitazione sopra un&#39;immagine di un cane mostrata a una webcam live

7. Complimenti

Complimenti! Hai creato un'app web che rileva gli oggetti nelle immagini. Per saperne di più, consulta una versione completa dell'app su CodePen.

Scopri di più