Tạo ứng dụng web phát hiện đối tượng tuỳ chỉnh bằng MediaPipe

1. Trước khi bắt đầu

MediaPipe Solutions giúp bạn áp dụng các giải pháp học máy (ML) cho các ứng dụng của mình. Thư viện này cung cấp một khung cho phép bạn định cấu hình các quy trình xử lý được tạo sẵn để cung cấp đầu ra tức thì, hấp dẫn và hữu ích cho người dùng. Bạn thậm chí có thể tuỳ chỉnh các giải pháp này bằng Model Maker để cập nhật các mô hình mặc định.

Phát hiện đối tượng là một trong nhiều nhiệm vụ liên quan đến thị giác học máy mà MediaPipe Solutions cung cấp. MediaPipe Tasks hỗ trợ Android, Python và web.

Trong lớp học lập trình này, bạn sẽ thêm tính năng phát hiện đối tượng vào một ứng dụng web để phát hiện chó trong hình ảnh và video webcam trực tiếp.

Kiến thức bạn sẽ học được

  • Cách kết hợp nhiệm vụ phát hiện đối tượng trong ứng dụng web với MediaPipe Tasks.

Sản phẩm bạn sẽ tạo ra

  • Ứng dụng web phát hiện sự hiện diện của chó. Bạn cũng có thể tuỳ chỉnh mô hình để phát hiện một lớp đối tượng mà bạn chọn bằng MediaPipe Model Maker.

Bạn cần có

  • Tài khoản CodePen
  • Một thiết bị có trình duyệt web
  • Kiến thức cơ bản về JavaScript, CSS và HTML

2. Bắt đầu thiết lập

Lớp học lập trình này chạy mã của bạn trong CodePen,một môi trường phát triển xã hội cho phép bạn viết mã trong trình duyệt và kiểm tra kết quả khi bạn tạo bản dựng.

Để thiết lập, hãy làm theo các bước sau:

  1. Trong tài khoản CodePen của bạn, hãy chuyển đến CodePen này. Bạn dùng mã này làm cơ sở để tạo trình phát hiện vật thể của riêng mình.
  2. Ở cuối CodePen trong trình đơn điều hướng, hãy nhấp vào Nĩa để tạo bản sao của mã khởi đầu.

Trình đơn điều hướng trong CodePen nơi có nút Fork

  1. Trong thẻ JS, hãy nhấp vào mũi tên mở rộng b15acb07e6357dce.png, sau đó chọn Tối đa hoá trình chỉnh sửa JavaScript. Bạn chỉ chỉnh sửa công việc trong thẻ JS của lớp học lập trình này, vì vậy, bạn không cần phải xem các thẻ HTML hoặc CSS.

Xem xét ứng dụng khởi đầu

  1. Trong ngăn xem trước, hãy chú ý rằng có hai hình ảnh những chú chó và một tuỳ chọn chạy webcam của bạn. Mô hình mà bạn dùng trong hướng dẫn này đã được huấn luyện dựa trên 3 chú chó xuất hiện trong 2 hình ảnh.

Bản xem trước ứng dụng web trong đoạn mã khởi đầu

  1. Trong thẻ JS, hãy lưu ý rằng có một số nhận xét xuyên suốt mã. Ví dụ: bạn có thể tìm thấy nhận xét sau trên dòng 15:
// Import the required package.

Các nhận xét này cho biết vị trí bạn cần chèn đoạn mã.

3. Nhập gói MediaPipe Tasks-vision và thêm các biến bắt buộc

  1. Trong thẻ JS, hãy nhập gói MediaPipe tasks-vision:
// Import the required package.
​​import { ObjectDetector, FilesetResolver, Detection } from "https://cdn.skypack.dev/@mediapipe/tasks-vision@latest";

Mã này sử dụng mạng phân phối nội dung (CDN) Skypack để nhập gói. Để biết thêm thông tin về cách sử dụng Skypack với CodePen, hãy xem Skypack + CodePen.

Trong các dự án của mình, bạn có thể sử dụng Node.js với npm hoặc trình quản lý gói hay CDN mà bạn chọn. Để biết thêm thông tin về gói bắt buộc mà bạn cần cài đặt, hãy xem gói JavaScript.

  1. Khai báo các biến cho trình phát hiện đối tượng và chế độ chạy:
// Create required variables.
let objectDetector = null;
let runningMode = "IMAGE";

Biến runningMode là một chuỗi được đặt thành giá trị "IMAGE" khi bạn phát hiện các đối tượng trong hình ảnh hoặc giá trị "VIDEO" khi bạn phát hiện các đối tượng trong video.

4. Khởi chạy trình phát hiện đối tượng

  • Để khởi chạy trình phát hiện đối tượng, hãy thêm mã sau vào sau nhận xét liên quan trong thẻ 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();

Phương thức FilesetResolver.forVisionTasks() chỉ định vị trí của tệp nhị phân WebAssembly (Wasm) cho tác vụ.

Phương thức ObjectDetector.createFromOptions() sẽ tạo thực thể cho trình phát hiện đối tượng. Bạn phải cung cấp đường dẫn đến mô hình được dùng để phát hiện. Trong trường hợp này, mô hình phát hiện chó được lưu trữ trên Cloud Storage.

Thuộc tính scoreThreshold được đặt thành giá trị 0.3. Điều này có nghĩa là mô hình sẽ trả về kết quả cho mọi đối tượng được phát hiện có mức độ tin cậy từ 30% trở lên. Bạn có thể điều chỉnh ngưỡng này cho phù hợp với nhu cầu của ứng dụng.

