get display buffer failed

Viewed 39

问题描述


在尝试使用micropython运行yolo程序时,屏幕正常显示2s左右,报错程序异常:get display buffer failed

复现步骤


===================== 1. 统一导入区域(顺序合理,无冗余) =====================

第三方库/工具类导入

from libs.PipeLine import PipeLine
from libs.AIBase import AIBase
from libs.AI2D import Ai2d

from libs.Utils import *
from libs.YOLO import YOLOv8 # 保留必要导入,无冗余

系统/硬件库导入

import os
import sys
import ujson
import gc
#import math
import utime # 嵌入式专用计时/延时,无需同时导入time(若ScopedTiming仍报错,再添加time)

媒体/AI相关导入

from media.media import *
from media.sensor import *
from media.display import *
import nncase_runtime as nn
import ulab.numpy as np
import image
import aicube
import aidemo
import random

===================== 2. 核心外设配置(仅保留需要的,整洁清晰) =====================

DISPLAY_WIDTH = 960 # LCD物理宽度(原生)
DISPLAY_HEIGHT = 540 # LCD物理高度(原生)

对齐函数(按需保留,适配Camera要求)

def align_to_8(x):
return (x // 8) * 8
def align_to_16(x):
return (x // 16) * 16

Sensor输出尺寸(对齐后,替换原1280x720)

SENSOR_WIDTH = DISPLAY_WIDTH
SENSOR_HEIGHT = 536

===================== 3. 自定义检测类(模型逻辑完全保留,仅适配外设参数) =====================

class DetectionApp(AIBase):
def init(self,kmodel_path,labels,model_input_size=[640,640],
anchors=[10.13,16,30,33,23,30,61,62,45,59,119,116,90,156,198,373,326],
model_type="AnchorBaseDet",confidence_threshold=0.5,nms_threshold=0.25,
nms_option=False,strides=[8,16,32],
rgb888p_size=[SENSOR_WIDTH, SENSOR_HEIGHT],
display_size=[DISPLAY_WIDTH, DISPLAY_HEIGHT],debug_mode=0):
super().init(kmodel_path,model_input_size,rgb888p_size,debug_mode)
# 模型核心参数(完全未修改,仅外设参数适配)
self.kmodel_path=kmodel_path
self.labels=labels
self.model_input_size=model_input_size
self.anchors=anchors
self.model_type=model_type
self.confidence_threshold=confidence_threshold
self.nms_threshold=nms_threshold
self.nms_option=nms_option
self.strides=strides
# 外设尺寸(适配新配置,宽16对齐)
self.rgb888p_size=[ALIGN_UP(rgb888p_size[0],16),rgb888p_size[1]]
self.display_size=[ALIGN_UP(display_size[0],16),display_size[1]]
# 其他参数(完全保留原逻辑)
self.debug_mode=debug_mode
self.color_four=get_colors(len(self.labels))
self.ai2d=Ai2d(debug_mode)
self.ai2d.set_ai2d_dtype(nn.ai2d_format.NCHW_FMT,nn.ai2d_format.NCHW_FMT,np.uint8, np.uint8)

# 预处理配置(模型核心逻辑完全未修改)
def config_preprocess(self,input_image_size=None):
    with ScopedTiming("set preprocess config",self.debug_mode > 0):
        ai2d_input_size=input_image_size if input_image_size else self.rgb888p_size
        top,bottom,left,right,_=center_pad_param(self.rgb888p_size,self.model_input_size)
        self.ai2d.pad([0,0,0,0,top,bottom,left,right], 0, [114,114,114])
        self.ai2d.resize(nn.interp_method.tf_bilinear, nn.interp_mode.half_pixel)
        self.ai2d.build([1,3,ai2d_input_size[1],ai2d_input_size[0]],
                        [1,3,self.model_input_size[1],self.model_input_size[0]])

# 后处理(模型核心逻辑完全未修改,无任何多余改动)
def postprocess(self,results):
    with ScopedTiming("postprocess",self.debug_mode > 0):
        if self.model_type == "AnchorBaseDet":
            det_boxes = aicube.anchorbasedet_post_process( results[0], results[1], results[2],
                                                           self.model_input_size, self.rgb888p_size,
                                                           self.strides, len(self.labels),
                                                           self.confidence_threshold, self.nms_threshold,
                                                           self.anchors, self.nms_option)
        elif self.model_type == "GFLDet":
            det_boxes = aicube.gfldet_post_process( results[0], results[1], results[2],
                                                    self.model_input_size, self.rgb888p_size,
                                                    self.strides, len(self.labels),
                                                    self.confidence_threshold, self.nms_threshold,
                                                    self.nms_option)
        elif self.model_type=="AnchorFreeDet":
            det_boxes = aicube.anchorfreedet_post_process( results[0], results[1], results[2],
                                                           self.model_input_size, self.rgb888p_size,
                                                           self.strides, len(self.labels),
                                                           self.confidence_threshold, self.nms_threshold,
                                                           self.nms_option)
        else:
            det_boxes=None
        return det_boxes

# 绘制结果(仅适配新外设尺寸,绘制逻辑完全未修改)
def draw_result(self,pl,det_boxes):
    with ScopedTiming("draw osd",self.debug_mode > 0):
        if det_boxes:
            pl.osd_img.clear()
            for det_boxe in det_boxes:
                x1, y1, x2, y2 = det_boxe[2],det_boxe[3],det_boxe[4],det_boxe[5]
                # 坐标映射适配新尺寸(仅此处适配,无其他改动)
                sx=int(x1 * self.display_size[0] // self.rgb888p_size[0])
                sy=int(y1 * self.display_size[1] // self.rgb888p_size[1])
                w = int(float(x2 - x1) * self.display_size[0] // self.rgb888p_size[0])
                h = int(float(y2 - y1) * self.display_size[1] // self.rgb888p_size[1])
                pl.osd_img.draw_rectangle(sx , sy , w , h , color=self.get_color(det_boxe[0]))
                label = self.labels[det_boxe[0]]
                score = str(round(det_boxe[1],2))
                pl.osd_img.draw_string_advanced(sx, sy-50,32, label + " " + score , color=self.color_four[det_boxe[0]])
        else:
            pl.osd_img.clear()
            pl.osd_img.draw_rectangle(0, 0, 128, 128, color=(0,0,0,0))

# 获取颜色(完全保留原逻辑)
def get_color(self, x):
    idx=x%len(self.color_four)
    return self.color_four[idx]

===================== 4. 主程序(整洁无冗余,外设参数适配,模型逻辑不变) =====================

优化后主程序(添加退出捕获)

if name=="main":
# 基础配置(不变)
display_mode="lcd"
kmodel_path="/sdcard/examples/ai_test_kmodel/insect_det.kmodel"
labels=["leconte","boerner","armandi","linnaeus","coleoptera","acuminatus"]
confidence_threshold=0.5
nms_threshold = 0.5
anchors=[30,23,21,33,29,43,44,29,41,39,41,68,71,43,59,61,71,72]

# 初始化变量(提前定义,方便异常释放)
pl = None
det = None
try:

    rgb888p_size = [SENSOR_WIDTH, SENSOR_HEIGHT]
    display_size = [DISPLAY_WIDTH, DISPLAY_HEIGHT]


    # 初始化PipeLine
    pl=PipeLine(rgb888p_size=rgb888p_size,display_mode=display_mode, display_size=display_size)
    #pl=PipeLine(rgb888p_size=rgb888p_size,display_mode=display_mode)
    pl.create()
    actual_display_size=pl.get_display_size()
    # 校验实际显示尺寸与配置尺寸是否一致
    if actual_display_size[0] != DISPLAY_WIDTH or actual_display_size[1] != DISPLAY_HEIGHT:
        print(f"警告:显示尺寸不匹配,配置[{DISPLAY_WIDTH},{DISPLAY_HEIGHT}],实际[{actual_display_size[0]},{actual_display_size[1]}]")
    # 初始化检测类
    det=DetectionApp(
        kmodel_path=kmodel_path,
        labels=labels,
        model_input_size=[640,640],
        anchors=anchors,
        rgb888p_size=rgb888p_size,
        display_size=actual_display_size,
        debug_mode=0
    )
    det.config_preprocess()


    # 推理循环
    while True:
        with ScopedTiming("total",1):
            img=pl.get_frame()

            det_boxes=det.run(img)

            det.draw_result(pl,det_boxes)
            print(f"剩余内存g:{gc.mem_free()} 字节")
            pl.show_image()                         #g打印h没打印,在这一行卡住且因为get display buffer failed
            
            #Display.show_image(det_boxes, 0, 0, Display.LAYER_OSD0)
            print(f"剩余内存h:{gc.mem_free()} 字节")
            gc.collect()
            print(f"剩余内存i:{gc.mem_free()} 字节")
            utime.sleep_ms(1)
except KeyboardInterrupt:
    print("用户退出程序")
except Exception as e:
    print(f"程序异常:{str(e)}")
finally:
    # 确保资源释放
    if det is not None:
        det.deinit()
    if pl is not None:
        pl.destroy()
    print("资源已释放")

硬件板卡


rt-smart ai学习套件

软件版本


k230_canmv_dongshanpi_sdcard__nncase_v2.9.0

其他信息


我在主程序加打印后,发现程序运行到 pl.show_image(),程序运行错误

2 Answers

你好,可以使用代码控件来保持代码的格式不被改变。现在的脚本无法直接运行。

# ===================== 1. 统一导入区域(顺序合理,无冗余) =====================
# 第三方库/工具类导入
from libs.PipeLine import PipeLine
from libs.AIBase import AIBase
from libs.AI2D import Ai2d

from libs.Utils import *
from libs.YOLO import YOLOv8  # 保留必要导入,无冗余
# 系统/硬件库导入
import os
import sys
import ujson
import gc
#import math
import utime  # 嵌入式专用计时/延时,无需同时导入time(若ScopedTiming仍报错,再添加time)
# 媒体/AI相关导入
from media.media import *
from media.sensor import *
from media.display import *
import nncase_runtime as nn
import ulab.numpy as np
import image
import aicube
import aidemo
import random

# ===================== 2. 核心外设配置(仅保留需要的,整洁清晰) =====================
DISPLAY_WIDTH = 960  # LCD物理宽度(原生)
DISPLAY_HEIGHT = 540 # LCD物理高度(原生)

# 对齐函数(按需保留,适配Camera要求)
def align_to_8(x):
    return (x // 8) * 8
def align_to_16(x):
    return (x // 16) * 16

# Sensor输出尺寸(对齐后,替换原1280x720)
SENSOR_WIDTH = DISPLAY_WIDTH
SENSOR_HEIGHT = 536

# ===================== 3. 自定义检测类(模型逻辑完全保留,仅适配外设参数) =====================
class DetectionApp(AIBase):
    def __init__(self,kmodel_path,labels,model_input_size=[640,640],
                 anchors=[10.13,16,30,33,23,30,61,62,45,59,119,116,90,156,198,373,326],
                 model_type="AnchorBaseDet",confidence_threshold=0.5,nms_threshold=0.25,
                 nms_option=False,strides=[8,16,32],
                 rgb888p_size=[SENSOR_WIDTH, SENSOR_HEIGHT],
                 display_size=[DISPLAY_WIDTH, DISPLAY_HEIGHT],debug_mode=0):
        super().__init__(kmodel_path,model_input_size,rgb888p_size,debug_mode)
        # 模型核心参数(完全未修改,仅外设参数适配)
        self.kmodel_path=kmodel_path
        self.labels=labels
        self.model_input_size=model_input_size
        self.anchors=anchors
        self.model_type=model_type
        self.confidence_threshold=confidence_threshold
        self.nms_threshold=nms_threshold
        self.nms_option=nms_option
        self.strides=strides
        # 外设尺寸(适配新配置,宽16对齐)
        self.rgb888p_size=[ALIGN_UP(rgb888p_size[0],16),rgb888p_size[1]]
        self.display_size=[ALIGN_UP(display_size[0],16),display_size[1]]
        # 其他参数(完全保留原逻辑)
        self.debug_mode=debug_mode
        self.color_four=get_colors(len(self.labels))
        self.ai2d=Ai2d(debug_mode)
        self.ai2d.set_ai2d_dtype(nn.ai2d_format.NCHW_FMT,nn.ai2d_format.NCHW_FMT,np.uint8, np.uint8)

    # 预处理配置(模型核心逻辑完全未修改)
    def config_preprocess(self,input_image_size=None):
        with ScopedTiming("set preprocess config",self.debug_mode > 0):
            ai2d_input_size=input_image_size if input_image_size else self.rgb888p_size
            top,bottom,left,right,_=center_pad_param(self.rgb888p_size,self.model_input_size)
            self.ai2d.pad([0,0,0,0,top,bottom,left,right], 0, [114,114,114])
            self.ai2d.resize(nn.interp_method.tf_bilinear, nn.interp_mode.half_pixel)
            self.ai2d.build([1,3,ai2d_input_size[1],ai2d_input_size[0]],
                            [1,3,self.model_input_size[1],self.model_input_size[0]])

    # 后处理(模型核心逻辑完全未修改,无任何多余改动)
    def postprocess(self,results):
        with ScopedTiming("postprocess",self.debug_mode > 0):
            if self.model_type == "AnchorBaseDet":
                det_boxes = aicube.anchorbasedet_post_process( results[0], results[1], results[2],
                                                               self.model_input_size, self.rgb888p_size,
                                                               self.strides, len(self.labels),
                                                               self.confidence_threshold, self.nms_threshold,
                                                               self.anchors, self.nms_option)
            elif self.model_type == "GFLDet":
                det_boxes = aicube.gfldet_post_process( results[0], results[1], results[2],
                                                        self.model_input_size, self.rgb888p_size,
                                                        self.strides, len(self.labels),
                                                        self.confidence_threshold, self.nms_threshold,
                                                        self.nms_option)
            elif self.model_type=="AnchorFreeDet":
                det_boxes = aicube.anchorfreedet_post_process( results[0], results[1], results[2],
                                                               self.model_input_size, self.rgb888p_size,
                                                               self.strides, len(self.labels),
                                                               self.confidence_threshold, self.nms_threshold,
                                                               self.nms_option)
            else:
                det_boxes=None
            return det_boxes

    # 绘制结果(仅适配新外设尺寸,绘制逻辑完全未修改)
    def draw_result(self,pl,det_boxes):
        with ScopedTiming("draw osd",self.debug_mode > 0):
            if det_boxes:
                pl.osd_img.clear()
                for det_boxe in det_boxes:
                    x1, y1, x2, y2 = det_boxe[2],det_boxe[3],det_boxe[4],det_boxe[5]
                    # 坐标映射适配新尺寸(仅此处适配,无其他改动)
                    sx=int(x1 * self.display_size[0] // self.rgb888p_size[0])
                    sy=int(y1 * self.display_size[1] // self.rgb888p_size[1])
                    w = int(float(x2 - x1) * self.display_size[0] // self.rgb888p_size[0])
                    h = int(float(y2 - y1) * self.display_size[1] // self.rgb888p_size[1])
                    pl.osd_img.draw_rectangle(sx , sy , w , h , color=self.get_color(det_boxe[0]))
                    label = self.labels[det_boxe[0]]
                    score = str(round(det_boxe[1],2))
                    pl.osd_img.draw_string_advanced(sx, sy-50,32, label + " " + score , color=self.color_four[det_boxe[0]])
            else:
                pl.osd_img.clear()
                pl.osd_img.draw_rectangle(0, 0, 128, 128, color=(0,0,0,0))

    # 获取颜色(完全保留原逻辑)
    def get_color(self, x):
        idx=x%len(self.color_four)
        return self.color_four[idx]

# ===================== 4. 主程序(整洁无冗余,外设参数适配,模型逻辑不变) =====================
# 优化后主程序(添加退出捕获)
if __name__=="__main__":
    # 基础配置(不变)
    display_mode="lcd"
    kmodel_path="/sdcard/examples/ai_test_kmodel/insect_det.kmodel"
    labels=["leconte","boerner","armandi","linnaeus","coleoptera","acuminatus"]
    confidence_threshold=0.5
    nms_threshold = 0.5
    anchors=[30,23,21,33,29,43,44,29,41,39,41,68,71,43,59,61,71,72]

    # 初始化变量(提前定义,方便异常释放)
    pl = None
    det = None
    try:

        rgb888p_size = [SENSOR_WIDTH, SENSOR_HEIGHT]
        display_size = [DISPLAY_WIDTH, DISPLAY_HEIGHT]


        # 初始化PipeLine
        pl=PipeLine(rgb888p_size=rgb888p_size,display_mode=display_mode, display_size=display_size)
        #pl=PipeLine(rgb888p_size=rgb888p_size,display_mode=display_mode)
        pl.create()
        actual_display_size=pl.get_display_size()
        # 校验实际显示尺寸与配置尺寸是否一致
        if actual_display_size[0] != DISPLAY_WIDTH or actual_display_size[1] != DISPLAY_HEIGHT:
            print(f"警告:显示尺寸不匹配,配置[{DISPLAY_WIDTH},{DISPLAY_HEIGHT}],实际[{actual_display_size[0]},{actual_display_size[1]}]")
        # 初始化检测类
        det=DetectionApp(
            kmodel_path=kmodel_path,
            labels=labels,
            model_input_size=[640,640],
            anchors=anchors,
            rgb888p_size=rgb888p_size,
            display_size=actual_display_size,
            debug_mode=0
        )
        det.config_preprocess()


        # 推理循环
        while True:
            with ScopedTiming("total",1):
                img=pl.get_frame()

                det_boxes=det.run(img)

                det.draw_result(pl,det_boxes)
                print(f"剩余内存g:{gc.mem_free()} 字节")
                pl.show_image()                         #g打印h没打印,在这一行卡住且因为get display buffer failed

                #Display.show_image(det_boxes, 0, 0, Display.LAYER_OSD0)
                print(f"剩余内存h:{gc.mem_free()} 字节")
                gc.collect()
                print(f"剩余内存i:{gc.mem_free()} 字节")
                utime.sleep_ms(1)
    except KeyboardInterrupt:
        print("用户退出程序")
    except Exception as e:
        print(f"程序异常:{str(e)}")
    finally:
        # 确保资源释放
        if det is not None:
            det.deinit()
        if pl is not None:
            pl.destroy()
        print("资源已释放")