สร้างเว็บแอปตรวจจับออบเจ็กต์ที่กำหนดเองด้วย MediaPipe

1. ก่อนเริ่มต้น

โซลูชัน MediaPipe ช่วยให้คุณใช้โซลูชันแมชชีนเลิร์นนิง (ML) กับแอปได้ ซึ่งให้บริการเฟรมเวิร์กที่ช่วยให้คุณกําหนดค่าไปป์ไลน์การประมวลผลที่สร้างไว้ล่วงหน้าซึ่งจะแสดงผลลัพธ์ที่ดึงดูดใจและมีประโยชน์ต่อผู้ใช้ได้ทันที คุณยังปรับแต่งโซลูชันเหล่านี้ด้วย Model Maker เพื่ออัปเดตโมเดลเริ่มต้นได้ด้วย

การตรวจจับวัตถุเป็นหนึ่งในงานด้านวิสัยทัศน์ ML หลายอย่างที่ MediaPipe Solutions มีให้บริการ MediaPipe Tasks พร้อมใช้งานสำหรับ Android, Python และเว็บ

ใน Codelab นี้ คุณจะได้เพิ่มการตรวจจับวัตถุลงในเว็บแอปเพื่อตรวจหาสุนัขในรูปภาพและวิดีโอสดจากเว็บแคม

สิ่งที่คุณจะได้เรียนรู้

  • วิธีรวมงานการตรวจหาวัตถุในเว็บแอปด้วย MediaPipe Tasks

สิ่งที่คุณจะสร้าง

  • เว็บแอปที่ตรวจหาสุนัข นอกจากนี้ คุณยังปรับแต่งโมเดลให้ตรวจหาคลาสของวัตถุที่คุณต้องการได้ด้วย MediaPipe Model Maker

สิ่งที่คุณต้องมี

  • บัญชี CodePen
  • อุปกรณ์ที่มีเว็บเบราว์เซอร์
  • ความรู้พื้นฐานเกี่ยวกับ JavaScript, CSS และ HTML

2. ตั้งค่า

โค้ดแล็บนี้จะเรียกใช้โค้ดของคุณใน CodePen ซึ่งเป็นสภาพแวดล้อมการพัฒนาแบบโซเชียลที่ให้คุณเขียนโค้ดในเบราว์เซอร์และตรวจสอบผลลัพธ์ขณะสร้าง

ทำตามขั้นตอนต่อไปนี้เพื่อตั้งค่า

  1. ในบัญชี CodePen ให้ไปที่ CodePen นี้ คุณใช้โค้ดนี้เป็นพื้นฐานในการสร้างตัวตรวจจับวัตถุของคุณเอง
  2. คลิกแยกที่ด้านล่างของ CodePen ในเมนูการนำทางเพื่อทำสำเนาโค้ดเริ่มต้น

เมนูการนำทางใน CodePen ที่มีปุ่ม Fork

  1. ในแท็บ JS ให้คลิกลูกศรขยาย b15acb07e6357dce.png แล้วเลือกขยายเครื่องมือแก้ไข JavaScript สูงสุด คุณแก้ไขงานได้ในแท็บ JS เท่านั้นสำหรับโค้ดแล็บนี้ คุณจึงไม่ต้องดูแท็บ HTML หรือ CSS

ตรวจสอบแอปเริ่มต้น

  1. ในแผงแสดงตัวอย่าง คุณจะเห็นรูปสุนัข 2 ตัวและตัวเลือกให้เปิดเว็บแคม โมเดลที่คุณใช้ในบทแนะนำนี้ได้รับการฝึกด้วยสุนัข 3 ตัวที่แสดงใน 2 รูปภาพ

ตัวอย่างเว็บแอปจากโค้ดเริ่มต้น

  1. ในแท็บ JS ให้สังเกตว่ามีความคิดเห็นหลายรายการตลอดทั้งโค้ด เช่น คุณจะเห็นความคิดเห็นต่อไปนี้ในบรรทัด 15
// Import the required package.

ความคิดเห็นเหล่านี้ระบุตําแหน่งที่คุณจําเป็นต้องแทรกข้อมูลโค้ด

3. นําเข้าแพ็กเกจ tasks-vision ของ MediaPipe และเพิ่มตัวแปรที่จําเป็น

  1. ในแท็บ JS ให้นําเข้าแพ็กเกจ MediaPipe tasks-vision โดยทําดังนี้
// Import the required package.
​​import { ObjectDetector, FilesetResolver, Detection } from "https://cdn.skypack.dev/@mediapipe/tasks-vision@latest";

