Removes old MLKit labeler because of the terrible labels it was creating.

This commit is contained in:
Vitor Pamplona
2026-04-27 11:29:28 -04:00
parent 54ef9ead2d
commit af6b8c8a52
3 changed files with 4 additions and 44 deletions
-1
View File
@@ -349,7 +349,6 @@ dependencies {
// On-device alt-text suggestions: genai image description (preferred, descriptive sentences) // On-device alt-text suggestions: genai image description (preferred, descriptive sentences)
// with image-labeling as a keyword-join fallback for devices without AICore. // with image-labeling as a keyword-join fallback for devices without AICore.
playImplementation libs.google.mlkit.genai.image.description playImplementation libs.google.mlkit.genai.image.description
playImplementation libs.google.mlkit.image.labeling
// PushNotifications // PushNotifications
playImplementation platform(libs.firebase.bom) playImplementation platform(libs.firebase.bom)
@@ -29,14 +29,8 @@ import com.google.mlkit.genai.imagedescription.ImageDescriber
import com.google.mlkit.genai.imagedescription.ImageDescriberOptions import com.google.mlkit.genai.imagedescription.ImageDescriberOptions
import com.google.mlkit.genai.imagedescription.ImageDescription import com.google.mlkit.genai.imagedescription.ImageDescription
import com.google.mlkit.genai.imagedescription.ImageDescriptionRequest import com.google.mlkit.genai.imagedescription.ImageDescriptionRequest
import com.google.mlkit.vision.common.InputImage
import com.google.mlkit.vision.label.ImageLabeler
import com.google.mlkit.vision.label.ImageLabeling
import com.google.mlkit.vision.label.defaults.ImageLabelerOptions
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import kotlin.coroutines.resume
/** /**
* Unified alt-text suggestion service. * Unified alt-text suggestion service.
@@ -47,15 +41,12 @@ import kotlin.coroutines.resume
class MLKitImageLabelService( class MLKitImageLabelService(
private val context: Context, private val context: Context,
) { ) {
private var labeler: ImageLabeler? = null
private var describer: ImageDescriber? = null private var describer: ImageDescriber? = null
// FeatureStatus is an Int enum. Cached per-instance — describer availability does not flip // FeatureStatus is an Int enum. Cached per-instance — describer availability does not flip
// mid-session in practice, and one composer mount only needs to ask AICore once. // mid-session in practice, and one composer mount only needs to ask AICore once.
@Volatile private var cachedGenAiStatus: Int? = null @Volatile private var cachedGenAiStatus: Int? = null
private fun ensureLabeler(): ImageLabeler = labeler ?: ImageLabeling.getClient(ImageLabelerOptions.DEFAULT_OPTIONS).also { labeler = it }
private fun ensureDescriber(): ImageDescriber? = private fun ensureDescriber(): ImageDescriber? =
describer describer
?: try { ?: try {
@@ -66,26 +57,7 @@ class MLKitImageLabelService(
null null
} }
suspend fun labelImage(uri: Uri): List<Pair<String, Float>> = suspend fun suggestAltText(uri: Uri): String? = describeWithGenAi(uri)
withContext(Dispatchers.IO) {
try {
val image = InputImage.fromFilePath(context, uri)
val client = ensureLabeler()
suspendCancellableCoroutine { cont ->
client
.process(image)
.addOnSuccessListener { labels ->
cont.resume(labels.map { it.text to it.confidence })
}.addOnFailureListener {
cont.resume(emptyList())
}
}
} catch (_: Exception) {
emptyList()
}
}
suspend fun suggestAltText(uri: Uri): String? = describeWithGenAi(uri) ?: labelKeywords(uri)
private suspend fun describeWithGenAi(uri: Uri): String? = private suspend fun describeWithGenAi(uri: Uri): String? =
withContext(Dispatchers.IO) { withContext(Dispatchers.IO) {
@@ -100,20 +72,13 @@ class MLKitImageLabelService(
.runInference(request) .runInference(request)
.get() .get()
.description .description
?.trim() .trim()
?.takeIf { it.isNotEmpty() } .takeIf { it.isNotEmpty() }
} catch (_: Exception) { } catch (_: Exception) {
null null
} }
} }
private suspend fun labelKeywords(uri: Uri): String? {
val labels = labelImage(uri)
val confident = labels.filter { it.second >= MIN_CONFIDENCE }.map { it.first }
if (confident.isEmpty()) return null
return confident.take(MAX_LABELS).joinToString(", ")
}
// Two-pass decode keeps a 12 MP camera shot from blowing past 40 MB of ARGB_8888 — the // Two-pass decode keeps a 12 MP camera shot from blowing past 40 MB of ARGB_8888 — the
// on-device describer downscales internally anyway, so a ~1024 px input is plenty. // on-device describer downscales internally anyway, so a ~1024 px input is plenty.
private fun loadDownscaledBitmap(uri: Uri): Bitmap? = private fun loadDownscaledBitmap(uri: Uri): Bitmap? =
@@ -136,14 +101,12 @@ class MLKitImageLabelService(
): Int { ): Int {
if (width <= 0 || height <= 0) return 1 if (width <= 0 || height <= 0) return 1
var sample = 1 var sample = 1
var maxDim = maxOf(width, height) val maxDim = maxOf(width, height)
while (maxDim / sample > target) sample *= 2 while (maxDim / sample > target) sample *= 2
return sample return sample
} }
fun close() { fun close() {
labeler?.close()
labeler = null
describer?.close() describer?.close()
describer = null describer = null
cachedGenAiStatus = null cachedGenAiStatus = null
-2
View File
@@ -41,7 +41,6 @@ genaiProofreading = "1.0.0-beta1"
genaiPrompt = "1.0.0-beta2" genaiPrompt = "1.0.0-beta2"
genaiRewriting = "1.0.0-beta1" genaiRewriting = "1.0.0-beta1"
genaiImageDescription = "1.0.0-beta1" genaiImageDescription = "1.0.0-beta1"
imageLabeling = "16.0.0"
languageId = "17.0.6" languageId = "17.0.6"
lifecycleRuntimeKtx = "2.10.0" lifecycleRuntimeKtx = "2.10.0"
lightcompressor-enhanced = "2.2.1" lightcompressor-enhanced = "2.2.1"
@@ -151,7 +150,6 @@ google-mlkit-genai-proofreading = { group = "com.google.mlkit", name = "genai-pr
google-mlkit-genai-prompt = { group = "com.google.mlkit", name = "genai-prompt", version.ref = "genaiPrompt" } google-mlkit-genai-prompt = { group = "com.google.mlkit", name = "genai-prompt", version.ref = "genaiPrompt" }
google-mlkit-genai-rewriting = { group = "com.google.mlkit", name = "genai-rewriting", version.ref = "genaiRewriting" } google-mlkit-genai-rewriting = { group = "com.google.mlkit", name = "genai-rewriting", version.ref = "genaiRewriting" }
google-mlkit-genai-image-description = { group = "com.google.mlkit", name = "genai-image-description", version.ref = "genaiImageDescription" } google-mlkit-genai-image-description = { group = "com.google.mlkit", name = "genai-image-description", version.ref = "genaiImageDescription" }
google-mlkit-image-labeling = { group = "com.google.android.gms", name = "play-services-mlkit-image-labeling", version.ref = "imageLabeling" }
google-mlkit-language-id = { group = "com.google.mlkit", name = "language-id", version.ref = "languageId" } google-mlkit-language-id = { group = "com.google.mlkit", name = "language-id", version.ref = "languageId" }
google-mlkit-translate = { group = "com.google.mlkit", name = "translate", version.ref = "translate" } google-mlkit-translate = { group = "com.google.mlkit", name = "translate", version.ref = "translate" }
jackson-module-kotlin = { group = "com.fasterxml.jackson.module", name = "jackson-module-kotlin", version.ref = "jacksonModuleKotlin" } jackson-module-kotlin = { group = "com.fasterxml.jackson.module", name = "jackson-module-kotlin", version.ref = "jacksonModuleKotlin" }