训练:K230 借助 AICube部署AI 视觉模型 YOLO等教程_嘉楠 ai cube多标签分类-CSDN博客K230模型训练ai cube报错生成部署文件异常_aicube部署模型显示生成部署文件异常-CSDN博客

部署:

# 导入必要的库和模块
import os
import ujson          # 超快的JSON解析库
import aicube         # AI加速库
from media.sensor import *    # 摄像头传感器相关
from media.display import *   # 显示相关
from media.media import *     # 媒体处理基础库
from time import *            # 时间相关
import nncase_runtime as nn   # 神经网络运行时库
import ulab.numpy as np       # 嵌入式优化的numpy替代库
import time
import utime                  # 更精确的时间库
import image                  # 图像处理
import random
import gc                     # 垃圾回收
import utime

# 显示模式配置(LCD或HDMI)
display_mode="lcd"
if display_mode=="lcd":
    DISPLAY_WIDTH = ALIGN_UP(800, 16)  # 对齐到16的倍数(硬件要求)
    DISPLAY_HEIGHT = 480
else:
    DISPLAY_WIDTH = ALIGN_UP(1920, 16)
    DISPLAY_HEIGHT = 1080

# RGB888输出分辨率配置
OUT_RGB888P_WIDTH = ALIGN_UP(1080, 16)
OUT_RGB888P_HEIGH = 720

# 预定义的80种颜色(ARGB格式),用于不同类别的检测框显示
# 颜色盘
color_four = [(255, 220, 20, 60), (255, 119, 11, 32), (255, 0, 0, 142), (255, 0, 0, 230),
        (255, 106, 0, 228), (255, 0, 60, 100), (255, 0, 80, 100), (255, 0, 0, 70),
        (255, 0, 0, 192), (255, 250, 170, 30), (255, 100, 170, 30), (255, 220, 220, 0),
        (255, 175, 116, 175), (255, 250, 0, 30), (255, 165, 42, 42), (255, 255, 77, 255),
        (255, 0, 226, 252), (255, 182, 182, 255), (255, 0, 82, 0), (255, 120, 166, 157),
        (255, 110, 76, 0), (255, 174, 57, 255), (255, 199, 100, 0), (255, 72, 0, 118),
        (255, 255, 179, 240), (255, 0, 125, 92), (255, 209, 0, 151), (255, 188, 208, 182),
        (255, 0, 220, 176), (255, 255, 99, 164), (255, 92, 0, 73), (255, 133, 129, 255),
        (255, 78, 180, 255), (255, 0, 228, 0), (255, 174, 255, 243), (255, 45, 89, 255),
        (255, 134, 134, 103), (255, 145, 148, 174), (255, 255, 208, 186),
        (255, 197, 226, 255), (255, 171, 134, 1), (255, 109, 63, 54), (255, 207, 138, 255),
        (255, 151, 0, 95), (255, 9, 80, 61), (255, 84, 105, 51), (255, 74, 65, 105),
        (255, 166, 196, 102), (255, 208, 195, 210), (255, 255, 109, 65), (255, 0, 143, 149),
        (255, 179, 0, 194), (255, 209, 99, 106), (255, 5, 121, 0), (255, 227, 255, 205),
        (255, 147, 186, 208), (255, 153, 69, 1), (255, 3, 95, 161), (255, 163, 255, 0),
        (255, 119, 0, 170), (255, 0, 182, 199), (255, 0, 165, 120), (255, 183, 130, 88),
        (255, 95, 32, 0), (255, 130, 114, 135), (255, 110, 129, 133), (255, 166, 74, 118),
        (255, 219, 142, 185), (255, 79, 210, 114), (255, 178, 90, 62), (255, 65, 70, 15),
        (255, 127, 167, 115), (255, 59, 105, 106), (255, 142, 108, 45), (255, 196, 172, 0),
        (255, 95, 54, 80), (255, 128, 76, 255), (255, 201, 57, 1), (255, 246, 0, 122),
        (255, 191, 162, 208)]

# 配置文件路径
root_path="/sdcard/mp_deployment_source/"
config_path=root_path+"deploy_config.json"
deploy_conf={}
debug_mode=1  # 调试模式开关

