调用AI 通过相机识别地标

https://www.youtube.com/watch?v=ViRfnLAR_Uc&list=PLQkwcJG4YTCRJxkPPDBcKqDWrfF5qanQs&index=3学习视频

TensorFlow Hub 机器学习模型的代码库

找到地标模型

如何在Android上使用ts模型

https://blog.tensorflow.org/2018/03/using-tensorflow-lite-on-android.html

1.下载模型后放在 asset 下

这个模型大概就有50M了

添加依赖

复制代码
 val cameraxVersion = "1.3.0-rc01"

    implementation("androidx.camera:camera-core:$cameraxVersion")
    implementation("androidx.camera:camera-camera2:$cameraxVersion")
    implementation("androidx.camera:camera-lifecycle:$cameraxVersion")
    implementation("androidx.camera:camera-video:$cameraxVersion")

    implementation("androidx.camera:camera-view:$cameraxVersion")
    implementation("androidx.camera:camera-extensions:$cameraxVersion")

    implementation("org.tensorflow:tensorflow-lite-task-vision:0.4.0")
    implementation("org.tensorflow:tensorflow-lite-gpu-delegate-plugin:0.4.0")
    implementation("org.tensorflow:tensorflow-lite-gpu:2.9.0")

我们希望可以通过ts模型识别图片,这个结果我们放在 Classification 中,自己定义

Kotlin 复制代码
data class Classification(
    val name: String,
    val score: Float
)

定义一个识别接口,然后我们可以有TS模型识别,以后有其他的模型,也可以实现其他的模型进行切换

Kotlin 复制代码
interface LandmarkClassifier {
    fun classify(bitmap: Bitmap, rotation: Int): List<Classification>
}

实现通过ts的API处理bitmap,识别,读取结果

Kotlin 复制代码
class TfLiteLandmarkClassifier(
    private val context: Context,
    private val threshold: Float = 0.5f,
    private val maxResults: Int = 3
): LandmarkClassifier {

    private var classifier: ImageClassifier? = null

    //创建图片识别 classifier
    private fun setupClassifier() {
        val baseOptions = BaseOptions.builder()
            .setNumThreads(2)
            .build()
        //基础参数
        val options = ImageClassifier.ImageClassifierOptions.builder()
            .setBaseOptions(baseOptions)
            .setMaxResults(maxResults)
            .setScoreThreshold(threshold)
            .build()

        //从asset创建
        try {
            classifier = ImageClassifier.createFromFileAndOptions(
                context,
                "landmarks.tflite",
                options
            )
        } catch (e: IllegalStateException) {
            e.printStackTrace()
        }
    }

    override fun classify(bitmap: Bitmap, rotation: Int): List<Classification> {
        if(classifier == null) {
            setupClassifier()
        }

        //处理bitmap
        val imageProcessor = ImageProcessor.Builder().build()
        val tensorImage = imageProcessor.process(TensorImage.fromBitmap(bitmap))

        val imageProcessingOptions = ImageProcessingOptions.builder()
            .setOrientation(getOrientationFromRotation(rotation))
            .build()

        //ts 的 api
        val results = classifier?.classify(tensorImage, imageProcessingOptions)


        //把结果flapmap,
        //合并,然后根据名字 distinct
        return results?.flatMap { classications ->
            classications.categories.map { category ->
                Classification(
                    name = category.displayName,
                    score = category.score
                )
            }
        }?.distinctBy { it.name } ?: emptyList()
    }

    private fun getOrientationFromRotation(rotation: Int): ImageProcessingOptions.Orientation {
        return when(rotation) {
            Surface.ROTATION_270 -> ImageProcessingOptions.Orientation.BOTTOM_RIGHT
            Surface.ROTATION_90 -> ImageProcessingOptions.Orientation.TOP_LEFT
            Surface.ROTATION_180 -> ImageProcessingOptions.Orientation.RIGHT_BOTTOM
            else -> ImageProcessingOptions.Orientation.RIGHT_TOP
        }
    }
}

我们在相机的Analyzer中使用分析器

