游乐游手机版
首页/AI教程/文章详情

手把手教你搭建第一个Android手机AI图像识别项目

时间:2026-06-04 17:05
在计算机视觉领域,把训练好的模型搬到移动端,是一件既让人兴奋又有点棘手的事。这里整理了从数据集准备、模型训练、Web部署、API封装,到最终在Android手机上调用API的全链路流程。整个过程不走捷径,但每一步都有清晰的代码和注释,希望能帮到正在做类似项目的你。 一、准备数据集,训练AI模型 搭建

在计算机视觉领域,把训练好的模型搬到移动端,是一件既让人兴奋又有点棘手的事。这里整理了从数据集准备、模型训练、Web部署、API封装,到最终在Android手机上调用API的全链路流程。整个过程不走捷径,但每一步都有清晰的代码和注释,希望能帮到正在做类似项目的你。

一、准备数据集,训练AI模型

搭建深度学习环境这件事就不展开说了,Python生态里该装的库一个都不能少。工程的目录结构和数据集组织方式如下图所示。


数据读取与预处理是模型训练的第一步,read_data.py 把杂乱的文件转化为模型能消化的张量。来看这段代码:

import os
from PIL import Image
import numpy as np
from sklearn.model_selection import train_test_split
from keras.utils import np_utils
import random

class_num = 8  # 类别数

def preprocess(x):
    Max = np.max(x)
    Min = np.min(x)
    x = (x - Min) / (Max - Min)
    return x * 2 - 1

def read_img(img_name, size, c):
    im = Image.open(img_name)
    im = im.resize((size, size))
    im = im.convert("L") if c == 1 else im.convert("RGB")
    data = np.array(im)
    return data

def read_label(img_name):
    basename = os.path.basename(img_name)
    label = basename.split('_')[0]
    return label

def get_data(pt, size=64, c=1, shuffle=True, test_size=0.2):
    images, labels = [], []
    i = 0
    for x in os.listdir(pt):
        d = os.path.join(pt, x)
        images.append(read_img(d, size=size, c=c))
        labels.append(read_label(d)[0])
        i += 1
    if shuffle == True:
        imgs, lbs = [], []
        index = [x for x in range(len(labels))]
        random.shuffle(index)
        for i in index:
            imgs.append(images[i])
            lbs.append(labels[i])
        images, labels = imgs, lbs
    y = np.array(list(map(int, labels)))
    x = np.array(images)
    x = x.reshape(len(x), size, size, c)
    x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=test_size, random_state=0)
    y_train = np_utils.to_categorical(y_train, class_num)
    y_test = np_utils.to_categorical(y_test, class_num)
    x_train = preprocess(x_train).astype('float32')
    x_test = preprocess(x_test).astype('float32')
    print(len(x_train), len(y_train))
    print(len(x_test), len(y_test))
    return (x_train, y_train, x_test, y_test)

接着是CNN模型的构建与训练,cnn01.py 里定义了一个多层卷积网络,加上批标准化、Dropout防止过拟合,最终用Softmax输出8个类别的概率。

from keras import Input, Model
from keras.layers import Conv2D, MaxPool2D, BatchNormalization
from keras.layers import Dropout, Flatten, Dense
import matplotlib.pyplot as plt
from read_data import get_data

pt = "data"
size = 64
classes = 8
c = 3
batch_size = 128
epochs = 20
name = './result/cnn01C64'

def model_():
    inputs = Input((size, size, c))
    x = BatchNormalization(axis=-1)(inputs)
    x = Conv2D(128, (3, 3), activation='relu')(x)
    x = Conv2D(64, (3, 3), activation='relu')(x)
    x = MaxPool2D((2, 2))(x)
    x = Dropout(0.6)(x)
    x = Conv2D(64, (3, 3), activation='relu')(x)
    x = MaxPool2D((2, 2))(x)
    x = Dropout(0.65)(x)
    x = Flatten()(x)
    x = Dense(64, activation='relu')(x)
    x = Dense(64, activation='relu')(x)
    x = Dropout(0.6)(x)
    outputs = Dense(classes, activation='softmax')(x)
    model = Model(inputs=inputs, outputs=outputs)
    return model

