Phát hiện đối tượng trong hình ảnh bằng Bộ công cụ học máy: Android

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

Bộ công cụ học máy là một SDK dành cho thiết bị di động, đưa kiến thức chuyên môn về công nghệ học máy trên thiết bị của Google vào các ứng dụng dành cho Android và iOS. Bạn có thể dùng các API Vision và Natural Language API mạnh mẽ mà đơn giản để giải quyết những thách thức thường gặp trong ứng dụng của mình hoặc tạo ra những trải nghiệm người dùng hoàn toàn mới. Tất cả đều sử dụng mô hình học máy hàng đầu của Google và được cung cấp miễn phí cho bạn.

Các API của Bộ công cụ học máy đều chạy trên thiết bị, chẳng hạn như cho phép sử dụng theo thời gian thực khi bạn muốn xử lý một luồng camera trực tiếp. Điều này cũng có nghĩa là chức năng này có thể sử dụng khi không có mạng.

Lớp học lập trình này sẽ hướng dẫn bạn các bước đơn giản để thêm tính năng Phát hiện và theo dõi đối tượng (ODT) cho một hình ảnh nhất định vào ứng dụng Android hiện có. Xin lưu ý rằng lớp học lập trình này cần một số lối tắt để làm nổi bật mức sử dụng ODT cho Bộ công cụ học máy.

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

Trong lớp học lập trình này, bạn sẽ xây dựng một ứng dụng Android bằng Bộ công cụ học máy. Ứng dụng của bạn sẽ sử dụng API Phát hiện và theo dõi đối tượng của Bộ công cụ học máy để phát hiện các đối tượng trong một hình ảnh nhất định.Cuối cùng, bạn sẽ thấy nội dung tương tự như hình ảnh ở bên phải.

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

  • Cách tích hợp SDK Bộ công cụ học máy vào ứng dụng Android
  • API Phát hiện và theo dõi đối tượng trong bộ công cụ học máy

Bạn cần có

  • Phiên bản Android Studio gần đây (v4.1.2 trở lên)
  • Trình mô phỏng Android Studio hoặc thiết bị Android thực
  • Mã mẫu
  • Kiến thức cơ bản về cách phát triển cho Android bằng Kotlin

Lớp học lập trình này tập trung vào Bộ công cụ học máy. Các khái niệm và khối mã không liên quan được che khuất và chỉ được cung cấp cho bạn để sao chép và dán.

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

Tải mã nguồn xuống

Nhấp vào đường liên kết sau đây để tải toàn bộ mã nguồn cho lớp học lập trình này:

Giải nén tệp zip đã tải xuống. Thao tác này sẽ giải nén thư mục gốc (mlkit-android-main) cùng với tất cả tài nguyên bạn cần. Đối với lớp học lập trình này, bạn chỉ cần có các nguồn trong thư mục con object-detection.

Thư mục con phát hiện đối tượng trong kho lưu trữ mlkit-android chứa hai thư mục:

  • android_studio_folder.pngstarter (khởi đầu) – Mã khởi đầu mà bạn dùng để xây dựng cho lớp học lập trình này.
  • android_studio_folder.pnghoàn thiện – Mã đã hoàn tất cho ứng dụng mẫu hoàn chỉnh.

3. Thêm API Phát hiện và theo dõi đối tượng của bộ công cụ học máy vào dự án

Nhập ứng dụng vào Android Studio

Hãy bắt đầu bằng cách nhập ứng dụng khởi đầu vào Android Studio.

Mở Android Studio, chọn Import Project (Gradle, Eclipse ADT, v.v.) rồi chọn thư mục starter trong mã nguồn mà bạn đã tải xuống trước đó.

7c0f27882a2698ac.png.

Thêm các phần phụ thuộc cho tính năng Phát hiện và theo dõi đối tượng của Bộ công cụ học máy

Các phần phụ thuộc của Bộ công cụ học máy cho phép bạn tích hợp SDK ODT của Bộ công cụ học máy trong ứng dụng của mình. Hãy thêm các dòng sau vào cuối tệp app/build.gradle của dự án:

build.gradle

dependencies {
  // ...
  implementation 'com.google.mlkit:object-detection:16.2.4'
}