โค้ดนี้ใช้เครือข่ายนำส่งข้อมูล (CDN) ของ Skypack เพื่อนำเข้าแพ็กเกจ ดูข้อมูลเพิ่มเติมเกี่ยวกับวิธีใช้ Skypack กับ CodePen ได้ที่ Skypack + CodePen

ในโปรเจ็กต์ คุณสามารถใช้ Node.js กับ npm หรือเครื่องมือจัดการแพ็กเกจหรือ CDN ที่ต้องการ ดูข้อมูลเพิ่มเติมเกี่ยวกับแพ็กเกจที่จําเป็นซึ่งต้องติดตั้งได้ที่แพ็กเกจ JavaScript

  1. ประกาศตัวแปรสําหรับตัวตรวจจับวัตถุและโหมดการทํางาน
// Create required variables.
let objectDetector = null;
let runningMode = "IMAGE";

ตัวแปร runningMode คือสตริงที่ตั้งค่าเป็นค่า "IMAGE" เมื่อคุณตรวจหาวัตถุในรูปภาพ หรือค่า "VIDEO" เมื่อคุณตรวจหาวัตถุในวิดีโอ

4. เริ่มต้นตัวตรวจจับวัตถุ

  • หากต้องการเริ่มต้นโปรแกรมตรวจจับวัตถุ ให้เพิ่มโค้ดต่อไปนี้หลังความคิดเห็นที่เกี่ยวข้องในแท็บ 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();

เมธอด FilesetResolver.forVisionTasks() จะระบุตำแหน่งของไฟล์ไบนารี WebAssembly (Wasm) สำหรับงาน

เมธอด ObjectDetector.createFromOptions() จะสร้างอินสแตนซ์ของโปรแกรมตรวจจับวัตถุ คุณต้องระบุเส้นทางไปยังโมเดลที่ใช้สำหรับการตรวจจับ ในกรณีนี้ โมเดลการตรวจจับสุนัขจะโฮสต์อยู่ใน Cloud Storage

ตั้งค่าพร็อพเพอร์ตี้ scoreThreshold เป็นค่า 0.3 ซึ่งหมายความว่าโมเดลจะแสดงผลลัพธ์สำหรับวัตถุที่ตรวจพบซึ่งมีระดับความเชื่อมั่น 30% ขึ้นไป คุณปรับเกณฑ์นี้ให้เหมาะกับความต้องการของแอปได้

ระบบจะตั้งค่าพร็อพเพอร์ตี้ runningMode เมื่อเริ่มต้นออบเจ็กต์ ObjectDetector คุณเปลี่ยนตัวเลือกนี้และตัวเลือกอื่นๆ ได้ตามต้องการในภายหลัง

5. เรียกใช้การคาดคะเนในรูปภาพ

  • หากต้องการเรียกใช้การคาดการณ์ในรูปภาพ ให้ไปที่ฟังก์ชัน handleClick() แล้วเพิ่มโค้ดต่อไปนี้ลงในเนื้อหาของฟังก์ชัน
// 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 });
  }

โค้ดนี้จะกำหนดว่ามีการเริ่มต้นโปรแกรมตรวจจับวัตถุหรือไม่ และตรวจสอบว่าได้ตั้งค่าโหมดการทํางานสําหรับรูปภาพแล้ว

ตรวจหาวัตถุ

  • หากต้องการตรวจหาวัตถุในรูปภาพ ให้เพิ่มโค้ดต่อไปนี้ลงในเนื้อหาของฟังก์ชัน handleClick()
// Run object detection.
  const detections = objectDetector.detect(event.target);

ข้อมูลโค้ดต่อไปนี้เป็นตัวอย่างข้อมูลเอาต์พุตจากงานนี้

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

ประมวลผลและแสดงการคาดการณ์

  1. เรียกใช้ฟังก์ชัน displayImageDetections() ที่ท้ายเนื้อหาของฟังก์ชัน handleClick() ดังนี้
// Call the displayImageDetections() function.
displayImageDetections(detections, event.target);
  1. ในเนื้อหาของฟังก์ชัน displayImageDetections() ให้เพิ่มโค้ดต่อไปนี้เพื่อแสดงผลการจับวัตถุ
// 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);
  }

ฟังก์ชันนี้จะแสดงกล่องขอบเขตเหนือวัตถุที่ตรวจพบในรูปภาพ ซึ่งจะนําการไฮไลต์ก่อนหน้าออก จากนั้นสร้างและแสดงแท็ก <p> เพื่อไฮไลต์วัตถุแต่ละรายการที่ตรวจพบ

ทดสอบแอป