Thuộc tính runningMode được đặt khi khởi động đối tượng ObjectDetector. Sau này, bạn có thể thay đổi lựa chọn này và các lựa chọn khác nếu cần.

5. Chạy dự đoán trên hình ảnh

  • Để chạy dự đoán trên hình ảnh, hãy chuyển đến hàm handleClick() rồi thêm mã sau vào phần nội dung của hàm:
// 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 });
  }

Mã này xác định xem trình phát hiện đối tượng có được khởi chạy hay không và đảm bảo rằng chế độ đang chạy được đặt cho hình ảnh.

Phát hiện đối tượng

  • Để phát hiện đối tượng trong hình ảnh, hãy thêm mã sau vào phần nội dung của hàm handleClick():
// Run object detection.
  const detections = objectDetector.detect(event.target);

Đoạn mã sau đây cho thấy một ví dụ về dữ liệu đầu ra của tác vụ này:

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

Quy trình và hiển thị nội dung gợi ý

  1. Ở cuối phần nội dung của hàm handleClick(), hãy gọi hàm displayImageDetections():
// Call the displayImageDetections() function.
displayImageDetections(detections, event.target);
  1. Trong phần nội dung của hàm displayImageDetections(), hãy thêm mã sau để hiển thị kết quả phát hiện vật thể:
// 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);
  }

Hàm này cho thấy các hộp giới hạn trên các đối tượng phát hiện được trong hình ảnh. Thao tác này sẽ xoá mọi đối tượng được đánh dấu trước đó, sau đó tạo và hiển thị các thẻ <p> để đánh dấu từng đối tượng được phát hiện.

Kiểm thử ứng dụng

Khi bạn thay đổi mã trong CodePen, ngăn xem trước sẽ tự động làm mới sau khi lưu. Nếu tính năng lưu tự động được bật, ứng dụng của bạn có thể đã được làm mới, nhưng bạn nên làm mới lại.

Để kiểm thử ứng dụng, hãy làm theo các bước sau:

  1. Trong ngăn xem trước, hãy nhấp vào từng hình ảnh để xem gợi ý. Một hộp giới hạn hiển thị tên của chú chó cùng với mức độ tin cậy của mô hình.
  2. Nếu không có hộp giới hạn, hãy mở Công cụ của Chrome cho nhà phát triển, sau đó kiểm tra bảng điều khiển Bảng điều khiển để tìm lỗi hoặc xem lại các bước trước đó để đảm bảo rằng bạn không bỏ lỡ bất kỳ điều gì.

Bản xem trước ứng dụng web với các hộp giới hạn trên những chú chó được phát hiện trong hình ảnh

6. Chạy dự đoán trên video webcam trực tiếp

Phát hiện đối tượng

  • Để phát hiện đối tượng trong một video webcam trực tiếp, hãy chuyển đến hàm predictWebcam() rồi thêm mã sau vào phần nội dung của hàm:
// 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);

Tính năng phát hiện đối tượng cho video sử dụng cùng một phương pháp bất kể bạn chạy suy luận dựa trên dữ liệu truyền trực tuyến hay video hoàn chỉnh. Phương thức detectForVideo() tương tự như phương thức detect() dùng cho ảnh, nhưng có thêm một tham số bổ sung cho dấu thời gian liên kết với khung hình hiện tại. Hàm này thực hiện việc phát hiện trực tiếp, vì vậy, bạn chuyển thời gian hiện tại làm dấu thời gian.

Quy trình và hiển thị nội dung gợi ý

  • Để xử lý và hiển thị kết quả phát hiện, hãy chuyển đến hàm displayVideoDetections() rồi thêm mã sau vào phần nội dung của hàm:
//  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);
  }
}

Mã này sẽ xoá mọi đối tượng được đánh dấu trước đó, sau đó tạo và hiển thị các thẻ <p> để đánh dấu từng đối tượng được phát hiện.

Kiểm thử ứng dụng

Để kiểm tra tính năng phát hiện đối tượng trực tiếp, bạn nên có hình ảnh của một trong những chú chó mà mô hình được huấn luyện.

Để kiểm thử ứng dụng, hãy làm theo các bước sau:

  1. Tải một trong những bức ảnh về các chú chó xuống điện thoại của bạn.
  2. Trong ngăn xem trước, hãy nhấp vào Bật webcam.
  3. Nếu trình duyệt hiển thị một hộp thoại yêu cầu bạn cấp quyền truy cập vào webcam, hãy cấp quyền.
  4. Giữ ảnh chú chó trên điện thoại trước webcam. Một hộp giới hạn cho biết tên của chú chó và mức độ tin cậy của mô hình.
  5. Nếu không có hộp giới hạn, hãy mở Công cụ của Chrome cho nhà phát triển, sau đó kiểm tra bảng điều khiển Bảng điều khiển để tìm lỗi hoặc xem lại các bước trước đó để đảm bảo rằng bạn không bỏ lỡ bất kỳ điều gì.

Một chiếc hộp có ràng buộc phía trên hình ảnh một chú chó đang giữ cạnh một webcam đang hoạt động

7. Xin chúc mừng

Xin chúc mừng! Bạn đã xây dựng một ứng dụng web phát hiện các đối tượng trong hình ảnh. Để tìm hiểu thêm, hãy xem phiên bản hoàn chỉnh của ứng dụng trên CodePen.

Tìm hiểu thêm