Đồng bộ hoá dự án với các tệp gradle

Để đảm bảo tất cả phần phụ thuộc đều dùng được cho ứng dụng, bạn nên đồng bộ hoá dự án với các tệp gradle.

Chọn Sync Project with Gradle Files (Đồng bộ hoá dự án với tệp Gradle) (b451ab2d04d835f9.png) trên thanh công cụ Android Studio.

(Nếu nút này bị tắt, hãy đảm bảo rằng bạn chỉ nhập starter/app/build.gradle , chứ không phải toàn bộ kho lưu trữ.)

4. Chạy ứng dụng khởi đầu

Giờ đây, sau khi nhập dự án vào Android Studio và thêm các phần phụ thuộc cho tính năng Phát hiện và theo dõi đối tượng của bộ công cụ học máy, bạn đã sẵn sàng chạy ứng dụng này lần đầu tiên.

Kết nối thiết bị Android với máy chủ lưu trữ qua USB hoặc Khởi động trình mô phỏng Android Studio rồi nhấp vào Chạy ( execute.png) trên thanh công cụ Android Studio.

Chạy và khám phá ứng dụng

Ứng dụng sẽ chạy trên thiết bị Android của bạn. Lớp học này có một số mã nguyên mẫu để cho phép bạn chụp ảnh hoặc chọn một hình ảnh đặt trước, sau đó cấp dữ liệu vào một quy trình phát hiện và theo dõi đối tượng mà bạn sẽ xây dựng trong lớp học lập trình này. Hãy khám phá một chút về ứng dụng trước khi viết mã.

Đầu tiên, có một Nút ( c6d965d639c3646.png) ở dưới cùng để:

  • hiển thị ứng dụng máy ảnh được tích hợp trong thiết bị/trình mô phỏng của bạn
  • chụp ảnh bên trong ứng dụng máy ảnh
  • nhận hình ảnh đã chụp trong ứng dụng khởi động
  • hiển thị hình ảnh

Hãy thử dùng nút Chụp ảnh, làm theo lời nhắc để chụp ảnh, chấp nhận ảnh và quan sát ảnh hiển thị bên trong ứng dụng khởi động.

Lặp lại vài lần để xem cách hoạt động:

9ec541980dbe2d31.pngs 8312dde41425ba4b.png. fa8492bfc1914ff0.png

Thứ hai, có 3 hình ảnh đặt trước để bạn chọn. Bạn có thể sử dụng những hình ảnh này vào lúc khác để kiểm thử mã phát hiện đối tượng nếu đang chạy trên trình mô phỏng Android.

Chọn một hình ảnh trong số 3 hình ảnh đặt trước. Xem hình ảnh hiển thị ở chế độ xem lớn hơn:

1dd41b3ec978f1d9.pngS

5. Thêm tính năng phát hiện đối tượng trên thiết bị

Ở bước này, bạn sẽ thêm chức năng vào ứng dụng khởi đầu để phát hiện các đối tượng trong hình ảnh. Như bạn đã thấy trong bước trước, ứng dụng khởi đầu chứa mã nguyên mẫu để chụp ảnh bằng ứng dụng máy ảnh trên thiết bị. Ngoài ra, còn có 3 hình ảnh đặt trước trong ứng dụng mà bạn có thể thử dùng tính năng phát hiện đối tượng nếu đang chạy lớp học lập trình trên trình mô phỏng Android.

Khi bạn chọn hình ảnh, từ các hình ảnh đặt trước hoặc chụp ảnh bằng ứng dụng máy ảnh, mã nguyên mẫu sẽ giải mã hình ảnh đó thành một thực thể Bitmap, hiển thị hình ảnh trên màn hình và gọi phương thức runObjectDetection bằng hình ảnh.

Trong bước này, bạn sẽ thêm mã vào phương thức runObjectDetection để phát hiện đối tượng!

Thiết lập và chạy tính năng phát hiện đối tượng trên thiết bị cho một hình ảnh

Chỉ có 3 bước đơn giản với 3 API để thiết lập ODT cho Bộ công cụ học máy:

  • chuẩn bị một hình ảnh: InputImage
  • tạo một đối tượng trình phát hiện: ObjectDetection.getClient(options)
  • kết nối 2 đối tượng ở trên: process(image)

