Applying KMeans clustering from OpenCV cannot return a Bitmap with alpha channel

30 Views Asked by At

I'm working in a task for applying kmeans clustering algorithm from OpenCV with Kotlin inside of an android app.

I'm got a piece of code that works, and result is an a reduced colors of the original bitmap. But the original bitmap has a lot of transparent pixels but the result bitmap is returning black pixels in the place of the transparent pixels, but I need that the result keep untouched the transparent pixels.

My method is:

suspend fun calculateDominantQuantizationColors(inputBitmap: Bitmap): Bitmap? {
    return withContext(Dispatchers.IO) {
        try {
            val imagen = Mat()
            Utils.bitmapToMat(inputBitmap, imagen, true)

            // Convertir el bitmap a una matriz de OpenCV (Mat)
            val ny = Mat()
            Utils.bitmapToMat(inputBitmap, ny, true)

            // Convertir la imagen de RGB a BGR
            val bgrImage = Mat()
            Imgproc.cvtColor(ny, bgrImage, Imgproc.COLOR_RGB2BGR)
            bgrImage.convertTo(bgrImage, CvType.CV_32F, 1.0 / 255.0)

            // Convertir la imagen a escala de grises
            val gres = Mat()
            Imgproc.cvtColor(ny, gres, Imgproc.COLOR_BGR2GRAY)

            // Calcular la intensidad mediana
            val medianIntensity = Core.mean(gres).`val`[0]

            // Calcular los umbrales inferior y superior iniciales
            val lowerThreshold = 0.8 * medianIntensity
            val upperThreshold = 1.6 * medianIntensity

            // Aplicar detección de bordes Canny con los umbrales calculados
            val edges = Mat()
            Imgproc.Canny(gres, edges, lowerThreshold, upperThreshold)

            // Encontrar contornos
            val contours: MutableList<MatOfPoint> = ArrayList()
            val hierarchy = Mat()
            Imgproc.findContours(edges, contours, hierarchy, Imgproc.THRESH_BINARY, Imgproc.CHAIN_APPROX_SIMPLE)

            // Reformar la imagen para el agrupamiento k-means
            val reshapedImage = bgrImage.reshape(1, bgrImage.rows() * bgrImage.cols())

            // Realizar agrupamiento k-means
            val labels = Mat()
            val K = 8
            val centers = Mat(K, reshapedImage.cols(), reshapedImage.type())

            val maxCount = 8
            val criteria = TermCriteria(TermCriteria.EPS, maxCount, 2.0)
            Core.kmeans(reshapedImage, K, labels, criteria, 1, Core.KMEANS_PP_CENTERS, centers)

            // Reconstruir la imagen agrupada
            var rec = Mat(bgrImage.rows() * bgrImage.cols(), 3, CvType.CV_32F)
            for (i in 0 until reshapedImage.rows()) {
                val j = labels.get(i, 0)[0].toInt()
                centers.row(j).copyTo(rec.row(i))
            }

            // Reformar la imagen reconstruida al tamaño y tipo original
            rec.convertTo(rec, CvType.CV_8U, 255.0)
            rec = rec.reshape(3, bgrImage.rows())
            Imgproc.cvtColor(rec, rec, Imgproc.COLOR_BGR2RGB)

            // Aplicar un filtro bilateral
            val biletra = Mat()
            Imgproc.bilateralFilter(rec, biletra, 50, 50.0, 50.0, Core.BORDER_DEFAULT)
            Imgproc.drawContours(biletra, contours, -1, Scalar(1.0, 1.0, 1.0), 1)

            // Convertir la imagen procesada a Bitmap
            val resultBitmap = Bitmap.createBitmap(biletra.cols(), biletra.rows(), Bitmap.Config.ARGB_8888)
            Utils.matToBitmap(biletra, resultBitmap, true)

            return@withContext resultBitmap
        } catch (ex: Exception) {
            ex.printStackTrace()
            return@withContext null
        }
    }
}

Sample of Original Bitmap:

Original Bitmap

Sample of the Result Bitmap:

Color Clusterized Bitmap

Any advice to achieve this will be appreciated.

Thank you

0

There are 0 best solutions below