def train_model(epochs):
    model = model_()
    model.compile(loss='categorical_crossentropy', optimizer='rmsprop', metrics=['accuracy'])
    x_train, y_train, x_test, y_test = get_data(pt=pt, size=size, c=c)
    result = model.fit(x_train, y_train, validation_data=(x_test, y_test), epochs=epochs)
    model.sa ve(name + '.h5')
    return result

def result_curve(result):
    # 绘制训练曲线
    # 略……(与原文一致)

执行 cnn01.py 后,训练好的模型会保存为 result/cnn01C64.h5


移动端不能直接跑h5格式,得转成轻量的 .tfliteh5_2_tflite.py 完成转换并顺便做个测试。

import tensorflow as tf
import numpy as np
from PIL import Image
from read_data import preprocess

def h5_to_tflite(in_f, out_f):
    model = tf.keras.models.load_model(in_f)
    converter = tf.lite.TFLiteConverter.from_keras_model(model)
    tflite_model = converter.convert()
    with open(out_f, 'wb') as f:
        f.write(tflite_model)

def test(model_path, img_file, size, c):
    img = Image.open(img_file)
    im = img.resize((size, size))
    im = im.convert("L") if c == 1 else im.convert("RGB")
    x = np.array(im)
    x = np.reshape(x, (1, size, size, c))
    x = preprocess(x)
    x = x.astype(np.float32)
    interpreter = tf.lite.Interpreter(model_path)
    interpreter.allocate_tensors()
    input_details = interpreter.get_input_details()
    output_details = interpreter.get_output_details()
    interpreter.set_tensor(input_details[0]['index'], x)
    interpreter.invoke()
    output = interpreter.get_tensor(output_details[0]['index'])
    y = np.argmax(output, axis=1)[0]
    print(y)

转换完成后,就能在边缘设备上愉快地推理了。

二、Web服务器部署测试及API封装

光有模型不够,得把它变成一个能对外提供服务的接口。前端页面 templates/index.html 提供了一个简单的文件上传表单,后端 app.py 用Flask搭建,同时提供了网页端和API端两种请求方式。

from flask import Flask, render_template, request, jsonify
import tensorflow as tf
import numpy as np
from PIL import Image
import os

app = Flask(__name__)
model = tf.keras.models.load_model("./result/cnn01C64.h5")
img_size = 64
img_channel = 3
dct = {0: '苹果', 1: '香蕉', 2: '樱桃', 3: '火龙果', 4: '芒果', 5: '橘子', 6: '木瓜', 7: '菠萝'}

def preprocess(filepath):
    img = Image.open(filepath)
    img = img.convert("RGB")
    img = img.resize((img_size, img_size))
    img = np.array(img) / 255.0
    img = img.reshape(1, img_size, img_size, img_channel)
    return img

def predict(filepath):
    img = preprocess(filepath)
    pred = model.predict(img)
    result = np.argmax(pred)
    result = dct.get(result)
    confidence = np.max(pred)
    return result, confidence

# ... 路由和API接口代码(与原文一致)

记得把 host 改成你自己的IP地址。下面是Web端的运行效果。

API接口测试脚本 api_test.pyrequests 发送图片,返回JSON结果。

import requests
url = "https://192.168.1.5:8086/api/predict"
files = {"file": open("test.jpg", "rb")}
response = requests.post(url, files=files)
results = response.json()
result = results.get('result')
confidence = results.get('confidence')
print(f"识别结果:{result} 置信度:{round(confidence,3)}")

测试结果如图。

三、Android手机端调用API

移动端的部署往往是最容易出问题的一环,不过有了前面的API,Android这边只需要做一件事:把图片发过去,把结果拿回来。

先搭建Android开发环境,选择“Empty Views Activity”模板,语言用Ja va。记得换国内镜像源——这一步能省下不少等待编译的时间。

修改 gradle/wrapper/gradle-wrapper.properties

distributionUrl=https://mirrors.aliyun.com/macports/distfiles/gradle/gradle-9.2.1-bin.zip

修改 settings.gradle.kts

ma ven { setUrl("https://ma ven.aliyun.com/repository/central") }
ma ven { setUrl("https://ma ven.aliyun.com/repository/jcenter") }
ma ven { setUrl("https://ma ven.aliyun.com/repository/google") }
ma ven { setUrl("https://ma ven.aliyun.com/repository/gradle-plugin") }
ma ven { setUrl("https://ma ven.aliyun.com/repository/public") }
ma ven { setUrl("https://jitpack.io") }
google()

