代码
基于ms香橙派AIpro实现垃圾回收AI识别方案五:香橙派OrangePi AIpro实践(基于MobileNetv2的垃圾分类)

基于ms香橙派AIpro实现垃圾回收AI识别方案五:香橙派OrangePi AIpro实践(基于MobileNetv2的垃圾分类)

基于ms香橙派AIpro实现垃圾回收AI识别方案五:香橙派OrangePi AIpro实践(基于MobileNetv2的垃圾分类)

基于ms香橙派AIpro实现垃圾回收AI识别方案一:昇思MindSpore介绍

基于ms香橙派AIpro实现垃圾回收AI识别方案二:昇思MindSpore如何使用

基于ms香橙派AIpro实现垃圾回收AI识别方案三:昇思大模型平台jupyter快速入门体验

基于ms香橙派AIpro实现垃圾回收AI识别方案四:MindSpore应用实践 - 基于MobileNetv2的垃圾分类

基于ms香橙派AIpro实现垃圾回收AI识别方案五:香橙派OrangePi AIpro实践(基于MobileNetv2的垃圾分类)

基于ms香橙派AIpro实现垃圾回收AI识别方案六:SOWT分析与总结


六、香橙派OrangePi AIpro实践 - 基于MobileNetv2的垃圾分类

昇腾样例仓提供了一系列媒体数据处理(DVPP/AIPP)、算子开发与调用(Ascend C)、推理应用开发与部署(AscendCL)等场景的丰富代码样例给开发者进行参考学习,帮助开发者快速入门,进而熟练掌握CANN关键特性使用。

上面章节通过官方的示例,基于昇腾软件栈的MobileNetV2垃圾分类的训练过程,通过使用mobilenetV2模型对输入图片进行分类推理,提供待推理的jpg图片,进行推理后,输出推理后的jpg图片。

6.1 OrangePi AIpro的亮点:

OrangePi AIpro(8-12T)采用昇腾AI技术路线,具体为4核64位处理器+AI处理器,集成图形处理器,支持8-12TOPS AI算力,拥有8GB/16GB LPDDR4X,可以外接32GB/64GB/128GB/256GB eMMC模块,支持双4K高清输出。

  • 丰富的接口:包括两个HDMI输出、GPIO接口、Type-C电源接口、支持SATA/NVMe SSD 2280的M.2插槽、TF插槽、千兆网口、两个USB3.0、一个USB Type-C 3.0、一个Micro USB(串口打印调试功能)、两个MIPI摄像头、一个MIPI屏等,预留电池接口。
  • 广泛适的应用场景:可用于AI边缘计算、深度视觉学习及视频流AI分析、视频图像分析、自然语言处理、智能小车、机械臂、人工智能、无人机、云计算、AR/VR、智能安防、智能家居等领域,覆盖 AIoT各个行业。
  • 系统支持:Orange Pi AIpro支持Ubuntu、openEuler操作系统,满足大多数AI算法原型验证、推理应用开发的需求。

6.2 环境搭建:

在评测之前,除了官方提供了一些配件外,还有一些需要自行提前准备的东西,自行提供的配件清单:

  • TF读卡器
  • HDMI显示器连接线
  • 串口测试线

首先打开balena烧录工具地址,因为个人办公是Mac电脑,借用了同事的Windows电脑来进行此次的测试,我们选择OS为“WINDOWS”的X86|X64版本下载。

打开下载的balena烧录工具,不用安装,直接就打开了,非常的方便,不用在电脑上安装软件:

  • 点击“从文件烧录”选择好我们提前下载的镜像(百度云真的慢)
  • 点击“选择目标磁盘”选中我们插入的TF卡(我提前格式化了)
  • 点击“现在烧录”就可以开始进行烧录了

经过2个阶段,一个是验证阶段,一个是烧录阶段,不过,可惜的是最后一步出错了,百度一下有人说可以不用管,先尝试一下可不可以开机。


6.3 机器组装:

插入USB的鼠标和键盘、显示器HDMI线、自带的type-c电源线后,即可以去插上电源了,一插入就自动启动了,没有什么开机键,即一通电就自动启动,但是有一个问题,等了5分钟除了风扇一直响外,显示器一直不显示,猜测是之前的烧录有问题。

排查原因:

|

序号

可能存在问题点

解决方案

难度

1

检查一下控制启动设备的两个拨码开关,要想从TF卡启动,需要都是右

检查无问题

1星

2

