Android 圖片區隔指南

MediaPipe 圖片區隔工作可讓您根據預先定義的類別,將圖片分為不同的區域,以便套用背景模糊效果等視覺效果。以下操作說明將說明如何搭配使用圖片區隔與 Android 應用程式。如需這些操作說明中提及的程式碼範例,請前往 GitHub。如要進一步瞭解這項工作的功能、模型和設定選項,請參閱總覽

程式碼範例

MediaPipe Tasks 程式碼範例包含兩個適用於 Android 圖片區隔應用程式的簡易實作方式:

這些範例使用實體 Android 裝置的相機,對即時攝影機畫面執行圖片區隔,或從裝置圖片庫中選擇圖片和影片。您可以將這些應用程式做為建構 Android 應用程式的起點,或在修改現有應用程式時參照這些應用程式。圖片區隔範例程式碼由 GitHub 代管。

以下各節將介紹具有類別遮罩的圖片區隔應用程式。

下載程式碼

以下操作說明說明如何使用 git 指令列工具建立範例程式碼的本機副本。

如要下載範例程式碼,請按照下列步驟操作:

  1. 使用下列指令複製 Git 存放區:
    git clone https://github.com/google-ai-edge/mediapipe-samples
    
  2. 您可以選擇將 Git 執行個體設為使用稀疏檢查,因此只有 Image Segmenter 範例應用程式的檔案:
    cd mediapipe
    git sparse-checkout init --cone
    git sparse-checkout set examples/image_segmentation/android
    

建立範例程式碼的本機版本後,您可以將專案匯入 Android Studio 並執行應用程式。如需操作說明,請參閱「Android 設定指南」。

重要元件

下列檔案包含此圖片區隔範例應用程式的重要程式碼:

設定

本節說明設定開發環境及程式碼專案以使用 Image Segmenter 的重要步驟。如需瞭解如何設定開發環境以使用 MediaPipe 工作 (包括平台版本需求),請參閱「Android 設定指南」。

依附元件

圖片區隔工具使用 com.google.mediapipe:tasks-vision 程式庫。將這個依附元件新增至 Android 應用程式開發專案的 build.gradle 檔案。使用下列程式碼匯入必要的依附元件:

dependencies {
    ...
    implementation 'com.google.mediapipe:tasks-vision:latest.release'
}

型號

MediaPipe 圖片區隔工作需要與這項工作相容的已訓練模型。如要進一步瞭解影像區隔可用的訓練模型,請參閱工作總覽模型一節。

選取並下載模型,然後將其儲存在專案目錄中:

<dev-project-root>/src/main/assets

請使用 BaseOptions.Builder.setModelAssetPath() 方法指定模型使用的路徑。在下一節的程式碼範例中稱為此方法。

在圖片區隔器 範例程式碼中,模型是在 setupImageSegmenter() 函式的 ImageSegmenterHelper.kt 類別中定義。

建立工作

您可以使用 createFromOptions 函式建立工作。createFromOptions 函式可接受設定選項,包括遮罩輸出類型。如要進一步瞭解工作設定,請參閱設定選項一文。

圖片區隔工作支援下列輸入資料類型:靜態圖片、影片檔案和即時影片串流。建立工作時,您必須指定與輸入資料類型相對應的執行模式。選擇輸入資料類型的分頁,瞭解建立工作的方式。

圖片

ImageSegmenterOptions options =
  ImageSegmenterOptions.builder()
    .setBaseOptions(
      BaseOptions.builder().setModelAssetPath("model.tflite").build())
    .setRunningMode(RunningMode.IMAGE)
    .setOutputCategoryMask(true)
    .setOutputConfidenceMasks(false)
    .build();
imagesegmenter = ImageSegmenter.createFromOptions(context, options);
    

影片

ImageSegmenterOptions options =
  ImageSegmenterOptions.builder()
    .setBaseOptions(
      BaseOptions.builder().setModelAssetPath("model.tflite").build())
    .setRunningMode(RunningMode.VIDEO)
    .setOutputCategoryMask(true)
    .setOutputConfidenceMasks(false)
    .build();
imagesegmenter = ImageSegmenter.createFromOptions(context, options);
    

直播

ImageSegmenterOptions options =
  ImageSegmenterOptions.builder()
    .setBaseOptions(
      BaseOptions.builder().setModelAssetPath("model.tflite").build())
    .setRunningMode(RunningMode.LIVE_STREAM)
    .setOutputCategoryMask(true)
    .setOutputConfidenceMasks(false)
    .setResultListener((result, inputImage) -> {
         // Process the segmentation result here.
    })
    .setErrorListener((result, inputImage) -> {
         // Process the segmentation errors here.
    })
    .build()
imagesegmenter = ImageSegmenter.createFromOptions(context, options)
    

Image Segmenter 程式碼範例實作可讓使用者切換處理模式。這種做法會讓工作建立程式碼變得更加複雜,並且可能不適合您的用途。您可以在 ImageSegmenterHelper 類別中,由 setupImageSegmenter() 函式看到此程式碼。

設定選項

這項工作的 Android 應用程式設定選項如下:

選項名稱 說明 值範圍 預設值
runningMode 設定工作的執行模式。共有三種模式:

IMAGE:單一圖片輸入的模式。

影片:影片已解碼影格的模式。

