mediapipe icon indicating copy to clipboard operation
mediapipe copied to clipboard

How to get segmentation image in a Bitmap?

Open victorjaviermartin opened this issue 1 year ago • 2 comments

Hi, I'm trying to work with this sample project, and I want to obtain a bitmap with the roi of the image only. But when I'm getting the result in the method onResults I need to build another Bitmap of the masked region only, but I'm doing something wrong because I can't build it from the ByteBuffer returned.

override fun onResults(result: InteractiveSegmentationHelper.ResultBundle?) {
        // Inform the overlap view to draw over the area of significance returned
        // from the helper
        result?.let {
            activityMainBinding.overlapView.setMaskResult(
                it.byteBuffer,
                it.maskWidth,
                it.maskHeight
            )
        } ?: kotlin.run {
            activityMainBinding.overlapView.clearAll()
        }
    }

I'm using the next two ways to perform this action, but the app crash this both.

fun InteractiveSegmentationHelper.ResultBundle.toBitmap(): Bitmap {
    val byteBuffer = this.byteBuffer
    val maskWidth = this.maskWidth
    val maskHeight = this.maskHeight

    // Crear un arreglo de bytes a partir del ByteBuffer
    val byteArray = ByteArray(byteBuffer.remaining())
    byteBuffer.get(byteArray)

    // Crear un mapa de bits a partir del arreglo de bytes
    val bitmap = Bitmap.createBitmap(maskWidth, maskHeight, Bitmap.Config.ARGB_8888)
    bitmap.copyPixelsFromBuffer(ByteBuffer.wrap(byteArray))

    return bitmap
}


fun InteractiveSegmentationHelper.ResultBundle.toBitmap(): Bitmap {
    val byteBuffer = this.byteBuffer
    val maskWidth = this.maskWidth
    val maskHeight = this.maskHeight

    // Crear un Bitmap a partir del ByteBuffer
    val bitmap = Bitmap.createBitmap(maskWidth, maskHeight, Bitmap.Config.ARGB_8888)

    // Copiar píxeles desde el ByteBuffer al Bitmap
    var copiedPixels = 0
    while (byteBuffer.hasRemaining() && copiedPixels < maskWidth * maskHeight) {
        val pixelsToCopy = minOf(byteBuffer.remaining(), maskWidth * maskHeight - copiedPixels)
        bitmap.copyPixelsFromBuffer(byteBuffer)
        copiedPixels += pixelsToCopy
    }

    // Verificar si se copiaron todos los píxeles
    if (copiedPixels < maskWidth * maskHeight) {
        throw IllegalStateException("No se copiaron todos los píxeles al Bitmap")
    }

    return bitmap
}

The error getted was:

java.lang.RuntimeException: Buffer not large enough for pixels
at android.graphics.Bitmap.copyPixelsFromBuffer(Bitmap.java:662)...

I'm doing the next:

override fun onResults(result: InteractiveSegmentationHelper.ResultBundle?) {
        // Inform the overlap view to draw over the area of significance returned
        // from the helper
        result?.let {
            binding.overlapView.setMaskResult(
                it.byteBuffer,
                it.maskWidth,
                it.maskHeight
            )

            try {
                CoroutineScope(Dispatchers.Main).launch {
                    withContext(Dispatchers.IO){
                        val maskBitmap = it.toBitmap()
                        sharedViewModel.setBitmapPhoto2(maskBitmap)
                    }
                    withContext(Dispatchers.Main){
                        binding.btImagepickerContinue.isEnabled = true
                    }
                }
            }catch (ex: IllegalArgumentException){
                ColoredSnackBar.error(binding.root, "Upss!! Algo no ha ido bien")
                ex.printStackTrace()
            }finally {
                mainActivity.hideProgressIndicator()
            }


        } ?: kotlin.run {
            binding.overlapView.clearAll()
            mainActivity.hideProgressIndicator()

        }

    }

victorjaviermartin avatar Feb 07 '24 00:02 victorjaviermartin

@victorjaviermartin Lo que yo hice fue obtener el bounding box de la región identificada, y con el bounding box recortar la imágen analizada, usa el bitmap que se le pasa al ObjectDetector, ya que la referencia de los bounding boxes, hacen referencia a la imágen analizada.

gerardoeg avatar Feb 08 '24 15:02 gerardoeg

@victorjaviermartin Lo que yo hice fue obtener el bounding box de la región identificada, y con el bounding box recortar la imágen analizada, usa el bitmap que se le pasa al ObjectDetector, ya que la referencia de los bounding boxes, hacen referencia a la imágen analizada.

Me he perdido un poco, tengo poca experiencia con esto, algun sitio donde te informaras de esto? gracias de igual modo @gerardoeg

El tema esta en que me gustaria tener solo la imagen de la mascara, eliminando el resto de pixels que la mascara marca. Estoy perdidisimo

victorjaviermartin avatar Feb 10 '24 01:02 victorjaviermartin