Kotlin 复制代码
LandmarkRecognitionTensorflowTheme {
                //分析器
                val analyzer = remember {
                    LandmarkImageAnalyzer(
                        classifier = TfLiteLandmarkClassifier(
                            context = applicationContext
                        ),
                        onResults = {
                            classifications = it
                        }
                    )
                }
                val controller = remember {
                    LifecycleCameraController(applicationContext).apply {
                        setEnabledUseCases(CameraController.IMAGE_ANALYSIS)
                        setImageAnalysisAnalyzer(
                            ContextCompat.getMainExecutor(applicationContext),
                            analyzer
                        )
                    }
                }
                Box(
                    modifier = Modifier
                        .fillMaxSize()
                ) {
                    CameraPreview(controller, Modifier.fillMaxSize())

                }
            }
        }

处理图片,根据ts 的文档,把图片裁剪处理成321*321

而且为了性能问题

并不是每一帧都是分析,所以加了 frameSkipCounter'

每60帧才分析,提高性能体验,

最后别忘了关掉imageproxy

Kotlin 复制代码
class LandmarkImageAnalyzer(
    private val classifier: LandmarkClassifier,
    private val onResults: (List<Classification>) -> Unit
): ImageAnalysis.Analyzer {

    private var frameSkipCounter = 0

    override fun analyze(image: ImageProxy) {
        if(frameSkipCounter % 60 == 0) {
            val rotationDegrees = image.imageInfo.rotationDegrees
            val bitmap = image
                .toBitmap()
                .centerCrop(321, 321)

            val results = classifier.classify(bitmap, rotationDegrees)
            onResults(results)
        }
        frameSkipCounter++

        image.close()
    }
}

最后我们把结果显示出来

在result中

Kotlin 复制代码
  var classifications by remember {
                    mutableStateOf(emptyList<Classification>())
                }
Kotlin 复制代码
 Column(
                        modifier = Modifier
                            .fillMaxWidth()
                            .align(Alignment.TopCenter)
                    ) {
                        classifications.forEach {
                            Text(
                                text = it.name,
                                modifier = Modifier
                                    .fillMaxWidth()
                                    .background(MaterialTheme.colorScheme.primaryContainer)
                                    .padding(8.dp),
                                textAlign = TextAlign.Center,
                                fontSize = 20.sp,
                                color = MaterialTheme.colorScheme.primary
                            )
                        }
                    }

效果

图片识别,显示

相关推荐
延凡科技7 分钟前
延凡科技电力数字化平台技术解析:从电力交易到虚拟电厂的全链路架构实践
人工智能·科技·物联网·架构·虚拟电厂·电力平台
Staticy16 分钟前
Claude Code 接国产模型不能识图?一个 MCP 让纯文本模型也能看图
人工智能·ai编程·全栈
极梦网络无忧28 分钟前
real-ai-editor:一款轻量、智能的纯前端 AI 富文本与 Markdown 编辑器
前端·人工智能·编辑器
phltxy29 分钟前
LangChain v1 Agent核心能力详解
大数据·人工智能·langchain
吴佳浩32 分钟前
AI 核心技术解析|OPD:大模型开始复制的不再是知识,而是判断力
人工智能·深度学习·llm
数智化管理手记1 小时前
主数据重复、错漏频发?一站式主数据管理平台如何落地?
大数据·运维·数据库·人工智能·数据挖掘
thesky1234561 小时前
27届大模型岗面试准备(五):预训练全流程拆解——从数据清洗到 Tokenizer 再到 PT 的每
人工智能·面试·大模型·预训练·tokenizer
attitude.x1 小时前
2026年数据透视分析工具推荐:多维与融合对比
人工智能
就是一顿骚操作1 小时前
Agent Loop 入门到深入:从 ReAct 到 LangGraph、Agents SDK 与 MCP
人工智能·大模型·llm·论文解读·ai agent
quanjui1 小时前
【医学尝试】基于Segment Anything Model的医学图像分割研究:眼底OCT与X线胸片微调实战
人工智能·笔记·学习