【Android Studio】将 ResNet50(pt格式->未量化) 模型部署在APP上
【Android Studio】将 ResNet50(pt格式->未量化) 模型部署在APP上
一、Android Studio 简单介绍
什么是Android Studio
Android Studio是谷歌官方推出的一款用于开发Android应用程序的集成开发环境(IDE)。它基于IntelliJ IDEA开发,集成了强大的代码编辑器、模拟器、调试器等功能,为开发者提供了一站式的开发工具,帮助快速高效地开发Android应用程序。
Android Studio的特点
-
集成模拟器:Android Studio内置了模拟器,可以在计算机上模拟运行Android设备,方便开发者进行应用程序的测试和调试。
-
强大的代码编辑器:Android Studio集成了功能强大的代码编辑器,支持语法高亮、自动补全、代码提示等功能,提高了代码编写效率。
-
调试工具:Android Studio内置了调试器,可以帮助开发者在开发过程中进行调试,快速找到并解决程序中的错误。
-
版本控制:Android Studio支持常见的版本控制系统(如Git),方便开发者进行代码版本控制和团队协作。
-
插件支持:Android Studio支持各种插件,可以根据开发者的需求扩展其功能。
-
多平台支持:Android Studio不仅支持Windows、Mac和Linux等多个操作系统,还支持多种屏幕分辨率和语言环境。
如何安装和启动Android Studio
-
下载Android Studio安装包(可以从官网下载)。
-
运行安装包,按照提示完成安装过程。
-
启动Android Studio,选择语言和版本,进入欢迎界面。
-
选择新建项目或打开已有项目,开始开发之旅。
如何使用Android Studio进行应用程序开发
-
创建新项目:在Android Studio中,选择“新建项目”,填写项目名称、包名等信息,选择应用程序类型和最小SDK版本等参数。
-
设计界面:在布局编辑器中,拖拽控件、设置属性,完成界面设计。
-
编写代码:使用Java或Kotlin语言编写代码,实现应用程序的功能。可以使用自动补全、语法高亮等功能提高编码效率。
-
运行调试:通过模拟器或连接真实设备进行应用程序的测试和调试。可以在Android Studio中实时查看日志、调试代码,提高开发效率。
-
打包发布:完成应用程序的开发后,可以使用Android Studio的打包工具将应用程序打包成APK文件,发布到应用市场或其他渠道。
二、Android Studio 创建项目
Gradle 版本

SDK & JDK 版本

三、Android Studio 界面设置
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/photoButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
android:text="Photo"
android:textAllCaps="false"
app:layout_constraintEnd_toStartOf="@+id/detectButton"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/detectButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
android:text="Detect"
android:textAllCaps="false"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/photoButton"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/resultText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="120dp"
android:textSize="18sp"
android:background="#80000000"
android:textColor="@android:color/white"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="MissingConstraints"
android:gravity="center"/>
</androidx.constraintlayout.widget.ConstraintLayout>
<ImageView
android:id="@+id/imageView"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginTop="180dp"
android:background="#FFFFFF"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ProgressBar
android:id="@+id/progressBar"
android:visibility="invisible"
android:layout_marginTop="20dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.498"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/imageView"/>
四、模型转换
# -*- coding:utf-8 -*-
# @author: 牧锦程
import argparse
from model.model import ResNetModel
import torch
def get_parser():
parser = argparse.ArgumentParser()
# model
parser.add_argument("--pretrained", type=bool, default=None, help="use pretrained model")
parser.add_argument("--selectLayer", type=int, default=50, choices=[18, 34, 50, 101, 152], help="resnet model layer number")
parser.add_argument("--n_classes", type=int, default=131, help="data category number")
# save
parser.add_argument("--save_pt", type=str, default="./weights/model.pt", help="save label dir")
# infer model
parser.add_argument("--infer_path", type=str, default="./weights/bset.ckpt", help='val dataset train and save best model')
return parser
def load_model(opts):
model = ResNetModel(weights_flag=opts.pretrained, selectLayer=opts.selectLayer, classNum=opts.n_classes)
model.load_state_dict(torch.load(opts.infer_path, map_location='cpu')['state_dict'])
model.eval()
return model
if __name__ == "__main__":
opts = get_parser().parse_args()
model = load_model(opts)
# 将模型保存为.pt文件
torch.jit.save(torch.jit.script(model), opts.save_pt)
注意:在这里我使用的 torch 的版本为 1.10.0。这里的转换的版本要与Android studio 中依赖的 pytorch_android 和 pytorch_android_torchvision 版本一致。如果不一致就会导致加载失败。
五、Android Studio 关键代码
模型加载
module = Module.load(assetFilePath(modelName));
类别文件读取
HashMap<Integer, String> labelMap = new HashMap<>();
try (BufferedReader br = new BufferedReader(new FileReader(labelPath))) {
String line;
while ((line = br.readLine()) != null) {
line = line.trim();
line = line.substring(1, line.length() - 1); // 去掉大括号
if (line.startsWith("{") || line.endsWith("}")) {
continue;
}
String[] pairs = line.split(", ");
for (String pair : pairs) {
String[] keyValue = pair.split(": ");
int key = Integer.parseInt(keyValue[0]);
String value = keyValue[1].replaceAll("'", "").trim();
labelMap.put(key, value);
}
}
} catch (IOException e) {
e.printStackTrace();
}
处理
// 修改为固定尺寸
Bitmap resizedBitmap = Bitmap.createScaledBitmap(bitmap, 100, 100, false);
// 将图片转换为tensor
final Tensor inputTensor = TensorImageUtils.bitmapToFloat32Tensor(resizedBitmap,
TensorImageUtils.TORCHVISION_NORM_MEAN_RGB,
TensorImageUtils.TORCHVISION_NORM_STD_RGB,
MemoryFormat.CHANNELS_LAST);
模型推理
// 进行推理
final Tensor outputTensor = module.forward(IValue.from(inputTensor)).toTensor();
推理结果
// 将结果处理成列表
final float[] scores = outputTensor.getDataAsFloatArray();
// 选取列表中最大的概率的一个值
float maxScore = -Float.MAX_VALUE;
int maxScoreIdx = -1;
for (int i = 0; i < scores.length; i++) {
if (scores[i] > maxScore) {
maxScore = scores[i];
maxScoreIdx = i;
}
}
// 获取到实际的类名
// Assuming labelData is a Map<String, String>
String className = labelData.get(maxScoreIdx);
六、Android Studio 真机测试

更多推荐


所有评论(0)