How to convert camera image to use it in tflite

I have an android app in Kotlin which depends on CameraX to analyze images and pass them to tensorflow lite image detection model ( not classification ). The problem is we get YUV or RGBA Output images and we need an argb bitmap to pass to tflite model to detect objects we have been struggling for weeks and we have a deadline soon help please.

ImageAnalysis.Analyzer {
private val supportedImages = listOf(ImageFormat.FLEX_RGBA_8888, ImageFormat.FLEX_RGB_888)
private var data = “”

@SuppressLint("UnsafeOptInUsageError")
override fun analyze(image: ImageProxy) {
    if (image.format in supportedImages) {
        val options = ObjectDetector.ObjectDetectorOptions.builder()
            .setScoreThreshold(0.2F)
            .setBaseOptions(BaseOptions.builder().build())
            .build()
        val objectDetector =
            ObjectDetector.createFromFileAndOptions(
                context, Model.createModel(context, "model.tflite").path, options
            )
        val bitmap = toBitmap(image)
        val tfImage = TensorImage.fromBitmap(bitmap)
        val results: List<Detection> = objectDetector.detect(tfImage)
        for (result in results) {
            val categories = result.categories
            for (category in categories) {
                val label = category.label
                val boundingBox = result.boundingBox
                data += "label : $label | bounding : $boundingBox"
            }
        }
        listener(data)
        image.close()
    }
}

private fun toBitmap(image: ImageProxy): Bitmap {
    val r = image.planes[0].buffer.int
    val g = image.planes[1].buffer.int
    val b = image.planes[2].buffer.int
    val a = image.planes[3].buffer.int
    var color = Color.argb(a, r, g, b)
    val rect = Rect(0, 0, 1, 1)
    color = ColorUtils.compositeColors(color, Color.WHITE)
    val bitmap = Bitmap.createBitmap(rect.width(), rect.height(), Bitmap.Config.ARGB_8888)
    val canvas = Canvas(bitmap)
    val paint = Paint()
    paint.color = color
    canvas.drawRect(rect, paint)
    savePic(bitmap = bitmap!!, display_name = Random(100000L).toString())
    return bitmap
}
private fun savePic(bitmap: Bitmap, display_name: String): Boolean {
    val mediaCollection = latest {
        MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
    } ?: MediaStore.Images.Media.EXTERNAL_CONTENT_URI
    val contentValues = ContentValues().apply {
        put(MediaStore.Images.Media.DISPLAY_NAME, "${display_name}.jpg")
        put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg")
        put(MediaStore.Images.Media.WIDTH, bitmap.width)
        put(MediaStore.Images.Media.HEIGHT, bitmap.height)
    }
    return try {
        context.contentResolver.insert(mediaCollection, contentValues)?.also { uri ->
            context.contentResolver.openOutputStream(uri).use { outputStream ->
                if (!bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream)) {
                    throw IOException("could not save bitmap!")
                }
            }
        } ?: throw IOException("could not create media store entry")
        return true
    } catch (e: IOException) {
        e.printStackTrace()
        false
    }
}

}

Hi, @ECi88

I apologize for the delayed response, to confirm below code snippet solved your issue or still do you need help on this issue please ?

fun imageToBitmap(image: Image): Bitmap? {
    // Get the image planes
    val planes: Array<Image.Plane> = image.planes
    val yPlane = planes[0]
    val uPlane = planes[1]
    val vPlane = planes[2]

    // Get the byte buffers for Y, U, and V planes
    val yBuffer: ByteBuffer = yPlane.buffer
    val uBuffer: ByteBuffer = uPlane.buffer
    val vBuffer: ByteBuffer = vPlane.buffer

    // Get the remaining bytes for each plane
    val ySize = yBuffer.remaining()
    val uSize = uBuffer.remaining()
    val vSize = vBuffer.remaining()

    // Create a byte array to hold NV21 data
    val nv21 = ByteArray(ySize + uSize + vSize)

    // Copy Y, U, and V data into the NV21 byte array
    yBuffer.get(nv21, 0, ySize)
    vBuffer.get(nv21, ySize, vSize)
    uBuffer.get(nv21, ySize + vSize, uSize)

    // Create a YuvImage object
    val yuvImage = YuvImage(nv21, ImageFormat.NV21, image.width, image.height, null)

    // Convert YuvImage to JPEG
    val out = ByteArrayOutputStream()
    yuvImage.compressToJpeg(Rect(0, 0, yuvImage.width, yuvImage.height), 90, out)
    val jpegBytes = out.toByteArray()

    // Decode JPEG byte array to Bitmap
    return BitmapFactory.decodeByteArray(jpegBytes, 0, jpegBytes.size)
}

Thank you for your cooperation and patience.