從菜鳥到高手, HMS Core影像分割服務教你如何在複雜背景裡精細摳圖

HMSCore發表於2022-03-03

2021年以來,自動駕駛賽道進入爆發期,該行業成為大廠以及初創企業的必爭之地。其中眾多公司都採用了計算機視覺作為自動駕駛的技術底座,通過影像分割技術,汽車才能夠有效理解道路場景,分清楚哪裡是路,哪裡是人。除了自動駕駛領域,影像分割技術也常出現在其他重要的場景中,比如:

  • 醫療影像分割:幫助醫生進行診斷測試
  • 衛星影像分析:適合深入研究大量影像資料
  • 影像娛樂類App:人像摳圖、避免視訊彈幕遮住人臉

因此,影像分割技術的應用十分重要且廣泛。HMS Core機器學習服務影像分割服務採用了具有創新意義的語義分割框架。這種框架將影像中的每個畫素點都標籤化,即使是髮絲細節都可以清晰完整的保留。另外,影像分割服務還提升了對於不同畫質、不同尺寸圖片的處理能力,針對分割演算法常常出現的白邊,採用更加結構化學習的訓練方式,使邊緣更加自然。

那麼如此穩定、精細化的分割能力,到底如何實現?

開發實戰

一、開發準備

Maven倉和SDK的配置步驟可以參考開發者網站中的應用開發介紹:
https://developer.huawei.com/...

1 配置華為Maven倉地址。

buildscript {
repositories {
google()
jcenter()
maven {url 'https://developer.huawei.com/repo/'}
}
dependencies {
...
classpath 'com.huawei.agconnect:agcp:1.4.1.300'
}
}
 
allprojects {
repositories {
google()
jcenter()
maven {url 'https://developer.huawei.com/repo/'}
}
}

2 新增編譯SDK依賴

dependencies {
    // 引入基礎SDK
implementation 'com.huawei.hms:ml-computer-vision-segmentation:2.1.0.301'
    // 引入人像分割模型包
implementation 'com.huawei.hms:ml-computer-vision-image-segmentation-body-model:2.1.0.303'
}

3 在AndroidManifest.xml中新增許可權

// 使用儲存許可權
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

二、開發步驟

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    if (!allPermissionsGranted()) {
        getRuntimePermissions();
    }
}
private boolean allPermissionsGranted() {
    for (String permission : getRequiredPermissions()) {
        if (!isPermissionGranted(this, permission)) {
            return false;
        }
    }
    return true;
}
private void getRuntimePermissions() {
    List<String> allNeededPermissions = new ArrayList<>();
    for (String permission : getRequiredPermissions()) {
        if (!isPermissionGranted(this, permission)) {
            allNeededPermissions.add(permission);
        }
    }
    if (!allNeededPermissions.isEmpty()) {
        ActivityCompat.requestPermissions(
                this, allNeededPermissions.toArray(new String[0]), PERMISSION_REQUESTS);
    }
}
private static boolean isPermissionGranted(Context context, String permission) {
    if (ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED) {
        return true; 
    }
    return false; 
}
private String[] getRequiredPermissions() { 
    try {
        PackageInfo info =
                this.getPackageManager()
                        .getPackageInfo(this.getPackageName(), PackageManager.GET_PERMISSIONS); 
        String[] ps = info.requestedPermissions;
        if (ps != null && ps.length > 0) { 
            return ps;
        } else { 
            return new String[0];
        } 
    } catch (RuntimeException e) {
        throw e; 
    } catch (Exception e) { 
        return new String[0];
    }
}

2 建立圖片分割檢測器

MLImageSegmentationSetting setting = new MLImageSegmentationSetting.Factory()
// 設定為人像分割
        .setAnalyzerType(MLImageSegmentationSetting.BODY_SEG)
        .create();
this.analyzer = MLAnalyzerFactory.getInstance().getImageSegmentationAnalyzer(setting);

3 通過android.graphics.Bitmap建立“MLFrame”物件用於分析器檢測圖片

MLFrame mlFrame = new MLFrame.Creator().setBitmap(this.originBitmap).create();

4 呼叫“asyncAnalyseFrame ”方法進行影像分割

// 建立一個task,處理影像分割檢測器返回的結果。
Task<MLImageSegmentation> task = this.analyzer.asyncAnalyseFrame(mlFrame);
// 非同步處理影像分割檢測器返回的結果。
task.addOnSuccessListener(new OnSuccessListener<MLImageSegmentation>() {
    @Override
    public void onSuccess(MLImageSegmentation mlImageSegmentationResults) {.
        if (mlImageSegmentationResults != null) {
//獲得從圖片中分割出的人像前景圖
            foreground = mlImageSegmentationResults.getForeground();
            preview.setImageBitmap(MainActivity.this.foreground);
        }
    }
}).addOnFailureListener(new OnFailureListener() {
    @Override
    public void onFailure(Exception e) {
        return;
    }
});

5 更換圖片背景

// 從相簿中獲取圖片
backgroundBitmap = Utils.loadFromPath(this, id, targetedSize.first, targetedSize.second);
BitmapDrawable drawable = new BitmapDrawable(backgroundBitmap);
preview.setBackground(drawable);
preview.setImageBitmap(this.foreground);

6 更換圖片背景

MLFrame mlFrame = new MLFrame.Creator().setBitmap(this.originBitmap).create();

(demo演示視訊如下)

瞭解更多詳情>>

訪問華為開發者聯盟官網
獲取開發指導文件
華為移動服務開源倉庫地址:GitHubGitee

關注我們,第一時間瞭解 HMS Core 最新技術資訊~

相關文章