遇到 IndexError: index is out of bounds 错误通常是在处理模型输出时数组索引超出范围。以下是针对YOLOv5 kmodel在MicroPython运行时的完整解决方案:
模型输出与代码不匹配:
锚点(anchor)配置错误:
输入尺寸不匹配:
后处理逻辑错误:
确保转换命令正确(参考官方文档):
./k230_optimize_tool optimize
--model yolov5s.onnx
--input_shape "[1,3,640,640]"
--mean 0.0,0.0,0.0
--std 255.0,255.0,255.0
--output_io hex
--output_dir out
--target k230
特别注意:
input_shape必须与推理代码中的输入尺寸完全一致
在MicroPython代码中使用正确的锚点:
# yolov5s原始锚点 (COCO数据集)
anchors = [
10,13, 16,30, 33,23, # P3/8 (小目标)
30,61, 62,45, 59,119, # P4/16 (中目标)
116,90, 156,198, 373,326 # P5/32 (大目标)
]更新YOLO处理类中的process方法:
class YOLOv5:
def process(self, output_data):
"""处理kmodel输出数据"""
outputs = np.array(output_data)
outputs = outputs.reshape((3, -1, 85)) # 假设85=4+1+80
boxes = []
scores = []
class_ids = []
# 处理每个检测层 (3层)
for i, output in enumerate(outputs):
# 分离坐标、置信度、类别概率
pred_boxes = output[:, 0:4]
pred_conf = output[:, 4]
pred_prob = output[:, 5:]
# 过滤低置信度检测
mask = pred_conf > self.conf_threshold
pred_boxes = pred_boxes[mask]
pred_conf = pred_conf[mask]
pred_prob = pred_prob[mask]
# 计算类别分数
class_score = pred_conf[:, None] * pred_prob
# 获取最高分数类别
class_idx = np.argmax(class_score, axis=1)
class_score_max = np.max(class_score, axis=1)
# 收集有效检测
for j in range(len(pred_boxes)):
box = pred_boxes[j]
score = class_score_max[j]
class_id = class_idx[j]
if score > self.conf_threshold:
# 转换为[x1, y1, w, h]
x, y, w, h = box[0], box[1], box[2], box[3]
boxes.append([x-w/2, y-h/2, w, h])
scores.append(score)
class_ids.append(class_id)
# NMS处理
indices = np.non_max_suppression(
boxes=np.array(boxes),
scores=np.array(scores),
class_ids=np.array(class_ids),
nms_threshold=self.nms_threshold
)
return [boxes[i] for i in indices], [scores[i] for i in indices], [class_ids[i] for i in indices]确保预处理尺寸与模型匹配:
# 图像预处理 (固定640x640)
def preprocess(img):
img = img.resize(640, 640) # 确保尺寸与模型一致
img = img.to_rgb888()
# HWC转CHW
img = img.transpose([2, 0, 1])
# 归一化 [0-255] => [0.0-1.0]
img = img / 255.0
return imgfrom libs.YOLO import YOLOv5
import image
import ulab.numpy as np
# 1. 初始化模型
anchors = [10,13, 16,30, 33,23, 30,61, 62,45, 59,119, 116,90, 156,198, 373,326]
model = YOLOv5(
class_num=80,
anchors=anchors,
net_in_size=(640, 640),
conf_threshold=0.25,
nms_threshold=0.45
)
model.load("yolov5s.kmodel")
# 2. 图像预处理
img = image.Image("/sd/test.jpg")
input_tensor = preprocess(img) # 返回CHW格式
# 3. 推理
outputs = model.forward(input_tensor)
# 4. 处理输出
boxes, scores, class_ids = model.process(outputs)
# 5. 结果可视化
for box, score, class_id in zip(boxes, scores, class_ids):
print(f"Class: {class_id}, Score: {score}, Box: {box}")
# 在原图上绘制矩形框
img.draw_rectangle(
int(box[0] * img.width()),
int(box[1] * img.height()),
int(box[2] * img.width()),
int(box[3] * img.height()),
thickness=2
)
img.save("/sd/result.jpg")确认输出张量维度:
print("Output shape:", np.array(outputs).shape)典型的有效输出形状:
(25200, 85) 或(3, X, 85) (X为每层检测数)调整输出处理:
如果输出维度不同:
# 如果输出是单张量 (25200x85)
outputs = outputs.reshape((-1, 85))检查锚点匹配:
使用原始模型的锚点值(YOLOv5的yaml文件中定义)
内存优化:
MicroPython设备内存有限,添加内存清理:
del outputs
gc.collect()通过以上调整,应该能解决索引越界问题。如果问题依然存在,请提供以下信息以便进一步排查:
print(output_data.shape)的输出结果
举报
更多回帖