可能烧录的时候出现上面异常,导致无法亮灯

可以尝试使用网友提供的ascend重新烧录一下

2星

3

手里是否有备用TF卡,不过最好使用容量大点的,32G以上,推荐64G

需要买一张备用卡

3星

4

可能开发板子存在问题

这个需要专业人员来解决

4星

因为手里没有备用的TF卡,只能通过第二种方案换一种工具来进行烧录试试,如果网友可以成功启动,就不需要下一步操作。


6.4 替换烧录工具:

在网友的推荐下,使用了另外一个烧录工具ascend,不过这个工具需要下一步下一步安装,就不过多复述了。

小细节:

  1. 烧录时,提示U盘找不到,需要重新插入,此时,不用管他的提示。
  2. 在烧录完成后,提示要格式化,也不需要管,因为在烧录时,就已经开始写成linux的启动镜像盘了,此时,在windows系统是无法识别的,是正常的。
  3. 第一次烧的时候,看到东西就点,点快了,结果重新烧录了一次,需要注意一下。

通过重新烧录之后,我们的系统就可以正常启动了,启动时,需要输入一个用户名密码,非常的开心,后面使用SSH也需要使用到。

  • 用户名:HwHiAiUser
  • 密码:Mind@123


6.5 链接Wifi,使用SSH登录:

因为没有联网,所以,只能在显示器上进行Wifi的联网操作,联网后输入ifconfig查看Wifi的IP地址,在同一个局域网,使用ping ip地址保证网是能连通的情况下,我们就可以使用我工作的主机来SSH登录到开发板子上了,这样操作起来比较便捷。

# 查看主机IP地址
ifconfig

# 检查网络是否连通
ping 192.xx.xx.xx

使用ssh远程链接到OrangePi AIpro开发板上,接下来可以进行环境的初始化,安装一些相关的依赖环境。

硬件要求:因为样例使用到opencv,ffmpeg等第三方依赖进行图像等处理,所以需要在运行之前,根据本文指导安装第三方依赖并进行环境配置。 由于python的开发过程不依赖于编译,所以第三方依赖安装都在运行环境进行操作,第三方依赖python-acllite 请参考第三方依赖选择需要的依赖完成安装。

配置编译依赖的头文件与库文件路径:

export DDK_PATH=/usr/local/Ascend/ascend-toolkit/latest 
export NPU_HOST_LIB=$DDK_PATH/runtime/lib64/stub

运行环境执行以下命令安装相关依赖及ffmpeg:

sudo apt-get install ffmpeg libavcodec-dev libswscale-dev libavdevice-dev

源码安装ACLLite库,获取ACLLite 源码,python acllite库以源码方式提供,安装时将acllite目录拷贝到运行环境的第三方库目录:

git clone https://gitee.com/ascend/ACLLite.git
# 进入到项目目录进行编译, 会编译到上面设置的lib 目录
bash build_so.sh

现在基本的初始化环境已经配置完成了,接下来就是拉取代码的准备和编译了。


6.6 模型转换:

注意:如果是昇腾软件栈的AI推理,需要把原始网络模型 (可能是 PyTorch 的、TensorFlow,也有可能是Caffe的等) 转换成 .om 模型,才能调用昇腾的aclmdlExecute 等模型执行接口在进行模型推理。

这个模型转换的过程就要用到 ATC 工具,目前 ATC 工具直接支持从 Caffe、ONNX、TensorFlow 以及 MindSpore模型的转换,所以如果的训练框架是 PyTorch,则需要做 torch.onnx.export 操作导出成ONNX模型后才能使用ATC工具。

什么是ATC:

昇腾张量编译器(Ascend Tensor Compiler,简称ATC)是昇腾模型转换工具,它可以将开源框架的网络模型(例如TensorFlow、ONNX等)转换为昇腾AI处理器支持的模型文件(.om格式),用于后续的模型推理。

模型转换过程中,ATC会进行算子调度优化、权重数据重排、内存使用优化等操作,对开源框架的网络模型做进一步调优,使其高效地在昇腾AI处理器上执行。

简单的来讲,就是可以将开源框架的网络模型(例如TensorFlow、ONNX等)转换为昇腾AI处理器支持的模型文件(.om格式),用于后续的模型推理,而Orange Ai pro 需要的是.om的格式,所以,需要把pt 的模型转成onnx 格式,再利用平台的 Atc工具转成.om的格式。