Bạn sẽ đạt được những điều này bên trong hàm runObjectDetection(bitmap: Bitmap) trong tệp MainActivity.kt.

/**
 * ML Kit Object Detection Function
 */
private fun runObjectDetection(bitmap: Bitmap) {
}

Hiện tại, hàm này đang trống. Hãy chuyển sang các bước sau để triển khai ODT cho bộ công cụ học máy! Đồng thời, Android Studio sẽ nhắc bạn thêm các lệnh nhập cần thiết:

  • com.google.mlkit.vision.common.InputImage
  • com.google.mlkit.vision.objects.ObjectDetection
  • com.google.mlkit.vision.objects.defaults.ObjectDetectorOptions

Bước 1: Tạo InputImage

Bộ công cụ học máy cung cấp một API đơn giản để tạo InputImage từ Bitmap. Sau đó, bạn có thể cấp InputImage cho các API của Bộ công cụ học máy.

// Step 1: create ML Kit's InputImage object
val image = InputImage.fromBitmap(bitmap, 0)

Thêm mã ở trên vào đầu runObjectDetection(bitmap:Bitmap).

Bước 2: Tạo một thực thể của trình phát hiện

Bộ công cụ học máy tuân theo Mẫu thiết kế dành cho trình tạo bản dựng. Bạn sẽ truyền cấu hình này đến trình tạo, sau đó có được trình phát hiện từ trình tạo đó. Có 3 cách định cấu hình (các tuỳ chọn ở dạng in đậm được sử dụng trong lớp học lập trình này):

  • chế độ trình phát hiện (một hình ảnh hoặc luồng)
  • chế độ phát hiện (phát hiện một hoặc nhiều đối tượng)
  • chế độ phân loại (bật hoặc tắt)

Lớp học lập trình này dành cho một hình ảnh – phát hiện nhiều đối tượng và của bạn. Thêm ngay bây giờ:

// Step 2: acquire detector object
val options = ObjectDetectorOptions.Builder()
   .setDetectorMode(ObjectDetectorOptions.SINGLE_IMAGE_MODE)
   .enableMultipleObjects()
   .enableClassification()
   .build()
val objectDetector = ObjectDetection.getClient(options)

Bước 3: Cung cấp(các) hình ảnh cho trình phát hiện

Tính năng phát hiện và phân loại đối tượng là quá trình xử lý không đồng bộ:

  • Bạn gửi hình ảnh tới trình phát hiện (qua process()).
  • Trình phát hiện hoạt động khá khó khăn.
  • Trình phát hiện sẽ báo cáo kết quả lại cho bạn thông qua lệnh gọi lại.

Đoạn mã sau đây sẽ thực hiện việc đó (sao chép và thêm mã này vào mã hiện có bên trong fun runObjectDetection(bitmap:Bitmap)):

// Step 3: feed given image to detector and setup callback
objectDetector.process(image)
   .addOnSuccessListener {
       // Task completed successfully
        debugPrint(it)
   }
   .addOnFailureListener {
       // Task failed with an exception
       Log.e(TAG, it.message.toString())
   }

Sau khi hoàn tất, trình phát hiện sẽ thông báo cho bạn với:

  • Tổng số đối tượng được phát hiện. Mỗi đối tượng phát hiện được sẽ được mô tả bằng:
  • trackingId: một số nguyên bạn dùng để theo dõi trong các khung (KHÔNG được sử dụng trong lớp học lập trình này).
  • boundingBox: hộp giới hạn của đối tượng.
  • labels: danh sách(các) nhãn cho đối tượng được phát hiện (chỉ khi tính năng phân loại được bật):
  • index (Lấy chỉ mục của nhãn này)
  • text (Lấy văn bản của nhãn này, bao gồm "Hàng thời trang", "Thực phẩm", "Đồ gia dụng", "Địa điểm", "Thực vật")
  • confidence ( số thực từ 0,0 đến 1,0 với 1,0 có nghĩa là 100%)

Bạn có thể nhận thấy mã thực hiện loại xử lý printf cho kết quả phát hiện được bằng debugPrint().

Thêm phương thức này vào lớp MainActivity:

