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 di động mang chuyên môn về học máy trên thiết bị của Google vào các ứng dụng Android và iOS. Bạn có thể sử dụng các API mạnh mẽ nhưng dễ sử dụng như Vision và Natural Language để giải quyết những thách thức thường gặp trong ứng dụng hoặc tạo ra trải nghiệm hoàn toàn mới cho người dùng. Tất cả đều được hỗ trợ bởi các mô hình học máy (ML) tốt nhất của Google và được cung cấp miễn phí cho bạn.

Tất cả các API của Bộ công cụ máy học đều chạy trên thiết bị, cho phép các trường hợp sử dụng theo thời gian thực khi bạn muốn xử lý một luồng video của camera trực tiếp, chẳng hạn như vậy. Điều này cũng có nghĩa là bạn có thể sử dụng chức năng này 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 sẽ sử dụng một số lối tắt để làm nổi bật cách sử dụng ODT của 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 kết quả 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 của Bộ công cụ học máy

Bạn cần có

  • Một phiên bản Android Studio gần đây (từ phiên bản 4.1.2 trở lên)
  • Trình mô phỏng Android Studio hoặc thiết bị Android thực
  • Mã mẫu
  • Có kiến thức cơ bản về phát triển 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 tinh chỉnh và cung cấp cho bạn, chỉ cầ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 một thư mục gốc (mlkit-android-main) chứa tất cả tài nguyên bạn cần. Trong lớp học lập trình này, bạn sẽ chỉ cần các nguồn trong thư mục con object-detection.

Thư mục con object-detection trong kho lưu trữ mlkit-android chứa 2 thư mục:

  • android_studio_folder.pngstarter – Mã khởi đầu mà bạn sẽ xây dựng trong lớp học lập trình này.
  • android_studio_folder.pngfinal – Mã hoàn chỉnh cho ứng dụng mẫu đã hoàn tất.

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, etc.) (Nhập dự án (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 vào ứng dụng. 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 rằng tất cả các phần phụ thuộc đều có sẵn cho ứng dụng của bạn, bạn nên đồng bộ hoá dự án với các tệp gradle tại thời điểm này.

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

(Nếu nút này bị vô hiệu hoá, hãy nhớ chỉ nhập starter/app/build.gradle chứ không nhập 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 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) trong thanh công cụ của Android Studio.

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

Ứng dụng sẽ khởi chạy trên thiết bị Android của bạn. Ứng dụng 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 sẵn rồi đưa vào quy trình phát hiện và theo dõi đối tượng mà bạn sẽ tạo trong lớp học lập trình này. Hãy khám phá ứng dụng một chút trước khi viết mã.

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

  • mở ứng dụng camera được tích hợp trong thiết bị/trình mô phỏng
  • chụp ảnh trong ứng dụng camera
  • nhận hình ảnh đã chụp trong ứng dụng khởi đầu
  • hiển thị hình ảnh

Hãy thử 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 xuất hiện trong ứng dụng khởi đầu.

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

9ec541980dbe2d31.png 8312dde41425ba4b.png fa8492bfc1914ff0.png

Thứ hai, có 3 hình ảnh đặt sẵn mà bạn có thể chọn. Sau này, bạn có thể dùng những hình ảnh này để 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 sẵn. Kiểm tra để đảm bảo hình ảnh xuất hiện ở chế độ xem lớn hơn:

1dd41b3ec978f1d9.png

5. Thêm tính năng phát hiện vật thể trên thiết bị

Trong bước này, bạn sẽ thêm chức năng phát hiện đối tượng trong hình ảnh vào ứng dụng khởi đầu. Như bạn thấy ở 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ó 3 hình ảnh đặt sẵn trong ứng dụng mà bạn có thể thử 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 một trình mô phỏng Android.

Khi bạn chọn một hình ảnh (từ các hình ảnh đặt sẵn 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 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 để thực hiện tính năng 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ị đối với một hình ảnh

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

  • chuẩn bị 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 đạ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. Chuyển sang các bước sau để triển khai ODT của Bộ công cụ học máy! Trong quá trình này, 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 một 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ể truyền một InputImage vào 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ế trình tạo. Bạn sẽ truyền cấu hình đến trình tạo, sau đó lấy một detector (trình phát hiện) từ trình tạo đó. Có 3 lựa chọn để định cấu hình (các lựa chọn được in đậm sẽ được dùng trong lớp học lập trình này):

  • chế độ 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 vật thể)
  • chế độ phân loại (bật hoặc tắt)

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

// 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: Truyền(các) hình ảnh vào bộ phát hiện

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

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

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, bộ phát hiện sẽ thông báo cho bạn bằng:

  • Tổng số đối tượng được phát hiện. Mỗi đối tượng được phát hiện đều được mô tả bằng:
  • trackingId: một số nguyên mà bạn dùng để theo dõi trên các khung hình (KHÔNG 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 bạn bật tính năng phân loại):
  • 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", "Hàng gia dụng", "Địa điểm", "Thực vật")
  • confidence ( một số thực có độ chính xác đơn từ 0,0 đến 1,0, trong đó 1,0 có nghĩa là 100%)

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

Thêm mã 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}")
       }
   }
}