# 为了方便下载,在这里直接给出原始模型下载及模型转换命令,可以直接拷贝执行
cd model    
wget https://obs-9be7.obs.cn-east-2.myhuaweicloud.com:443/003_Atc_Models/AE/ATC%20Model/garbage/mobilenetv2.air   
wget https://obs-9be7.obs.cn-east-2.myhuaweicloud.com/models/garbage_picture/insert_op_yuv.cfg
atc --model=./mobilenetv2.air --framework=1 --output=garbage_yuv --soc_version= Ascend310B4 --insert_op_conf=./insert_op_yuv.cfg --input_shape="data:1,3,224,224" --input_format=NCHW

–framework:原始网络模型框架类型,0:Caffe,1:MindSpore,3:TensorFlow,5:ONNX –soc_version:模型转换时昇腾AI处理器的版本,例如含扩展名 –output:转换后的*.om模型文件路径,含文件名,转换成功后,模型文件名自动以.om后缀结尾 –insert_op_conf: 模型相关的配置文件,包含图像大小,预处理等参数

mobilenetv2.air文件是一个模型文件:

  • ‌① . 通常是在模型转换过程中生成的。‌
  • ②. 这个文件包含了模型的架构和权重信息,‌可以用于在特定硬件或软件平台上进行推理。
  • ‌③. 将MobileNetV2模型从PyTorch格式转换为ONNX格式,‌然后再进一步转换为模型格式,‌最终生成了mobilenetv2.air文件。‌

insert_op_yuv.cfg文件则是一个配置文件,:

  • ①. 用于定义在模型转换或推理过程中需要插入的特定操作或配置。
  • ‌②. 这个文件可能包含了针对特定硬件或软件平台的优化设置,‌以确保模型能够在特定环境下高效运行。‌
  • ③. 可能包含了关于输入数据的预处理、‌输出数据的后处理以及可能的硬件加速指令等信息。 ‌- ④. ‌被用于Ascend芯片上的模型转换过程中,‌以实现模型的优化和加速。‌

总结,通过使用Ascend的实例转换模型非常的快,只用了2分钟就完成了操作,而用香橙派OrangePi AIpro,由于硬件配置原因,转了半小时也没反应,果断换了实例。


6.7 官方的Ai Demo项目:

# 开发环境,非root用户命令行中执行以下命令下载源码仓。    
cd ${HOME}     
git clone https://gitee.com/ascend/samples.git
# 将ZIP包上传到开发环境中的目录中,【例如:${HOME}/ascend-samples-master.zip】
unzip ascend-samples-master.zip
# 进入项目
cd python/contrib/garbage_picture

在data中添加一些需要识别的图片:

运行可执行文件:

python3 classify_test.py ../data/

#!/usr/bin/env python
# encoding: utf-8
import sys
import os
path = os.path.dirname(os.path.abspath(__file__))
sys.path.append(os.path.join(path, ".."))
sys.path.append(os.path.join(path, "../../../common/"))
sys.path.append(os.path.join(path, "../../../common/acllite"))

import numpy as np
import acl
import base64
import acllite_utils as utils
from PIL import Image, ImageDraw, ImageFont
from acllite_imageproc import AclLiteImageProc
import constants as const
from acllite_model import AclLiteModel
from acllite_image import AclLiteImage
from acllite_resource import AclLiteResource

SRC_PATH = os.path.realpath(__file__).rsplit("/", 1)[0]
MODEL_PATH = os.path.join(SRC_PATH, "../model/garbage_yuv.om")
MODEL_WIDTH = 224
MODEL_HEIGHT = 224
image_net_classes = [
 "Seashel", "Lighter","Old Mirror", "Broom","Ceramic Bowl", "Toothbrush","Disposable Chopsticks","Dirty Cloth",
     "Newspaper", "Glassware", "Basketball", "Plastic Bottle", "Cardboard","Glass Bottle", "Metalware", "Hats", "Cans", "Paper",
      "Vegetable Leaf","Orange Peel", "Eggshell","Banana Peel",
    "Battery", "Tablet capsules","Fluorescent lamp", "Paint bucket"]

# 中文名列表(与class_en一一对应)
class_cn = [
    '贝壳', '打火机', '旧镜子', '扫把', '陶瓷碗', '牙刷', '一次性筷子', '脏污衣服',
    '报纸', '玻璃制品', '篮球', '塑料瓶', '硬纸板', '玻璃瓶', '金属制品', '帽子', '易拉罐', '纸张',
    '菜叶', '橙皮', '蛋壳', '香蕉皮',
    '电池', '药片胶囊', '荧光灯', '油漆桶'
]