เมื่อคุณทำการเปลี่ยนแปลงโค้ดใน CodePen แผงแสดงตัวอย่างจะรีเฟรชโดยอัตโนมัติเมื่อบันทึก หากเปิดใช้การบันทึกอัตโนมัติ แอปของคุณน่าจะรีเฟรชแล้ว แต่คุณควรรีเฟรชอีกครั้ง

หากต้องการทดสอบแอป ให้ทำตามขั้นตอนต่อไปนี้

  1. ในแผงแสดงตัวอย่าง ให้คลิกรูปภาพแต่ละรูปเพื่อดูการคาดคะเน กล่องขอบเขตแสดงชื่อสุนัขพร้อมระดับความเชื่อมั่นของโมเดล
  2. หากไม่มีกล่องขอบ ให้เปิดเครื่องมือสำหรับนักพัฒนาเว็บใน Chrome แล้วตรวจสอบแผงคอนโซลเพื่อหาข้อผิดพลาด หรือตรวจสอบขั้นตอนก่อนหน้าเพื่อให้แน่ใจว่าคุณไม่ได้พลาดอะไรไป

ตัวอย่างเว็บแอปที่มีกล่องขอบเขตเหนือสุนัขที่ตรวจพบในรูปภาพ

6. เรียกใช้การคาดการณ์ในวิดีโอสดจากเว็บแคม

ตรวจหาวัตถุ

  • หากต้องการตรวจหาวัตถุในวิดีโอสดจากเว็บแคม ให้ไปที่ฟังก์ชัน predictWebcam() แล้วเพิ่มโค้ดต่อไปนี้ลงในเนื้อหาของฟังก์ชัน
// 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);

การตรวจจับวัตถุสำหรับวิดีโอจะใช้วิธีการเดียวกัน ไม่ว่าคุณจะทำการอนุมานกับข้อมูลสตรีมมิงหรือวิดีโอที่สมบูรณ์ เมธอด detectForVideo() คล้ายกับเมธอด detect() ที่ใช้กับรูปภาพ แต่จะมีพารามิเตอร์เพิ่มเติมสำหรับการประทับเวลาซึ่งเชื่อมโยงกับเฟรมปัจจุบัน ฟังก์ชันจะทำการค้นหาแบบเรียลไทม์ คุณจึงต้องส่งเวลาปัจจุบันเป็นการประทับเวลา

ประมวลผลและแสดงการคาดการณ์

  • หากต้องการประมวลผลและแสดงผลลัพธ์การตรวจจับ ให้ไปที่ฟังก์ชัน displayVideoDetections() แล้วเพิ่มโค้ดต่อไปนี้ลงในเนื้อหาของฟังก์ชัน
//  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);
  }
}

โค้ดนี้จะนําการไฮไลต์ก่อนหน้านี้ออก จากนั้นสร้างและแสดงแท็ก <p> เพื่อไฮไลต์วัตถุแต่ละรายการที่ตรวจพบ

ทดสอบแอป

หากต้องการทดสอบการตรวจจับวัตถุแบบเรียลไทม์ คุณควรมีรูปภาพสุนัขที่ใช้ในการฝึกโมเดล

หากต้องการทดสอบแอป ให้ทำตามขั้นตอนต่อไปนี้

  1. ดาวน์โหลดรูปสุนัข 1 รูปลงในโทรศัพท์
  2. ในช่องแสดงตัวอย่าง ให้คลิกเปิดใช้เว็บแคม
  3. หากเบราว์เซอร์แสดงกล่องโต้ตอบที่ขอให้คุณให้สิทธิ์เข้าถึงเว็บแคม ให้ให้สิทธิ์
  4. ถือรูปสุนัขในโทรศัพท์ไว้หน้าเว็บแคม กล่องขอบเขตจะแสดงชื่อสุนัขและระดับความเชื่อมั่นของโมเดล
  5. หากไม่มีกล่องขอบ ให้เปิดเครื่องมือสำหรับนักพัฒนาเว็บใน Chrome แล้วตรวจสอบแผงคอนโซลเพื่อหาข้อผิดพลาด หรือตรวจสอบขั้นตอนก่อนหน้าเพื่อให้แน่ใจว่าคุณไม่ได้พลาดอะไรไป

กล่องขอบเขตเหนือรูปภาพสุนัขที่ถือขึ้นให้กล้องเว็บแคมแบบสด

7. ขอแสดงความยินดี

ยินดีด้วย คุณสร้างเว็บแอปที่ตรวจหาวัตถุในรูปภาพ ดูข้อมูลเพิ่มเติมได้ที่แอปเวอร์ชันที่สมบูรณ์บน CodePen

ดูข้อมูลเพิ่มเติม