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

Giải pháp MediaPipe cho phép bạn áp dụng các giải pháp học máy (ML) cho ứ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 quy trình xử lý tạo sẵn để cung cấp kết quả 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 Trình tạo mô hình để cập nhật các mô hình mặc định.

Phát hiện đối tượng là một trong số các nhiệm vụ thị giác máy học mà MediaPipe Solutions cung cấp. MediaPipe Tasks có sẵn cho 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 trực tiếp từ webcam.

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

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

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

  • Một ứ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ột mô hình để phát hiện một lớp đối tượng mà bạn chọn bằng Trình tạo mô hình MediaPipe.

Bạn cần có

  • Tài khoản CodePen
  • 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 tạo.

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

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

Trình đơn điều hướng trong CodePen, nơi có nút Fork (Tách)

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

Xem lại ứng dụng khởi động

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

Bản xem trước ứng dụng web từ mã khởi động

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

Những 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 tasks-vision của MediaPipe 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 phần Skypack + CodePen.

Trong dự án, bạn có thể sử dụng Node.js với npm hoặc trình quản lý gói hoặc 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 phần Gói JavaScript.

  1. Khai báo 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 đối tượng trong hình ảnh hoặc giá trị "VIDEO" khi bạn phát hiện đố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 phần chú thích có 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() tạo bản sao cho trình phát hiện đối tượng. Bạn phải cung cấp đường dẫn đến mô hình 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 tạo đối tượng ObjectDetector. 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 sau này.

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

  • Để chạy tính năng 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ế độ 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 thân của hàm handleClick():
// Run object detection.
  const detections = objectDetector.detect(event.target);

Đoạn mã sau đây bao gồm 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

Xử lý và hiển thị kết quả dự đoán

  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 đối tượng:
// 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 hiển thị các hộp giới hạn trên các đối tượng được phát hiện trong hình ảnh. Phương thức này xoá mọi phần được làm nổi bật trước đó, sau đó tạo và hiển thị các thẻ <p> để làm nổi bật từng đối tượng được phát hiện.

Kiểm thử ứng dụng

Khi bạn thực hiện thay đổi đối với mã trong CodePen, ngăn xem trước sẽ tự động làm mới khi lưu. Nếu bạn đã bật tính năng tự động lưu, thì ứ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 kết quả dự đoán. 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 Console (Bảng điều khiển) để tìm lỗi hoặc xem lại các bước trước đó để đảm bảo bạn không bỏ lỡ điều gì.

Bản xem trước ứng dụng web 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 tính năng dự đoán trên video trực tiếp từ webcam

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

  • Để phát hiện đối tượng trong video trực tiếp từ webcam, hãy chuyển đến hàm predictWebcam(), sau đó thêm mã sau vào phần thân 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ác phương thức tương tự, bất kể bạn chạy quy trình suy luận trên dữ liệu phát 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 thông số 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 sẽ truyền thời gian hiện tại làm dấu thời gian.

Xử lý và hiển thị kết quả dự đoán

  • Để xử lý và hiển thị kết quả phát hiện, hãy chuyển đến hàm displayVideoDetections(), sau đó thêm mã sau vào phần thân 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 xoá mọi nội dung làm nổi bật trước đó, sau đó tạo và hiển thị các thẻ <p> để làm nổi bật từng đối tượng được phát hiện.

Kiểm thử ứng dụng

Để kiểm thử tính năng phát hiện vật thể trong thực tế, bạn cầ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 các ảnh chó xuống điện thoại.
  2. Trong ngăn xem trước, hãy nhấp vào Bật webcam.
  3. Nếu trình duyệt của bạn hiển thị 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. Hộp giới hạn hiển thị 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 Console (Bảng điều khiển) để tìm lỗi hoặc xem lại các bước trước đó để đảm bảo bạn không bỏ lỡ điều gì.

Hộp giới hạn trên hình ảnh một chú chó được đưa lên webcam trực tiếp

7. Xin chúc mừng

Xin chúc mừng! Bạn đã tạo một ứng dụng web phát hiện đố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