Python代码中painted_img始终为0的原因排查求助
问题情况
跑下面这段代码后,painted_img一直是全0的数组,但已确认sp_intensity[seg]并非全0:
self.painted_imgs = [] self.labels = labels for idx, (sp_intensity, _, sp_order, superpixels) in enumerate(sp_data): painted_img = np.zeros_like(images[idx]) for seg in sp_order: mask = (superpixels == seg) painted_img[mask] = sp_intensity[seg] self.painted_imgs.append(painted_img)
各变量形状&类型:
images[idx]:(3, 512, 512),uint8类型superpixels:(512, 512),int64类型sp_intensity:(100, 3),float64类型sp_order:(100,),int64类型
几个可能的坑和解决办法
1. 数据类型不兼容,赋值直接变0
painted_img是uint8类型(继承自images[idx]),但sp_intensity[seg]是float64类型。如果sp_intensity里的值都是小于1的小数,赋值给uint8数组时会被直接截断成0。
解决办法:
要么把sp_intensity转成uint8类型(比如先乘255,确保值在0-255之间):
painted_img[mask] = sp_intensity[seg].astype(np.uint8)
要么创建painted_img时就用浮点类型:
painted_img = np.zeros_like(images[idx], dtype=np.float64)
2. seg和superpixels的数值对不上,mask全是False
检查sp_order里的seg值,是不是不在superpixels的实际取值范围内?比如superpixels里的像素值从1开始计数,但sp_order里的seg从0开始,那mask = (superpixels == seg)就全是False,根本没赋值到任何像素。
排查技巧:
加个打印看看mask里有没有有效匹配:
for seg in sp_order: mask = (superpixels == seg) print(f"seg {seg} 对应的匹配像素数:{mask.sum()}") # 输出大于0才正常 painted_img[mask] = sp_intensity[seg]
如果输出全是0,说明seg在superpixels里不存在,得检查sp_order和superpixels的对应关系是不是错了。
3. 维度不匹配,赋值没生效
sp_intensity[seg]是长度为3的数组(对应RGB三通道),但painted_img是(3, 512, 512)的通道优先格式,直接赋值可能因为维度广播问题没生效。
解决办法:
把sp_intensity[seg]调整成和painted_img通道维度匹配的形状,方便广播:
# 把(3,)变成(3,1,1),对应(3,512,512)的每个通道 painted_img[:, mask] = sp_intensity[seg][:, np.newaxis, np.newaxis]
另外也确认下superpixels的形状是不是(512,512),和images[idx]的后两个维度一致。
总结
先查数据类型,再看mask有没有效,最后检查维度匹配,一步步试就能找到问题。
内容的提问来源于stack exchange,提问作者user17349469

