Android透明背景在照片中显示为黑色。

huangapple go评论81阅读模式
英文:

Android transparent background shows as black in Photos

问题

以下是代码的翻译部分:

我正在使用以下代码从图像中删除背景这确实有效但当我将图像保存到设备时您可以看到背景变成了黑色

object BackgroundRemover {

    private val segment: Segmenter
    private var buffer = ByteBuffer.allocate(0)
    private var width = 0
    private var height = 0

    init {
        val segmentOptions = SelfieSegmenterOptions.Builder()
            .setDetectorMode(SelfieSegmenterOptions.SINGLE_IMAGE_MODE)
            .build()
        segment = Segmentation.getClient(segmentOptions)
    }

    /**
     * 处理图像以获取缓冲区和图像高度和宽度
     * @param bitmap 要删除背景的位图。
     * @param trimEmptyPart 如果为true,则在删除背景后将删除位图的空白部分。默认为false。
     * @param listener 成功和失败回调的监听器。
     **/
    fun bitmapForProcessing(
        bitmap: Bitmap,
        trimEmptyPart: Boolean = false,
        listener: OnBackgroundChangeListener
    ) {
        // 生成位图的副本以防万一位图是不可变的。
        val copyBitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true)
        val input = InputImage.fromBitmap(copyBitmap, 0)
        segment.process(input)
            .addOnSuccessListener { segmentationMask ->
                buffer = segmentationMask.buffer
                width = segmentationMask.width
                height = segmentationMask.height

                CoroutineScope(Dispatchers.IO).launch {
                    val time = measureTimeMillis {
                        val resultBitmap = if (trimEmptyPart) {
                            val bgRemovedBitmap = removeBackgroundFromImage(copyBitmap)
                            trim(bgRemovedBitmap)
                        } else {
                            removeBackgroundFromImage(copyBitmap)
                        }
                        withContext(Dispatchers.Main) {
                            listener.onSuccess(resultBitmap)
                        }
                    }
                    Log.e("TAG", "bitmapForProcessingTime: $time")
                }

            }
            .addOnFailureListener { e ->
                println("Image processing failed: $e")
                listener.onFailed(e)
            }
    }

    /**
     * 将背景像素颜色更改为透明。
     * */
    private suspend fun removeBackgroundFromImage(
        image: Bitmap
    ): Bitmap {
        val bitmap = CoroutineScope(Dispatchers.IO).async {
            for (y in 0 until height) {
                for (x in 0 until width) {
                    val bgConfidence = ((1.0 - buffer.get()) * 255).toInt()
                    if (bgConfidence >= 100) {
                        image.setPixel(x, y, Color.TRANSPARENT)
                    }
                }
            }
            buffer.rewind()
            return@async image
        }
        return bitmap.await()
    }

    /**
     * 裁剪位图的空白部分。
     **/
    private suspend fun trim(
        bitmap: Bitmap
    ): Bitmap {
        val result = CoroutineScope(Dispatchers.Default).async {
            var firstX = 0
            var firstY = 0
            var lastX = bitmap.width
            var lastY = bitmap.height
            val pixels = IntArray(bitmap.width * bitmap.height)
            bitmap.getPixels(pixels, 0, bitmap.width, 0, 0, bitmap.width, bitmap.height)
            loop@ for (x in 0 until bitmap.width) {
                for (y in 0 until bitmap.height) {
                    if (pixels[x + y * bitmap.width] != Color.TRANSPARENT) {
                        firstX = x
                        break@loop
                    }
                }
            }
            loop@ for (y in 0 until bitmap.height) {
                for (x in firstX until bitmap.width) {
                    if (pixels[x + y * bitmap.width] != Color.TRANSPARENT) {
                        firstY = y
                        break@loop
                    }
                }
            }
            loop@ for (x in bitmap.width - 1 downTo firstX) {
                for (y in bitmap.height - 1 downTo firstY) {
                    if (pixels[x + y * bitmap.width] != Color.TRANSPARENT) {
                        lastX = x
                        break@loop
                    }
                }
            }
            loop@ for (y in bitmap.height - 1 downTo firstY) {
                for (x in bitmap.width - 1 downTo firstX) {
                    if (pixels[x + y * bitmap.width] != Color.TRANSPARENT) {
                        lastY = y
                        break@loop
                    }
                }
            }
            return@async Bitmap.createBitmap(bitmap, firstX, firstY, lastX - firstX, lastY - firstY)
        }
        return result.await()
    }
}

希望这有助于您理解代码。如果有任何问题,请随时提出。

英文:

I'm using the below code to remove the background from an image, which does work fine, but when i save the image to device, as you can see the background becomes black?

