You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Kotlin中用Google ML Kit人像分割实现图像背景去除并保存

解决方案:基于ML Kit Segmentation Mask实现人像背景去除与Bitmap保存

不需要使用Matrix来完成这个需求,核心是通过图像合成技术将Mask与原图融合,保留人像区域。以下是具体实现步骤:

1. 将ML Kit返回的Segmentation Mask转换为Bitmap并缩放

ML Kit的Selfie Segmentation返回的Mask是256×256的ByteBuffer,首先需要将其转换为Bitmap,再缩放到与目标原图一致的尺寸:

// 把ML Kit返回的SegmentationMask转为Bitmap
val maskBitmap = Bitmap.createBitmap(256, 256, Bitmap.Config.ARGB_8888)
val buffer = segmentationMask.buffer
buffer.rewind()
maskBitmap.copyPixelsFromBuffer(buffer)

// 缩放Mask到与原图相同的宽高
val scaledMask = Bitmap.createScaledBitmap(
    maskBitmap,
    originalBitmap.width,
    originalBitmap.height,
    true // 启用双线性过滤保证缩放质量
)

2. 合成去除背景的Bitmap(高效方式)

使用Android Canvas的PorterDuffXfermode实现像素级融合,只保留Mask覆盖的人像区域:

// 创建与原图尺寸一致的空白Bitmap用于存放结果
val resultBitmap = Bitmap.createBitmap(
    originalBitmap.width,
    originalBitmap.height,
    Bitmap.Config.ARGB_8888
)
val canvas = Canvas(resultBitmap)
val paint = Paint().apply {
    // SRC_IN模式:只保留原图与Mask重叠的区域
    xfermode = PorterDuffXfermode(PorterDuff.Mode.SRC_IN)
}

// 先绘制原图,再绘制缩放后的Mask(应用Xfermode)
canvas.drawBitmap(originalBitmap, 0f, 0f, null)
canvas.drawBitmap(scaledMask, 0f, 0f, paint)

3. Jetpack Compose中的绘制优化

你当前使用的drawPoints并不是合适的方式,直接在DrawScope中利用blendMode即可实现实时绘制去除背景的图像:

Canvas(modifier = Modifier.fillMaxSize()) {
    // 绘制原图
    drawImage(originalBitmap)
    // 绘制缩放后的Mask,使用SrcIn混合模式保留人像区域
    drawImage(scaledMask, blendMode = BlendMode.SrcIn)
}

4. 保存合成后的Bitmap到设备

使用MediaStore(适配Android 10+)将结果Bitmap保存到图库:

fun savePortraitBitmap(bitmap: Bitmap, context: Context) {
    val filename = "portrait_${System.currentTimeMillis()}.png"
    val contentValues = ContentValues().apply {
        put(MediaStore.Images.Media.DISPLAY_NAME, filename)
        put(MediaStore.Images.Media.MIME_TYPE, "image/png")
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            put(MediaStore.Images.Media.RELATIVE_PATH, "${Environment.DIRECTORY_PICTURES}/MyApp")
            put(MediaStore.Images.Media.IS_PENDING, 1)
        }
    }

    context.contentResolver.insert(
        MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
        contentValues
    )?.let { uri ->
        context.contentResolver.openOutputStream(uri)?.use { outputStream ->
            bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream)
        }
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            contentValues.put(MediaStore.Images.Media.IS_PENDING, 0)
            context.contentResolver.update(uri, contentValues, null, null)
        }
    }
}

关键说明

  • Matrix主要用于图像的平移、旋转、缩放等几何变换,这里的核心需求是图像像素级融合,因此使用PorterDuffXfermode或Compose的BlendMode是更直接高效的方案。
  • 如果你的Mask中蓝色区域对应人像,需要先将Mask转为灰度图,确保人像区域为白色(高亮度),背景为黑色(低亮度),这样SRC_IN模式才能正确生效。

内容的提问来源于stack exchange,提问作者Gregor Sotošek

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 06:30:48