问题描述
我使用的YOLO11,我期望的模型效果是能够像素级识别地面或障碍物区域,并获得图片中每个像素的“地面”“受限地面”或“障碍物”置信度构成的全图矩阵。我的模型推理之后,得到results,形状为(1, 39, 4620),打印results 39行每行4620个元素的均值,发现其不受输入图像的影响。一系列后处理后,得到的矩阵仍然不受输入图像影响。对此,我想问问,这些现象是因为模型有问题导致得到的张量无效,还是因为我目前的后处理操作有误?多谢大佬指点!(下面会补充均值输出、后处理代码信息与.onnx相关信息)
复现步骤
我使用的.onnx的图的最下面部分:
均值输出:
(第1-4行在60与300之间,第5-7行在-10的-5次方与2x10的-4次方之间,后面32行绝对值几乎都在0.001到0.5之间,且每个均值仅有很微弱的波动)
后处理代码(最关键部分):
def postprocess(self, results):
print("postprocess starts")
det_head_out = results[0][0]
print(det_head_out.shape)
# 遍历39行,打印每一行的全局均值
for i in range(39):
row_mean = np.mean(det_head_out[i, :])
print(f"The row {i} average: {row_mean}")
# 8倍尺度:44×80,直接reshape
obs_s8 = det_head_out[4, 0:3520].reshape((44,80))
grd_s8 = det_head_out[5, 0:3520].reshape((44,80))
# 16倍尺度:22×40,切片起始位置3520,总数量880
obs_s16 = det_head_out[4, 3520:3520+880].reshape((22,40))
grd_s16 = det_head_out[5, 3520:3520+880].reshape((22,40))
# 32倍尺度:11×20,切片起始位置3520+880,总数量220
obs_s32 = det_head_out[4, 3520+880:].reshape((11,20))
grd_s32 = det_head_out[5, 3520+880:].reshape((11,20))
def sigmoid_fast(x):
return 0.5 * (np.tanh(x/2) + 1.0)
obs_s8 = sigmoid_fast(obs_s8)
grd_s8 = sigmoid_fast(grd_s8)
obs_s16 = sigmoid_fast(obs_s16)
grd_s16 = sigmoid_fast(grd_s16)
obs_s32 = sigmoid_fast(obs_s32)
grd_s32 = sigmoid_fast(grd_s32)
# 16倍图2倍上采样到44×80,32倍图4倍上采样到44×80
def upsample2x(x):
h, w = x.shape
out = np.zeros((h*2, w*2), dtype=np.float)
out[::2, ::2] = x
out[1::2, ::2] = x
out[:, 1::2] = out[:, ::2]
return out
obs_s16_up = upsample2x(obs_s16)
grd_s16_up = upsample2x(grd_s16)
obs_s32_up = upsample2x(upsample2x(obs_s32))
grd_s32_up = upsample2x(upsample2x(grd_s32))
obstacle_conf = np.maximum(np.maximum(obs_s8, obs_s16_up), obs_s32_up)
ground_conf = np.maximum(np.maximum(grd_s8, grd_s16_up), grd_s32_up)
obstacle_conf = upsample2x(upsample2x(obstacle_conf))
ground_conf = upsample2x(upsample2x(ground_conf))
print("障碍物通道全局均值:", np.mean(obstacle_conf))
print("地面通道全局均值:", np.mean(ground_conf))
硬件板卡
庐山派K230
软件版本
CanMV_K230_LCKFB_micropython_v1.5-legacy-0-g413737f_nncase_v2.9.0 (1).img
其他信息
张量第4,5,6行应该对应.onnx图最右边那个分支的输出,而且我一直以为,这三行应该包含我需要提取的置信度信息。
前面提到的所有现象,都是用我自己的后处理代码得到的结果,而同一个kmodel用官方的sdcard/libs/YOLO.py封装的config_preprocess, postprocess和draw_result获得的结果类似下图:
这样的结果,问题在于:
1.绘制的掩码全是标准矩形,不是真实物体的不规则形状
2.掩码铺满整个或大半个屏幕,极为不准确
3.仅出现Obstacle这一种类型的掩码,只有置信度调到极低(例如0.01)才极短时间出现地面类型掩码
4.Obstacle本身置信度很低,一般在0.2以下
5.无论摄像头输入图像怎样,结果都没有显著差异,都是这些现象
(补充:模型训练好得到的.pt,电脑端检验的时候能够正常工作,没有出现这5种问题,如下图)
此外,发现使用官方自己的python文件:sdcard/examples/20-YOLO-Module-Examples/yolo11_seg_video.py与对应的官方kmodel:sdcard/examples/kmodel/fruit_seg_yolo11n_320.kmodel来直接运行的时候,仍然不能正常识别和分割香蕉、苹果和橘子,同样存在类别识别错误(三者全部识别为香蕉)、置信度低(一般低于0.4)、掩码分散且破碎不准确的问题。至于推理输出张量,其目标对应的三行同样存在数值极为接近0的情况,10的-5到-4数量级。