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

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

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

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

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

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

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

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

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

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

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

2. ตั้งค่า

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

หากต้องการตั้งค่า ให้ทำตามขั้นตอนต่อไปนี้

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

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

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

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

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

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

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

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

3. นำเข้าแพ็กเกจ MediaPipe Tasks Vision และเพิ่มตัวแปรที่จำเป็น

  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. เริ่มต้นตัวตรวจหาออบเจ็กต์

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

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

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

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

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