调用threshold函数触发IndexError:索引3超出轴0大小3的范围
解决调用
threshold函数时的IndexError问题 嘿,我一眼就揪出问题所在啦!你遇到的IndexError: index 3 is out of bounds错误,根源是你的图片是RGB三通道格式,但代码里硬要操作不存在的第4个Alpha通道。
错误原因分析
从报错信息能明确看出来:当你访问eachPix[3]时,这个像素数组只有3个元素(对应红、绿、蓝三个颜色通道),根本没有第4个索引位。这是因为JPG格式的图片默认是RGB三通道,不带透明度(Alpha)通道,而你的代码不管图片实际通道数,直接修改索引3的位置,自然就触发越界错误了。
另外还有个隐藏坑:你用了reduce函数,但在Python3里reduce已经从全局命名空间移到functools模块了,所以必须在代码开头导入它,不然迟早会遇到NameError。
两种解决方案
方案1:去掉Alpha通道的操作(不需要透明度时用)
直接修改threshold函数里的像素赋值逻辑,只处理RGB三个通道即可:
from functools import reduce # 一定要加这个导入! from PIL import Image from matplotlib import pyplot as plt import numpy as np import time np.seterr(over='ignore') def threshold(imageArray): balanceAr = [] newAr = imageArray for eachRow in imageArray: for eachPix in eachRow: avgNum = reduce(lambda x, y: x + y, eachPix[:3]) / len(eachPix[:3]) balanceAr.append(avgNum) balance = reduce(lambda x, y: x + y, balanceAr) / len(balanceAr) for eachRow in newAr: for eachPix in eachRow: if reduce(lambda x, y: x + y, eachPix[:3]) / len(eachPix[:3]) > balance: # 仅修改RGB三个通道 eachPix[0] = 255 eachPix[1] = 255 eachPix[2] = 255 else: # 同样只修改RGB三个通道 eachPix[0] = 0 eachPix[1] = 0 eachPix[2] = 0 return newAr
方案2:将图片转换为RGBA四通道(需要透明度时用)
如果你确实需要保留Alpha通道,在打开图片时就转换成RGBA格式,这样每个像素会自动拥有4个元素:
# 修改图片打开代码,添加.convert('RGBA') i3=Image.open(open('images/User.1.11.jpg','rb')).convert('RGBA') iar3=np.array(i3)
这样再调用threshold函数时,eachPix[3] = 255就不会报错了,因为现在每个像素数组的长度是4。
额外优化小建议
用reduce计算像素平均值有点繁琐,其实可以用numpy的内置函数更高效简洁,比如用np.mean(eachPix[:3])替代reduce(lambda x,y:x+y, eachPix[:3])/len(eachPix[:3]),代码会更清爽,运行速度也更快。
内容的提问来源于stack exchange,提问作者Lucas Diehl
相关产品推荐
相关产品推荐