object BackgroundRemover {
private val segment: Segmenter
private var buffer = ByteBuffer.allocate(0)
private var width = 0
private var height = 0
init {
val segmentOptions = SelfieSegmenterOptions.Builder()
.setDetectorMode(SelfieSegmenterOptions.SINGLE_IMAGE_MODE)
.build()
segment = Segmentation.getClient(segmentOptions)
}
/**
* Process the image to get buffer and image height and width
* @param bitmap Bitmap which you want to remove background.
* @param trimEmptyPart After removing the background if its true it will remove the empty part of bitmap. by default its false.
* @param listener listener for success and failure callback.
**/
fun bitmapForProcessing(
bitmap: Bitmap,
trimEmptyPart: Boolean = false,
listener: OnBackgroundChangeListener
) {
//Generate a copy of bitmap just in case the if the bitmap is immutable.
val copyBitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true)
val input = InputImage.fromBitmap(copyBitmap, 0)
segment.process(input)
.addOnSuccessListener { segmentationMask ->
buffer = segmentationMask.buffer
width = segmentationMask.width
height = segmentationMask.height
CoroutineScope(Dispatchers.IO).launch {
val time = measureTimeMillis {
val resultBitmap = if (trimEmptyPart) {
val bgRemovedBitmap = removeBackgroundFromImage(copyBitmap)
trim(bgRemovedBitmap)
} else {
removeBackgroundFromImage(copyBitmap)
}
withContext(Dispatchers.Main) {
listener.onSuccess(resultBitmap)
}
}
Log.e("TAG", "bitmapForProcessingTime: $time")
}
}
.addOnFailureListener { e ->
println("Image processing failed: $e")
listener.onFailed(e)
}
}
/**
* Change the background pixels color to transparent.
* */
private suspend fun removeBackgroundFromImage(
image: Bitmap
): Bitmap {
val bitmap = CoroutineScope(Dispatchers.IO).async {
for (y in 0 until height) {
for (x in 0 until width) {
val bgConfidence = ((1.0 - buffer.float) * 255).toInt()
if (bgConfidence >= 100) {
image.setPixel(x, y, Color.TRANSPARENT)
}
}
}
buffer.rewind()
return@async image
}
return bitmap.await()
}
/**
* trim the empty part of a bitmap.
**/
private suspend fun trim(
bitmap: Bitmap
): Bitmap {
val result = CoroutineScope(Dispatchers.Default).async {
var firstX = 0
var firstY = 0
var lastX = bitmap.width
var lastY = bitmap.height
val pixels = IntArray(bitmap.width * bitmap.height)
bitmap.getPixels(pixels, 0, bitmap.width, 0, 0, bitmap.width, bitmap.height)
loop@ for (x in 0 until bitmap.width) {
for (y in 0 until bitmap.height) {
if (pixels[x + y * bitmap.width] != Color.TRANSPARENT) {
firstX = x
break@loop
}
}
}
loop@ for (y in 0 until bitmap.height) {
for (x in firstX until bitmap.width) {
if (pixels[x + y * bitmap.width] != Color.TRANSPARENT) {
firstY = y
break@loop
}
}
}
loop@ for (x in bitmap.width - 1 downTo firstX) {
for (y in bitmap.height - 1 downTo firstY) {
if (pixels[x + y * bitmap.width] != Color.TRANSPARENT) {
lastX = x
break@loop
}
}
}
loop@ for (y in bitmap.height - 1 downTo firstY) {
for (x in bitmap.width - 1 downTo firstX) {
if (pixels[x + y * bitmap.width] != Color.TRANSPARENT) {
lastY = y
break@loop
}
}
}
return@async Bitmap.createBitmap(bitmap, firstX, firstY, lastX - firstX, lastY - firstY)
}
return result.await()
}

}background removed image Android透明背景在照片中显示为黑色。

答案1

得分: 1

看到图像背景为黑色的原因是因为图像未使用 alpha 通道。

    val c : Canvas = Canvas(bm); // 位图
    c.drawColor(0, Mode.CLEAR);

ARGB_8888 模式创建的位图支持透明度。

将此方法更新为以下内容。

    private suspend fun removeBackgroundFromImage(
        image: Bitmap
    ): Bitmap {
        val bitmap = CoroutineScope(Dispatchers.IO).async {
            for (y in 0 until height) {
                for (x in 0 until width) {
                    val bgConfidence = ((1.0 - buffer.float) * 255).toInt()
                    if (bgConfidence >= 100) {
                        image.setHasAlpha(true)
                        image.setPixel(x, y, Color.TRANSPARENT)
                    }
                }
            }
            buffer.rewind()
            return@async image
        }
        return bitmap.await()
    }

我只是添加了 image.setHasAlpha(true)

setHasAlpha

告诉位图所有像素是否已知为不透明(false)或可能包含非不透明 alpha 值(true)。
注意,对于某些配置(如 RGB_565),此调用会被忽略,因为它不支持每像素 alpha 值。这是作为绘图提示,因为在某些情况下,已知为不透明的位图可以采用比可能具有不透明像素 alpha 值更快的绘制方式。

英文:

The reason you see black in the background of your image is because your image is not using the alpha channel.

val c : Canvas = Canvas(bm); // bitmap
c.drawColor(0, Mode.CLEAR);

Bitmap created in mode ARGB_8888 supports transparency

Update this method like this.

private suspend fun removeBackgroundFromImage(
image: Bitmap
): Bitmap {
val bitmap = CoroutineScope(Dispatchers.IO).async {
for (y in 0 until height) {
for (x in 0 until width) {
val bgConfidence = ((1.0 - buffer.float) * 255).toInt()
if (bgConfidence >= 100) {
image.setHasAlpha(true)
image.setPixel(x, y, Color.TRANSPARENT)
}
}
}
buffer.rewind()
return@async image
}
return bitmap.await()
}

I just added image.setHasAlpha(true).

setHasAlpha

> Tell the bitmap if all of the pixels are known to be opaque (false) or
> if some of the pixels may contain non-opaque alpha values (true).
> Note, for some configs (e.g. RGB_565) this call is ignored, since it
> does not support per-pixel alpha values. This is meant as a drawing
> hint, as in some cases a bitmap that is known to be opaque can take a
> faster drawing case than one that may have non-opaque per-pixel alpha
> values.

huangapple
  • 本文由 发表于 2023年5月17日 16:20:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/76269954.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定