# 性能分析工具类(上下文管理器)
class ScopedTiming:
    def __init__(self, info="", enable_profile=True):
        self.info = info
        self.enable_profile = enable_profile

    def __enter__(self):
        if self.enable_profile:
            self.start_time = time.time_ns()
        return self

    def __exit__(self, exc_type, exc_value, traceback):
        if self.enable_profile:
            elapsed_time = time.time_ns() - self.start_time
            print(f"{self.info} took {elapsed_time / 1000000:.2f} ms")

# 读取部署配置文件
def read_deploy_config(config_path):
    with open(config_path, 'r') as json_file:
        try:
            config = ujson.load(json_file)  # 使用ujson快速解析
        except ValueError as e:
            print("JSON 解析错误:", e)
    return config

# 主检测函数
def detection():
    print("det_infer start")
    # 加载部署配置
    deploy_conf=read_deploy_config(config_path)
    # 解析配置参数
    kmodel_name=deploy_conf["kmodel_path"]        # 模型文件路径
    labels=deploy_conf["categories"]             # 类别标签
    confidence_threshold= deploy_conf["confidence_threshold"]  # 置信度阈值
    nms_threshold = deploy_conf["nms_threshold"] # NMS阈值
    img_size=deploy_conf["img_size"]             # 模型输入尺寸
    num_classes=deploy_conf["num_classes"]       # 类别数量
    nms_option = deploy_conf["nms_option"]       # NMS选项
    model_type = deploy_conf["model_type"]       # 模型类型(AnchorBaseDet等)
    
    # 锚点配置(如果是基于锚点的检测模型)
    if model_type == "AnchorBaseDet":
        anchors = deploy_conf["anchors"][0] + deploy_conf["anchors"][1] + deploy_conf["anchors"][2]

    # 图像预处理参数计算
    kmodel_frame_size = img_size  # 模型输入尺寸
    frame_size = [OUT_RGB888P_WIDTH,OUT_RGB888P_HEIGH]  # 实际输入尺寸
    strides = [8,16,32]  # 特征图步长
    
    # 计算保持长宽比的缩放参数
    ori_w = OUT_RGB888P_WIDTH
    ori_h = OUT_RGB888P_HEIGH
    width, height = kmodel_frame_size
    ratiow = width / ori_w
    ratioh = height / ori_h
    ratio = min(ratiow, ratioh)  # 选择较小比例保持长宽比
    new_w = int(ratio * ori_w)
    new_h = int(ratio * ori_h)
    # 计算填充参数(居中填充)
    dw = (width - new_w) / 2
    dh = (height - new_h) / 2
    top = int(round(dh - 0.1))
    bottom = int(round(dh + 0.1))
    left = int(round(dw - 0.1))
    right = int(round(dw - 0.1))

    # 初始化神经网络推理组件
    kpu = nn.kpu()        # 创建KPU(神经网络加速器)实例
    ai2d = nn.ai2d()      # 创建AI2D(图像预处理加速器)实例
    
    # 加载kmodel模型文件
    kpu.load_kmodel(root_path+kmodel_name)
    
    # 配置AI2D预处理参数
    ai2d.set_dtype(nn.ai2d_format.NCHW_FMT, nn.ai2d_format.NCHW_FMT, np.uint8, np.uint8)
    ai2d.set_pad_param(True, [0,0,0,0,top,bottom,left,right], 0, [114,114,114])  # 填充灰色
    ai2d.set_resize_param(True, nn.interp_method.tf_bilinear, nn.interp_mode.half_pixel)
    
    # 构建AI2D预处理流水线
    ai2d_builder = ai2d.build([1,3,OUT_RGB888P_HEIGH,OUT_RGB888P_WIDTH], [1,3,height,width])

    # 初始化摄像头传感器
    sensor = Sensor(id = 1)
    sensor.reset()
    # 摄像头参数配置
    sensor.set_hmirror(False)  # 水平镜像关闭
    sensor.set_vflip(False)    # 垂直翻转关闭
    
    # 配置显示通道(YUV420格式)
    sensor.set_framesize(DISPLAY_WIDTH, DISPLAY_HEIGHT)
    sensor.set_pixformat(PIXEL_FORMAT_YUV_SEMIPLANAR_420)
    
    # 配置AI处理通道(RGB888格式)
    sensor.set_framesize(OUT_RGB888P_WIDTH, OUT_RGB888P_HEIGH, chn=CAM_CHN_ID_2)
    sensor.set_pixformat(PIXEL_FORMAT_RGB_888_PLANAR, chn=CAM_CHN_ID_2)
    
    # 绑定显示层
    sensor_bind_info = sensor.bind_info(x=0, y=0, chn=CAM_CHN_ID_0)
    Display.bind_layer(**sensor_bind_info, layer=Display.LAYER_VIDEO1)
    
    # 初始化显示设备
    if display_mode=="lcd":
        Display.init(Display.ST7701, to_ide=True)  # 7寸LCD屏
    else:
        Display.init(Display.LT9611, to_ide=True)  # HDMI输出

    # 创建OSD层用于绘制检测结果
    osd_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888)

    try:
        MediaManager.init()  # 初始化媒体系统
        sensor.run()         # 启动摄像头
        
        # 初始化AI2D输入输出张量
        ai2d_input_tensor = None
        ai2d_output_tensor = nn.from_numpy(np.ones((1,3,width,height), dtype=np.uint8))
        
        # 主循环
        while True:
            with ScopedTiming("total", debug_mode > 0):
                # 捕获图像
                rgb888p_img = sensor.snapshot(chn=CAM_CHN_ID_2)
                
                if rgb888p_img.format() == image.RGBP888:
                    # 转换为numpy格式
                    ai2d_input = rgb888p_img.to_numpy_ref()
                    ai2d_input_tensor = nn.from_numpy(ai2d_input)
                    
                    # 执行预处理(缩放+填充)
                    ai2d_builder.run(ai2d_input_tensor, ai2d_output_tensor)
                    
                    # 模型推理
                    kpu.set_input_tensor(0, ai2d_output_tensor)
                    kpu.run()
                    
                    # 获取输出
                    results = []
                    for i in range(kpu.outputs_size()):
                        out_data = kpu.get_output_tensor(i)
                        result = out_data.to_numpy().flatten()
                        results.append(result)
                        del out_data  # 及时释放内存
                    gc.collect()  # 垃圾回收

                    # 后处理
                    if model_type == "AnchorBaseDet":
                        det_boxes = aicube.anchorbasedet_post_process(...)
                    elif model_type == "GFLDet":
                        det_boxes = aicube.gfldet_post_process(...)
                    else:
                        det_boxes = aicube.anchorfreedet_post_process(...)
                    
                    # 清空OSD层并绘制结果
                    osd_img.clear()
                    if det_boxes:
                        for box in det_boxes:
                            # 坐标转换到显示尺寸
                            x1, y1, x2, y2 = box[2], box[3], box[4], box[5]
                            w = (x2 - x1) * DISPLAY_WIDTH / OUT_RGB888P_WIDTH
                            h = (y2 - y1) * DISPLAY_HEIGHT / OUT_RGB888P_HEIGH
                            # 绘制矩形框
                            osd_img.draw_rectangle(
                                int(x1 * DISPLAY_WIDTH / OUT_RGB888P_WIDTH),
                                int(y1 * DISPLAY_HEIGHT / OUT_RGB888P_HEIGH),
                                int(w), int(h),
                                color=color_four[box[0]][1:]  # 根据类别选择颜色
                            )
                    # 显示OSD层
                    Display.show_image(osd_img, 0, 0, Display.LAYER_OSD3)
                    gc.collect()
                rgb888p_img = None  # 释放图像引用
                
    except Exception as e:
        print(f"运行异常: {e}")
    finally:
        # 资源清理
        os.exitpoint(os.EXITPOINT_ENABLE_SLEEP)
        del ai2d_input_tensor
        del ai2d_output_tensor
        sensor.stop()        # 停止摄像头
        Display.deinit()     # 关闭显示
        MediaManager.deinit()# 释放媒体资源
        gc.collect()
        time.sleep(1)
        nn.shrink_memory_pool()  # 释放神经网络内存
    print("det_infer end")
    return 0

if __name__=="__main__":
    detection()

更多推荐