# 垃圾分类字典
garbage_classes = {
    '干垃圾': ['贝壳', '打火机', '旧镜子', '扫把', '陶瓷碗', '牙刷', '一次性筷子', '脏污衣服'],
    '可回收物': ['报纸', '玻璃制品', '篮球', '塑料瓶', '硬纸板', '玻璃瓶', '金属制品', '帽子', '易拉罐', '纸张'],
    '湿垃圾': ['菜叶', '橙皮', '蛋壳', '香蕉皮'],
    '有害垃圾': ['电池', '药片胶囊', '荧光灯', '油漆桶']
}

# 建立从class_en到class_cn的映射
en_to_cn_mapping = dict(zip(image_net_classes, class_cn))

# 查找并推断垃圾分类的函数
def infer_garbage_class_for_en(en_class_name):
    # 使用映射找到对应的中文名
    cn_class_name = en_to_cn_mapping.get(en_class_name, None)
    if cn_class_name is None:
        return '未知'
    
    # 遍历所有垃圾分类以找到匹配的中文名
    for category, classes in garbage_classes.items():
        if cn_class_name in classes:
            return category + '[' + cn_class_name + ']'
    
    # 如果没有找到匹配项(理论上不应该发生,因为映射是完整的),返回'未知'
    return '未知'

def get_image_net_class(class_id):
    if class_id >= len(image_net_classes):
        return "unknown"
    else:
        return image_net_classes[class_id]

def pre_process(image, dvpp):
    """preprocess"""
    image_input = image.copy_to_dvpp()
    yuv_image = dvpp.jpegd(image_input)

    print("decode jpeg end")
    resized_image = dvpp.resize(yuv_image,
                    MODEL_WIDTH, MODEL_HEIGHT)

    print("resize yuv end")
    return resized_image

def post_process(infer_output, image_file):
    print("post process")
    data = infer_output[0]
    vals = data.flatten()
    top_k = vals.argsort()[-1:-6:-1]
    object_class = get_image_net_class(top_k[0])
    fontText = infer_garbage_class_for_en(object_class)
    print("infer result: " + fontText)
    output_path = os.path.join(os.path.join(SRC_PATH, "../out"), os.path.basename(image_file))
    origin_image = Image.open(image_file)
    draw = ImageDraw.Draw(origin_image)
    font = ImageFont.truetype("/usr/share/fonts/truetype/wqy/wqy-microhei.ttc", size=20)
    font.size =50
    draw.text((10, 50), fontText, font=font, fill=255)
    origin_image.save(output_path)
    object_class = get_image_net_class(top_k[0])
    return

def construct_image_info():
    """construct image info"""
    image_info = np.array([MODEL_WIDTH, MODEL_HEIGHT,
                           MODEL_WIDTH, MODEL_HEIGHT],
                           dtype = np.float32)
    return image_info

def main():
    if (len(sys.argv) != 2):
        print("The App arg is invalid")
        exit(1)

    acl_resource = AclLiteResource()
    acl_resource.init()
    model = AclLiteModel(MODEL_PATH)
    dvpp = AclLiteImageProc(acl_resource)

    image_dir = sys.argv[1]
    images_list = [os.path.join(image_dir, img)
                   for img in os.listdir(image_dir)
                   if os.path.splitext(img)[1] in const.IMG_EXT]

    #Create a directory to store the inference results
    if not os.path.isdir(os.path.join(SRC_PATH, "../out")):
        os.mkdir(os.path.join(SRC_PATH, "../out"))

    image_info = construct_image_info()
    for image_file in images_list:
        image = AclLiteImage(image_file)
        resized_image = pre_process(image, dvpp)
        print("pre process end")

        result = model.execute([resized_image,])
        post_process(result, image_file)

        print("process "+image_file+" end")
if __name__ == '__main__':
main()

提示:这里如果使用英文的字体是写不出来中文的,可以确认系统是否已经安装了中文字体,可以使用 fc-list 命令来查看当前系统上安装的所有字体,如下所示:

fc-list

6.8 查看结果:

运行完成后,会在out目录下生成带推理结果的jpg图片。

总结,通过上面的实验,可以看到我们可以很好的在香橙派OrangePi AIpro上运行基于MobileNetV2垃圾分类项目,可以看到有一个电池的图片没有识别正确,识别的结果为“牙刷”,可以增加多一点的图片,再自己训练一下。