使用3x3卷积核将彩色图转灰度图代码输出黑屏问题求助
代码问题排查与修复方案
核心错误点
- 遍历范围完全错误:两层for循环的起始值和终止值写反了,原代码
for y in range(Hi, Hk + pad)逻辑完全错误,当原图高宽大于4时(3x3核pad=1,Hk+pad=4),range为空,循环根本没有执行,output数组全为0,所以输出黑屏。正确的遍历范围应该是从pad到Hi+pad(因为原图做了pad,总高度是Hi+2*pad),宽度同理。
- 遍历范围完全错误:两层for循环的起始值和终止值写反了,原代码
- 代码缩进错误:像素值缩放、类型转换的代码被错误放到了外层for循环内部,还没完成所有像素的卷积计算就提前做了缩放,而且每遍历一行就做一次无意义的缩放转换,逻辑完全错误。这部分代码应该放到两层for循环全部结束之后再执行。
- 卷积核参数错误:3x3的平均卷积核权重应该是
1/(3*3)=1/9,你写的1/3会导致卷积结果超过0-255范围,就算前面的问题修复了也会出现过曝问题。
- 卷积核参数错误:3x3的平均卷积核权重应该是
- (次要优化点)获取原图高宽的逻辑可以调整到灰度转换之后,避免后续逻辑修改时出现维度错误。
修复后的完整代码
from skimage.exposure import rescale_intensity import numpy as np import cv2 def convolve(image, kernel): # 先拆分通道转灰度 red, green, blue = cv2.split(image) gray = (red + green + blue) / 3 # 转灰度后再取高宽更稳妥 (Hi, Wi) = gray.shape[:2] (Hk, Wk) = kernel.shape[:2] pad = (Wk - 1) // 2 # 对灰度图做填充 pad_gray = cv2.copyMakeBorder(gray, pad, pad, pad, pad, cv2.BORDER_REPLICATE) output = np.zeros((Hi, Wi), dtype="float32") # 修正遍历范围:从pad到Hi+pad,覆盖所有原图像素对应的位置 for y in range(pad, Hi + pad): for x in range(pad, Wi + pad): roi = pad_gray[y - pad:y + pad + 1, x - pad:x + pad + 1] k = (roi * kernel).sum() output[y - pad, x - pad] = k # 修正缩进:所有卷积计算完成后再做缩放和类型转换 output = rescale_intensity(output, in_range=(0, 255)) output = (output * 255).astype("uint8") return output image = cv2.imread("mandrill.png") # 修正卷积核权重为1/9 kernel = np.ones((3, 3)) * (1/9) cv2.imshow("Output", convolve(image, kernel)) cv2.waitKey(0) cv2.destroyAllWindows()
内容的提问来源于stack exchange,提问作者karlembeast
相关产品推荐
相关产品推荐

