运行Python直方图图像分割代码报NumPy布尔索引赋值错误咨询
问题背景
正在学习Youtube频道DigitalSreeni的Python中基于直方图的图像分割教程,运行几乎未修改的教程配套代码时触发ValueError报错,相关代码与报错信息如下。
复现代码
from skimage.restoration import denoise_nl_means, estimate_sigma from skimage import img_as_ubyte, img_as_float, io from matplotlib import pyplot as plt import numpy as np import os print(os.getcwd()) filename = 'C:/Users/user/' f1 = (filename + '20220614_1.jpg') print(f1) img = img_as_float(io.imread(f1)) sigma_est = np.mean(estimate_sigma(img, multichannel=True)) denoise = denoise_nl_means(img, h=1.15 * sigma_est, fast_mode=True, patch_size=5, patch_distance=3, multichannel=True) denoise_ubyte = img_as_ubyte(denoise) segm1 = (denoise_ubyte <= 57) segm2 = (denoise_ubyte > 57) & (denoise_ubyte <= 110) segm3 = (denoise_ubyte > 110) & (denoise_ubyte <= 210) segm4 = (denoise_ubyte > 210) all_segments = np.zeros((denoise_ubyte.shape[0], denoise_ubyte.shape[1], 3)) all_segments[segm1] = (1,0,0) all_segments[segm2] = (0,1,0) all_segments[segm3] = (0,0,1) all_segments[segm4] = (1,1,0) plt.imshow(all_segments)
报错信息
ValueError: NumPy boolean array indexing assignment cannot assign 3 input values to the 587028 output values where the mask is true
报错原因
报错核心是布尔索引维度与赋值逻辑不匹配,具体触发逻辑:
- 代码读取的是RGB三通道彩色图像,经过去噪、
img_as_ubyte类型转换后,denoise_ubyte是形状为(图像高度, 图像宽度, 3)的三维数组。 - 直接对三维数组做阈值比较生成的
segm1~segm4四个分割掩码,同样是形状为(高度, 宽度, 3)的三维布尔数组。 - 当用三维布尔数组索引
all_segments(同形状三维数组)时,NumPy会选中所有掩码值为True的单个通道元素,报错信息里的587028就是segm1中True值的总个数。此时试图给这几十万个元素传入长度为3的颜色元组,赋值两边的元素数量完全不匹配,就会抛出该错误。
本质原因是教程代码默认处理单通道灰度图,直接传入三通道彩色图会导致生成的掩码维度不符合赋值要求。
修复方案
在生成分割掩码前,先把三通道去噪结果转为单通道灰度图,生成二维的分割掩码即可:
- 先导入灰度转换工具:
from skimage.color import rgb2gray
- 在
denoise_ubyte = img_as_ubyte(denoise)代码后新增一行,生成单通道灰度图:
denoise_gray = img_as_ubyte(rgb2gray(denoise))
- 将所有生成
segm1~segm4的判断逻辑中的denoise_ubyte替换为denoise_gray。
修改后生成的分割掩码是形状为(高度, 宽度)的二维布尔数组,用它索引三通道的all_segments数组时,会自动选中对应像素的全部3个通道,此时传入长度为3的RGB颜色元组维度完全匹配,代码可正常运行。
内容的提问来源于stack exchange,提问作者Philip Ma
相关产品推荐
相关产品推荐