Giờ đây, bạn đã sẵn sàng 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 Run (Chạy) (execute.png) trong thanh công cụ của Android Studio. Hãy thử chọn một hình ảnh đặt sẵn hoặc chụp ảnh, sau đó xem cửa sổ logcat( 16bd6ea224cf8cf1.png) bên trong IDE.

Bạn sẽ thấy nội dung 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

...điều này có nghĩa là trình phát hiện đã nhìn thấy 3 đối tượng:

  • Các danh mục là Thực phẩmĐồ gia dụng.
  • Không có danh mục nào được trả về cho danh mục thứ 2 vì đây là một loại 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))
  • Công cụ phát hiện khá chắc chắn rằng hình ảnh thứ nhất là Thực phẩm (độ tin cậy 90% – đó là món salad).

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

Về phía giao diện người dùng, bạn vẫn ở giai đoạn bắt đầu, nhưng bạn có thể tận dụng các kết quả được phát hiện trên giao diện người dùng, chẳng hạn như vẽ ra khung hình chữ nhật để 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ả được phát hiện!

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 vào 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à độ tin cậy bên trong khung hình chữ nhật

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

Có một số mã nguyên mẫu trong lớp học lập trình này để giúp bạn hình dung 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á:

  • data class BoxWithText(val box: Rect, val text: String) Đây là một lớp dữ liệu để lưu trữ kết quả phát hiện đối tượng nhằm mục đích trực quan hoá. box là khung hình chữ nhật nơi đối tượng nằm và text là chuỗi kết quả phát hiện để hiển thị cùng với khung hình chữ nhật 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 bitmap đầu vào và trả về bản sao đã sửa đổi của kết quả đó.

Sau đây là ví dụ về kết quả của phương thức tiện ích drawDetectionResult:

58c6f1d4ddb00dfa.png

Trực quan hoá kết quả phát hiện của 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() rồi 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 một danh sách các đố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 trên hình ảnh đầu vào bằng phương thức tiện ích drawDetectionResult và 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 Chạy ( execute.png) trong thanh công cụ của Android Studio.

Sau khi ứng dụng tải xong, hãy nhấn vào Nút có biểu tượng camera, hướng camera vào một vật thể, 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 sẵn nào. Bạn sẽ thấy kết quả phát hiện; hãy nhấn lại vào Nút hoặc chọn một hình ảnh khác để lặp lại vài lần nhằm 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 đã sử 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 công cụ phát hiện

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

Khi tiếp tục, bạn có thể muốn cải thiện mô hình: như bạn có thể thấy, 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 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 sử dụng tính năng phát hiện và theo dõi 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

Các bước tiếp theo

  • Khám phá thêm với ODT của Bộ công cụ học máy bằng nhiều hình ảnh và video trực tiếp hơn để trải nghiệm độ chính xác và hiệu suất của tính năng phát hiện và phân loại
  • Hãy xem lộ trình học tập Phát hiện vật thể trong phần Học máy trên thiết bị để tìm hiểu cách huấn luyện một mô hình tuỳ chỉnh
  • Áp dụng tính nă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