private fun debugPrint(detectedObjects: List<DetectedObject>) {
   detectedObjects.forEachIndexed { index, detectedObject ->
       val box = detectedObject.boundingBox

       Log.d(TAG, "Detected object: $index")
       Log.d(TAG, " trackingId: ${detectedObject.trackingId}")
       Log.d(TAG, " boundingBox: (${box.left}, ${box.top}) - (${box.right},${box.bottom})")
       detectedObject.labels.forEach {
           Log.d(TAG, " categories: ${it.text}")
           Log.d(TAG, " confidence: ${it.confidence}")
       }
   }
}

Bây giờ, bạn có thể chấp nhận hình ảnh để phát hiện!

Hãy chạy lớp học lập trình này bằng cách nhấp vào biểu tượng Chạy ( execute.png) trên thanh công cụ Android Studio. Hãy thử chọn một hình ảnh đặt trước hoặc chụp ảnh, sau đó xem cửa sổ logcat( 16bd6ea224cf8cf1.png.) bên trong IDE.

Bạn sẽ thấy mã tương tự như sau:

D/MLKit Object Detection: Detected object: 0
D/MLKit Object Detection:  trackingId: null
D/MLKit Object Detection:  boundingBox: (481, 2021) - (2426,3376)
D/MLKit Object Detection:  categories: Food
D/MLKit Object Detection:  confidence: 0.90234375
D/MLKit Object Detection: Detected object: 1
D/MLKit Object Detection:  trackingId: null
D/MLKit Object Detection:  boundingBox: (2639, 2633) - (3058,3577)
D/MLKit Object Detection: Detected object: 2
D/MLKit Object Detection:  trackingId: null
D/MLKit Object Detection:  boundingBox: (3, 1816) - (615,2597)
D/MLKit Object Detection:  categories: Home good
D/MLKit Object Detection:  confidence: 0.75390625

...có nghĩa là máy phát hiện thấy 3 vật thể:

  • Danh mục là Thực phẩmĐồ dùng gia đình.
  • Không có danh mục nào được trả về cho lớp thứ 2 vì đây là lớp không xác định.
  • Không có trackingId (vì đây là chế độ phát hiện một hình ảnh).
  • Vị trí bên trong hình chữ nhật boundingBox (ví dụ: (481, 2021) – (2426, 3376))
  • Trình phát hiện khá tự tin rằng thứ nhất là Thực phẩm (độ tin cậy 90% — đó là rau trộn).

Về mặt kỹ thuật, đó là tất cả những gì bạn cần để tính năng Phát hiện đối tượng của bộ công cụ học máy hoạt động: hiện tại bạn đã có tất cả! Xin chúc mừng!

Về phía giao diện người dùng, bạn vẫn đang ở giai đoạn khi bắt đầu, nhưng bạn có thể tận dụng các kết quả phát hiện được trên giao diện người dùng, chẳng hạn như vẽ hộp giới hạn để tạo trải nghiệm tốt hơn: hãy chuyển sang bước tiếp theo – xử lý hậu kỳ các kết quả phát hiện được!

6. Xử lý hậu kỳ kết quả phát hiện

Trong các bước trước, bạn in kết quả phát hiện được ra dạng logcat: đơn giản và nhanh chóng.

Trong phần này, bạn sẽ sử dụng kết quả vào hình ảnh:

  • vẽ hộp giới hạn trên hình ảnh
  • vẽ tên danh mục và mức độ tin cậy bên trong hộp giới hạn

Tìm hiểu các tiện ích trực quan hoá

Có một số mã nguyên mẫu bên trong lớp học lập trình để giúp bạn trực quan hoá kết quả phát hiện. Tận dụng các tiện ích này để đơn giản hoá mã trực quan hoá của chúng tôi:

  • data class BoxWithText(val box: Rect, val text: String) Đây là lớp dữ liệu dùng để lưu trữ kết quả phát hiện đối tượng cho mục đích trực quan hoá. box là hộp giới hạn nơi đối tượng định vị và text là chuỗi kết quả phát hiện sẽ hiển thị cùng với hộp giới hạn của đối tượng.
  • fun drawDetectionResult(bitmap: Bitmap, detectionResults: List<BoxWithText>): Bitmap Phương thức này vẽ kết quả phát hiện đối tượng trong detectionResults trên dữ liệu đầu vào bitmap rồi trả về bản sao đã sửa đổi.

