项目目标:
基于AidLux平台的部署沃柑瑕疵语义分割,任务的瑕疵主要包括干疤、腐烂霉点、色斑三种,并包括特征果蒂、果脐两种,最高mIOU 86.5%, 模型选取deeplabv3+网络,进行大量的模型优化工作,本文重点介绍如何基于AidLux平台的沃柑瑕疵的语义分割部署。
Aidlux平台介绍:
Aidlux主打的是基于ARM架构的跨生态(Android/鸿蒙+Linux)一站式AIOT应用开发平台。 用比较简单的方式理解,我们平时编写训练模型,测试模型的时候,常用的是 Linux/window系统。 而实际应用到现场的时候,通常会以几种形态:GPU服务器、嵌入式设备(比如Android手机、人脸识 别闸机,摄像头等)、边缘设备。GPU服务器我们好理解,而Android 嵌入式设备的底层芯片,通常是 ARM架构。而Linux底层也是ARM架构,并且Android又是基于Linux内核开发的操作系统,两者可以共享Linux内核。因此就产生了从底层开发一套应用系统的方式,在此基础上同时带来原生Android和原生Linux使用体验。
Aidlux的ARM架构
因此基于ARM芯片,开发了Aidlux平台,可以在安卓手机上直接下载Aidlux使用。同时基于 ARM芯片,比如高通骁龙的855芯片和865芯片,也开发了AidBox边缘设备,提供7T OPS和15TOPS算力,可以直接在设备上使用。
而使用这些设备平台开发的时候,和在Linux上开发都是通用的,即Linux上开发的Python代 码,可以在安卓手机、边缘设备上转换后无缝使用。 那么为什么可以无缝使用呢? 常规的方式,应用在手机Android时,需要将PC上编写的代码,封装成Android SO库(C++)。经过测试后,封装JNI调用SO库,最终在Android上使用Java调用JNI,最终再进行测试发布。因此我们可以看到,这样的流程需要一系列的工作人员参与,比如C++、Java、Python的工程师。 Aidlux将其中的整个开发流程,全部打通,通过Aidlux平台,可以将PC端编写的代码,快速应用到Android系统上。
模型转换:
AidLux的部署路线一般为:onnx ---> tf ---> tflite 。AidLux可直接推理量化后的tflite模型。
模型转换源码:
import onnx
import tensorflow as tf
# onnx--->tf
onnx_model = onnx.load("../model_data/aidlux_segorange.onnx")
# load onnx model
tf_rep = prepare(onnx_model)
# prepare tf representation
tf_rep.export_graph("aidlux_segorange.tf")
# export the model
# Convert the model tf---->tflite
converter = tf.lite.TFLiteConverter.from_saved_model('aidlux_segorange.tf')
# path to the SavedModel directory
converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS, tf.lite.OpsSet.SELECT_TF_OPS]
# enable TensorFlow ops
converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS]
converter.target_spec.supported_types = [tf.float16]
converter.optimizations = [tf.lite.Optimize.DEFAULT]
tflite_model = converter.convert()
# Save the model.
with open('aidlux_segorange.tflite', 'wb') as f:
f.write(tflite_model) print("done")
基于AidLux平台的部署
from cvs import * import time import cv2 import torch import requests import aidlite_gpu import torch.nn as nn import torchvision.utils import copy import numpy as np import os from tqdm import tqdm device = "cuda" if torch.cuda.is_available() else "cpu"
def preprocess_img(img_pth):
mean = (0.406, 0.456, 0.485)
std = (0.225, 0.224, 0.229)
img_oribgr = cv2.imread(img_pth) # img_orirgb = img_oribgr[…, ::-1]
img_bgr = img_oribgr / 255.0
img_bgr = (img_bgr - mean) / std
img_rgb = img_bgr[…, ::-1]
# image = img_rgb.transpose(2, 0, 1)[None]
image = np.ascontiguousarray(img_rgb)
image = np.array(image, dtype=np.float32)[None]
return imagedef main():
# AidLite初始化:调用AidLite进行AI模型的加载与推理,需导入aidlite
aidlite = aidlite_gpu.aidlite()
# Aidlite模型路径
model_path = ‘/home/Lesson5_code/adv_code/aidlux_segorange.tflite’
# 定义输入输出shape
in_shape = [1 * 384 * 384 * 3 * 4]
out_shape = [1 * 384 * 384 * 4]
# 加载Aidlite检测模型:支持tflite, tnn, mnn, ms, nb格式的模型加载
aidlite.ANNModel(model_path, in_shape, out_shape, 4, 0)
# # 读取图片进行推理
# 数据转换:因为setTensor_Fp32()需要的是float32类型的数据,所以送入的input的数据需为float32
for img_name in tqdm(os.listdir("/home/Lesson5_code/adv_code/img")):
img_path = os.path.join("/home/Lesson5_code/adv_code/img", img_name)
img_np32 = preprocess_img(img_path)
aidlite.setInput_Float32(img_np32, 384, 384)
# 模型推理API
aidlite.invoke()
# 读取返回的结果
pred = aidlite.getOutput_Float32(0)
pred = pred.reshape(1, 384, 384)
pred = np.int32(pred)
seg_img = np.reshape(np.array(colors, np.uint8)[np.reshape(pred, [-1])], [384, 384, -1])
# cv2.imwrite("./img_out/"+img_name, seg_img)
cap = cvs.VideoCapture("/home/Lesson5_code/adv_code/img_out/"+img_name)
img = cap.read()
cap.imshow(img)
if cv2.waitKey(0) == ord(‘q’):
break
# print("finish")colors = [(0, 0, 0), (128, 0, 0), (0, 128, 0), (128, 128, 0), (0, 0, 128),(128, 0, 128), (0, 128, 128), (128, 128, 128), (64, 0, 0)]
main()
AidLux终端输出结果:
正确捕获分割出干疤及果蒂 轮廓部分,并渲染其相应颜色。
手机端显示效果:
学习心得:
通过这次AidLux终端部署学习历程,对AidLux部署有更深层次的理解,尤其是模型转换中的注意事项,为下一步AidLux边缘部署设备的利用打下基础,再次感谢大白老师、Rocky老师,助理的指导。