Removes old MLKit labeler because of the terrible labels it was creating.
This commit is contained in:
@@ -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)
|
||||||
|
|||||||
+4
-41
@@ -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
|
||||||
|
|||||||
@@ -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" }
|
||||||
|
|||||||
Reference in New Issue
Block a user