LIVE_STREAM:輸入資料串流 (例如攝影機) 的直播模式。在這個模式下,必須呼叫 resultListener 才能設定事件監聽器,以非同步方式接收結果。
{IMAGE, VIDEO, LIVE_STREAM} IMAGE
outputCategoryMask 如果設為 True,輸出結果會包含 uint8 圖片的區隔遮罩,其中每個像素值都代表勝出類別值。 {True, False} False
outputConfidenceMasks 如果設為 True,輸出結果會包含以浮點值圖片形式的區隔遮罩,其中每個浮點值都代表該類別的可信度分數對應關係。 {True, False} True
displayNamesLocale 設定標籤語言,用於工作模型中繼資料內的顯示名稱 (如有)。英文的預設值是 en。您可以使用 TensorFlow Lite Metadata Writer API,在自訂模型的中繼資料中加入本地化標籤。語言代碼 en
resultListener 在圖片區隔處於直播模式時,設定結果監聽器以非同步方式接收區隔結果。只能在執行模式設為 LIVE_STREAM 時使用 不適用 不適用
errorListener 設定選用的錯誤事件監聽器。 不適用 未設定

準備資料

「圖片區隔」支援圖片、影片檔案和直播影片。工作會處理資料輸入的預先處理作業,包括調整大小、旋轉和值正規化。

您必須先將輸入圖片或框架轉換為 com.google.mediapipe.framework.image.MPImage 物件,才能將其傳送至圖片區隔。

圖片

import com.google.mediapipe.framework.image.BitmapImageBuilder;
import com.google.mediapipe.framework.image.MPImage;

// Load an image on the user’s device as a Bitmap object using BitmapFactory.

// Convert an Android’s Bitmap object to a MediaPipe’s Image object.
Image mpImage = new BitmapImageBuilder(bitmap).build();
    

影片

import com.google.mediapipe.framework.image.BitmapImageBuilder;
import com.google.mediapipe.framework.image.MPImage;

// Load a video file on the user's device using MediaMetadataRetriever

// From the video’s metadata, load the METADATA_KEY_DURATION and
// METADATA_KEY_VIDEO_FRAME_COUNT value. You’ll need them
// to calculate the timestamp of each frame later.

// Loop through the video and load each frame as a Bitmap object.

// Convert the Android’s Bitmap object to a MediaPipe’s Image object.
Image mpImage = new BitmapImageBuilder(frame).build();
    

直播

import com.google.mediapipe.framework.image.MediaImageBuilder;
import com.google.mediapipe.framework.image.MPImage;

// Create a CameraX’s ImageAnalysis to continuously receive frames
// from the device’s camera. Configure it to output frames in RGBA_8888
// format to match with what is required by the model.

// For each Android’s ImageProxy object received from the ImageAnalysis,
// extract the encapsulated Android’s Image object and convert it to
// a MediaPipe’s Image object.
android.media.Image mediaImage = imageProxy.getImage()
Image mpImage = new MediaImageBuilder(mediaImage).build();
    

在圖片區隔器範例程式碼中,資料準備是由 segmentLiveStreamFrame() 函式在 ImageSegmenterHelper 類別中處理。

執行工作

您可以根據目前使用的執行模式呼叫其他 segment 函式。Image Segmenter 函式會傳回輸入圖片或影格中已識別的區段區域。

圖片

ImageSegmenterResult segmenterResult = imagesegmenter.segment(image);
    

影片

// Calculate the timestamp in milliseconds of the current frame.
long frame_timestamp_ms = 1000 * video_duration * frame_index / frame_count;

// Run inference on the frame.
ImageSegmenterResult segmenterResult =
    imagesegmenter.segmentForVideo(image, frameTimestampMs);
    

直播

// Run inference on the frame. The segmentations results will be available via
// the `resultListener` provided in the `ImageSegmenterOptions` when the image
// segmenter was created.
imagesegmenter.segmentAsync(image, frameTimestampMs);
    

注意事項:

  • 以影片模式或直播模式執行時,您也必須為圖片區隔工作提供輸入影格的時間戳記。
  • 在圖片或影片模式中執行時,「圖片區隔」工作會封鎖目前的執行緒,直到完成輸入圖片或影格的處理為止。如要避免封鎖使用者介面,請在背景執行緒中執行處理作業。
  • 以直播模式執行時,圖片區隔工作不會封鎖目前的執行緒,但會立即傳回。每當它處理完輸入影格時,就會透過偵測結果叫用結果監聽器。如果在圖片區隔工作忙於處理其他影格時呼叫 segmentAsync 函式,工作會忽略新的輸入影格。

在圖片區隔器範例程式碼中,ImageSegmenterHelper.kt 檔案中定義了 segment 函式。

處理並顯示結果

執行推論時,圖片區隔工作會傳回 ImageSegmenterResult 物件,其中包含區隔工作的結果。輸出內容的內容取決於您在設定工作時設定的 outputType

以下各節說明這項工作的輸出資料範例:

類別可信度

下圖顯示類別可信度遮罩的工作輸出內容。可信度遮罩輸出包含介於 [0, 1] 之間的浮點值。

原始圖片和類別可信度遮罩輸出內容。Pascal VOC 2012 資料集的來源映像檔。

類別值

下圖以視覺化方式呈現類別值遮罩的工作輸出內容。類別遮罩範圍為 [0, 255],每個像素值代表模型輸出的勝出類別索引。勝出類別索引是模型可識別類別中的最高分數。

原始圖片和類別遮罩輸出內容。Pascal VOC 2012 資料集的來源映像檔。