界面设计都在 activity_main.xml 里,一个ImageView显示图片,三个按钮(选择、拍照、API识别),还有两个TextView显示结果和置信度。



  

网络请求用了 OkHttp,封装了一个 ApiCaller 类,处理异步回调。别忘了在 app/build.gradle.kts 中添加依赖。

implementation("com.squareup.okhttp3:okhttps:4.12.0")

接着是 MainActivity.ja va,处理相册选择、拍照、点击识别三个事件。识别时调用 ApiCaller.uploadBitmap,在回调中解析JSON,更新UI。

// 代码与原文一致

Android 9+ 默认禁止明文HTTP,需要配置网络安全策略。在 res/xml/network_security_config.xml 中放行。



    

同时在 AndroidManifest.xml 中声明网络权限并引用该配置。



最后,APP的测试效果如图所示。

整个流程走下来,你会发现从数据到手机其实只隔了几层皮。关键在于每一步的衔接要清晰,代码要可复用。希望这份记录能给你带来一些启发。

来源:https://blog.csdn.net/weixin_39954229/article/details/159418458
上一篇QClaw腾讯本地化AI Agent助手从使用到实战详解 下一篇AI监控HTML5+AI应用运行状态告警
本站内容用于信息整理与展示,如有侵权或内容问题请及时联系处理。

相关推荐

补充同频道和同主题内容,方便继续浏览更多相关内容。

同类最新

继续查看同栏目最近更新的文章。

更多
跨境物流AI Agent感知决策全链路自动化技术拆解
AI教程 · 2026-07-11

跨境物流AI Agent感知决策全链路自动化技术拆解

2026年,跨境物流领域正迎来一场根本性变革——从“被动记录”全面迈向“主动执行”,AI智能体正在重塑整个行业格局。 你可能已经深有体会:每天一到岗,光是后台处理货件创建、物流追踪等重复操作,就要耗费数小时之久。行业调研数据显示,超过60%的运营人员每天至少花费2小时在这些机械性劳动上,而手动操作引

天学会AI应用开发第十二课:从PDF、Word和网页构建RAG
AI教程 · 2026-07-11

天学会AI应用开发第十二课:从PDF、Word和网页构建RAG

上一篇文章介绍了如何从TXT文件中读取文本内容,但在日常办公场景中,纯文本文件的使用频率并不高。更常见的需求是处理PDF、Word等文档格式,同时还需要从网页中提取知识信息。 因此,本篇文章将重点讲解如何从PDF、Word以及网页中提取内容,并将其应用于RAG(检索增强生成)系统。 一、从PDF文件

Hy3+WorkBuddy组合国产顶级Agent附完整提示词
AI教程 · 2026-07-11

Hy3+WorkBuddy组合国产顶级Agent附完整提示词

五个 Case 跑完,总结一下整体体验。工具使用能力:能不能自己开网页、找信息、标出处。规划能力:能不能把多约束需求拆成可执行步骤。长程执行能力:跨多步任务时会不会丢状态。复杂推理能力:能不能先推导、再写代码、再执行验证。WorkBuddy+Hy3 的表现完全符合预期。趁着 WorkBuddy 里的

AI Agent是什么?一文理解大语言模型、记忆、技能、工具、MCP、工作流与上下文
AI教程 · 2026-07-11

AI Agent是什么?一文理解大语言模型、记忆、技能、工具、MCP、工作流与上下文

智能体并非单一模型,而是由大语言模型、记忆、工具、工作流等模块协同构成的自主系统。它通过理解目标、检索记忆、调用工具、构建上下文、推理决策,并基于反馈闭环持续迭代,最终自主完成复杂任务。

DeepSeek决定自研芯片打造人工智能全新算力芯脏
AI教程 · 2026-07-11

DeepSeek决定自研芯片打造人工智能全新算力芯脏

被“逼”出来的第三条路。 一直以模型技术见长的DeepSeek,这次在算力供应链上迈出了让所有人侧目的一步。 2026年7月7日,路透社援引三位知情人士消息,DeepSeek正在悄然开发自有AI芯片。值得玩味的是,这颗芯片的定位非常精准——专攻推理,不涉足训练。消息人士称,项目大约启动于一年前,目前