如何将单通道数组保存为色彩一致的灰度分割掩码图像
解决分割掩码保存时颜色不一致的问题
问题根源
你遇到的问题是因为mpimg.imsave默认会对输入的单通道数组做自动归一化处理:它会把当前图像数组中的最小值映射到灰度0,最大值映射到灰度255。比如:
- 第一张图最大像素值是6,标签值2会被映射到
(2/6)*255≈85 - 添加新圆形后第二张图最大像素值是12,同样的标签值2会被映射到
(2/12)*255≈42
这就导致相同标签的像素在不同图像里呈现不同灰度,破坏了标签与颜色的对应关系。
两种解决方案
方案1:用OpenCV直接保存(推荐)
OpenCV的cv2.imwrite处理单通道uint8数组时,会直接将像素值作为灰度级保存,不会做自动归一化,能保证相同标签值对应固定灰度。
修改后的代码:
import numpy as np import cv2 image = np.zeros(shape=[256, 256], dtype=np.uint8) # 绘制原有圆形(单通道无需传元组,直接传标签值即可) cv2.circle(image, center=(50, 50), radius=10, color=2, thickness=-1) cv2.circle(image, center=(100, 100), radius=10, color=3, thickness=-1) cv2.circle(image, center=(150, 150), radius=10, color=4, thickness=-1) cv2.circle(image, center=(75, 200), radius=10, color=5, thickness=-1) cv2.circle(image, center=(200, 89), radius=10, color=6, thickness=-1) # 添加额外圆形(Image #2) cv2.circle(image, center=(21, 230), radius=5, color=7, thickness=-1) cv2.circle(image, center=(149, 250), radius=5, color=12, thickness=-1) # 直接保存单通道灰度掩码 cv2.imwrite('image_mask.png', image)
方案2:固定Matplotlib的映射范围
如果一定要用mpimg.imsave,需要通过vmin和vmax参数固定整个数据集的标签值范围,强制所有图像按同一规则映射灰度。
修改后的代码:
import numpy as np import cv2 import matplotlib.image as mpimg image = np.zeros(shape=[256, 256], dtype=np.uint8) cv2.circle(image, center=(50, 50), radius=10, color=2, thickness=-1) cv2.circle(image, center=(100, 100), radius=10, color=3, thickness=-1) cv2.circle(image, center=(150, 150), radius=10, color=4, thickness=-1) cv2.circle(image, center=(75, 200), radius=10, color=5, thickness=-1) cv2.circle(image, center=(200, 89), radius=10, color=6, thickness=-1) cv2.circle(image, center=(21, 230), radius=5, color=7, thickness=-1) cv2.circle(image, center=(149, 250), radius=5, color=12, thickness=-1) # 指定vmin为背景值0,vmax为数据集最大标签值(这里是12),确保所有图像映射一致 mpimg.imsave('image_mask.png', image, vmin=0, vmax=12, cmap='gray')
注意:如果后续新增更大的标签值,需要同步更新
vmax的数值,否则超出范围的标签会被截断到255灰度。
内容的提问来源于stack exchange,提问作者Deep
相关产品推荐
相关产品推荐