Dưới đây là ví dụ về kết quả của phương thức hiệu dụng drawDetectionResult:

58c6f1d4ddb00dfa.png.

Trực quan hoá kết quả phát hiện Bộ công cụ học máy

Sử dụng các tiện ích trực quan hoá để vẽ kết quả phát hiện đối tượng của Bộ công cụ học máy lên trên hình ảnh đầu vào.

Chuyển đến nơi bạn gọi debugPrint() và thêm đoạn mã sau bên dưới:

// Parse ML Kit's DetectedObject and create corresponding visualization data
val detectedObjects = it.map { obj ->
    var text = "Unknown"

    // We will show the top confident detection result if it exist
    if (obj.labels.isNotEmpty()) {
        val firstLabel = obj.labels.first()
        text = "${firstLabel.text}, ${firstLabel.confidence.times(100).toInt()}%"
    }
    BoxWithText(obj.boundingBox, text)
}

// Draw the detection result on the input bitmap
val visualizedResult = drawDetectionResult(bitmap, detectedObjects)

// Show the detection result on the app screen
runOnUiThread {
    inputImageView.setImageBitmap(visualizedResult)
}
  • Bạn bắt đầu bằng cách phân tích cú pháp DetectedObject của Bộ công cụ học máy và tạo danh sách đối tượng BoxWithText để hiển thị kết quả trực quan.
  • Sau đó, bạn vẽ kết quả phát hiện lên hình ảnh đầu vào bằng cách sử dụng phương thức tiện ích drawDetectionResult rồi hiển thị kết quả đó trên màn hình.

Chạy ứng dụng

Bây giờ, hãy nhấp vào biểu tượng Run (Chạy) (execute.png) trên thanh công cụ Android Studio.

Sau khi ứng dụng tải xong, hãy nhấn Nút có biểu tượng máy ảnh, hướng máy ảnh vào một đối tượng, chụp ảnh, chấp nhận ảnh (trong Ứng dụng máy ảnh) hoặc bạn có thể dễ dàng nhấn vào bất kỳ hình ảnh đặt trước nào. Bạn sẽ thấy kết quả phát hiện; nhấn lại Nút hoặc chọn một hình ảnh khác để lặp lại vài lần để trải nghiệm ODT mới nhất của Bộ công cụ học máy!

a03109cb30d5014d.png

7. Xin chúc mừng!

Bạn đã dùng Bộ công cụ học máy để thêm các chức năng Phát hiện đối tượng vào ứng dụng của mình:

  • 3 bước với 3 API
  • Tạo hình ảnh đầu vào
  • Tạo trình phát hiện
  • Gửi hình ảnh đến trình phát hiện

Đó là tất cả những gì bạn cần để thiết lập và chạy chiến dịch!

Khi tiếp tục, bạn có thể muốn cải tiến mô hình: như bạn có thể thấy rằng mô hình mặc định chỉ có thể nhận dạng 5 danh mục – mô hình thậm chí không biết đến dao, nĩa và chai. Hãy tham khảo lớp học lập trình khác trong Lộ trình học tập về Học máy trên thiết bị – Phát hiện đối tượng để tìm hiểu cách huấn luyện một mô hình tuỳ chỉnh.

Nội dung đã đề cập

  • Cách thêm tính năng Phát hiện và theo dõi đối tượng của bộ công cụ học máy vào ứng dụng Android
  • Cách dùng tính năng theo dõi và phát hiện vật thể trên thiết bị trong Bộ công cụ học máy để phát hiện vật thể trong hình ảnh

Bước tiếp theo

  • Khám phá thêm bằng ODT của Bộ công cụ học máy với nhiều hình ảnh và video trực tiếp hơn để trải nghiệm khả năng phát hiện và độ chính xác và hiệu suất của hoạt động phân loại
  • Xem công cụ Học máy trên thiết bị – Lộ trình học tập về Phát hiện đối tượng để tìm hiểu cách huấn luyện một mô hình tuỳ chỉnh
  • Áp dụng ODT của Bộ công cụ học máy trong ứng dụng Android của riêng bạn

Tìm hiểu thêm