为何plt.imshow在图像数值已修改时仍显示原始图像?
问题原因及修复方案
核心问题点
plt.imshow自动缩放导致视觉误判
你生成的img_shrunk像素值被限制在0-30区间,但plt.imshow处理uint8类型灰度图时,默认会将当前图像的像素极值映射为黑白,相当于把0-30的范围拉伸到了0-255的显示区间,视觉上和原图差异极小,让你误以为显示的是原始图像。灰度映射计算存在uint8溢出隐患
你用np.arange(256, dtype=np.uint8)创建查找表后直接做减法运算,若img_min大于某个灰度值,uint8的无符号特性会导致减法溢出(比如5-10会得到251),直接导致映射结果错误。
修复后的代码
# Load the image img = cv2.imread(current_dir + "/img.jpg", cv2.IMREAD_GRAYSCALE) plt.figure("Original Image", figsize=(6, 6)) plt.subplot(211) plt.title("Original Image") plt.imshow(img, "gray") plt.subplot(212) hist_full = cv2.calcHist([img], [0], None, [256], [0, 256]) plt.plot(hist_full) img_min = np.amin(img) img_max = np.amax(img) # 转换为float32类型,避免uint8减法溢出 gray_levels = np.arange(256, dtype=np.float32) gray_levels = np.uint8( ((gray_levels - img_min) / (img_max - img_min)) * 30 ) img_shrunk = cv2.LUT(img, gray_levels) plt.figure("Shrunk Original Image", figsize=(6, 6)) plt.subplot(211) plt.title("Shrunk Original Image") # 指定vmin和vmax,强制按0-30的范围显示,还原真实效果 plt.imshow(img_shrunk, "gray", vmin=0, vmax=30) plt.subplot(212) hist_full = cv2.calcHist([img_shrunk], [0], None, [256], [0, 256]) plt.plot(hist_full) plt.show() # 必须调用该方法才能显示图像
关键说明
- 指定
vmin=0, vmax=30后,plt.imshow会严格按照0对应黑色、30对应白色渲染,你能直观看到灰度范围压缩后的效果。 - 将查找表转换为float32类型计算,彻底避免了uint8无符号减法的溢出问题,保证直方图变化和显示效果一致。
内容的提问来源于stack exchange,提问作者Mahmood
相关产品推荐
相关产品推荐

