如何通过ML Kit Selfie Segmentation在流式模式下添加图片虚拟背景?
ML Kit自拍分割流式模式下替换背景为图片的实现方案
核心思路
自拍分割会生成前景遮罩(人像区域),我们只需通过画布混合模式,将背景图作为底层,再把原图的人像区域叠加到背景图上,即可实现图片背景替换,替代原有的纯色背景。
具体实现步骤
结合你参考的官方示例代码,只需修改SelfieSegmentationProcessor类中的渲染逻辑即可:
准备并缓存背景图
提前加载背景图,并根据相机预览尺寸缩放(避免每帧重复缩放消耗性能):// 在Activity或Processor类中初始化背景图 private Bitmap backgroundBitmap; // 示例:从资源加载背景图 backgroundBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.your_bg_image); // 提前缩放至相机预览尺寸(假设previewSize为相机预览的宽高) backgroundBitmap = Bitmap.createScaledBitmap(backgroundBitmap, previewSize.getWidth(), previewSize.getHeight(), true);修改渲染逻辑,替换纯色背景为图片
替换原有的drawColor纯色绘制逻辑,改为先画背景图,再通过混合模式叠加人像区域:private void draw(Canvas canvas) { if (isFaceDetectionEnabled && faceBoundingBox != null) { drawFaceBoundingBox(canvas); } if (backgroundBitmap == null) { // 背景图未加载时,回退到原粉色背景 canvas.drawColor(Color.MAGENTA); canvas.drawBitmap(foregroundBitmap, 0, 0, paint); return; } // 1. 绘制缩放后的背景图 canvas.drawBitmap(backgroundBitmap, 0, 0, null); // 2. 设置混合模式:仅显示遮罩内的人像区域 paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); canvas.drawBitmap(foregroundBitmap, 0, 0, paint); // 3. 重置混合模式,避免影响后续绘制 paint.setXfermode(null); }处理方向适配
如果相机预览方向与屏幕方向不一致,需要将背景图旋转对应角度,保证背景与预览帧方向匹配:// 示例:旋转背景图至相机预览方向(比如90度) Matrix matrix = new Matrix(); matrix.postRotate(90); // 根据实际预览角度调整 backgroundBitmap = Bitmap.createBitmap(backgroundBitmap, 0, 0, backgroundBitmap.getWidth(), backgroundBitmap.getHeight(), matrix, true);
性能优化注意事项
- 背景图提前缩放并缓存,不要在每帧渲染时重复执行缩放操作,避免流式模式下卡顿。
- 若背景图较大,建议在子线程完成缩放、旋转等预处理操作,避免阻塞主线程。
- 页面销毁时回收Bitmap资源,避免内存泄漏:
@Override protected void onDestroy() { super.onDestroy(); if (backgroundBitmap != null && !backgroundBitmap.isRecycled()) { backgroundBitmap.recycle(); backgroundBitmap = null; } }
内容的提问来源于stack exchange,提问作者Ivan Šimović
相关产品推荐
相关产品推荐

