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

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

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

การตรวจจับออบเจ็กต์เป็นหนึ่งในงานด้านการมองเห็น ML หลายรายการที่โซลูชัน MediaPipe มีให้ MediaPipe Tasks พร้อมใช้งานใน Android, Python และเว็บ

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

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

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

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

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

สิ่งที่ต้องมี

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

2. ตั้งค่า

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

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

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

เมนูการนำทางใน CodePen ที่มีปุ่ม "แยก" อยู่

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

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

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

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

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

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

3. นำเข้าแพ็กเกจงาน 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, Package Manager หรือ 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. ที่ตอนท้ายของส่วนเนื้อหาของฟังก์ชัน handleClick() ให้เรียกฟังก์ชัน displayImageDetections() ดังนี้
// 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. ดาวน์โหลดรูปสุนัขลงในโทรศัพท์
  2. ในแผงแสดงตัวอย่าง ให้คลิกเปิดใช้เว็บแคม
  3. หากเบราว์เซอร์แสดงกล่องโต้ตอบที่ขอให้คุณให้สิทธิ์เข้าถึงเว็บแคม โปรดให้สิทธิ์
  4. ถือภาพสุนัขในโทรศัพท์หน้าเว็บแคม กรอบล้อมรอบจะแสดงชื่อของสุนัขและระดับความมั่นใจของโมเดลนั้น
  5. หากไม่มีกรอบล้อมรอบ ให้เปิดเครื่องมือสำหรับนักพัฒนาเว็บใน Chrome แล้วตรวจสอบข้อผิดพลาดที่แผงคอนโซลหรือตรวจสอบขั้นตอนก่อนหน้านี้เพื่อให้แน่ใจว่าคุณไม่พลาดข้อมูลใดไป

กล่องล้อมรอบภาพสุนัขที่กำลังชูเว็บแคมสด

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

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

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