为何skimage的slic函数处理RGB图像时返回单通道灰度输出?
SLIC分割结果为单通道灰度图的原因及解决方法
问题描述
使用Python的skimage.segmentation模块的slic函数处理RGB图像时,即使设置了multichannel=True,输出结果的形状仍为(512, 512)而非预期的(512, 512, 3),保存后的图像为完全灰度图。
输入图像:
原代码:
from skimage.segmentation import slic,mark_boundaries from skimage import io img = io.imread("luna.png", 0) print("img shape: {0}".format(img.shape)) segments = slic(img, n_segments=10, compactness=10, start_label = 1, multichannel=True) print("seg type:", type(segments)) print("seg shape: {0}".format(segments.shape)) print("seg max:", np.max(segments)) print("seg min:", np.min(segments)) seg_255 = (segments / np.max(segments)) * 255 seg_255 = seg_255.astype(np.uint8) cv2.imwrite("luna_seg.png", seg_255)
命令行输出:
img shape: (512, 512, 3) seg type: <class 'numpy.ndarray'> seg shape: (512, 512) seg max: 34 seg min: 1
输出的灰度分割图:
原因分析
SLIC的输出本质是分割标签图,每个像素值代表该像素所属的分割区域ID,因此天生是单通道格式。multichannel=True的作用仅在于告知SLIC输入是多通道图像(如RGB),让算法在颜色空间中进行聚类,并不会改变输出的形状。直接将标签图拉伸到0-255保存,自然会得到灰度图。
解决方法
要得到带色彩的分割可视化结果,可采用以下两种方式:
方法1:在原图上绘制分割边界
使用mark_boundaries函数在原图上叠加分割区域的边界,保留原图色彩的同时清晰展示分割结果。
修正代码:
from skimage.segmentation import slic, mark_boundaries from skimage import io import numpy as np import cv2 # 读取RGB图像(skimage>=0.19版本中,io.imread默认读取彩色图,无需额外参数) img = io.imread("luna.png") print("img shape: {0}".format(img.shape)) # 执行SLIC分割 segments = slic(img, n_segments=10, compactness=10, start_label=1, multichannel=True) print("seg shape: {0}".format(segments.shape)) # 生成带边界的可视化图像 boundary_img = mark_boundaries(img, segments) # 将float类型(0-1)转换为uint8格式,并转换为BGR通道适配cv2保存 boundary_img = (boundary_img * 255).astype(np.uint8) cv2.imwrite("luna_seg_boundary.png", cv2.cvtColor(boundary_img, cv2.COLOR_RGB2BGR))
方法2:生成彩色分割掩码图
使用label2rgb函数为不同的分割ID分配颜色(可选择区域平均颜色或随机颜色),生成纯彩色的分割结果图。
修正代码:
from skimage.segmentation import slic from skimage import io import numpy as np import cv2 from skimage.color import label2rgb img = io.imread("luna.png") segments = slic(img, n_segments=10, compactness=10, start_label=1, multichannel=True) # 用区域内的平均颜色填充分割区域(kind='avg'),也可省略该参数使用随机颜色 color_seg = label2rgb(segments, image=img, kind='avg') # 转换格式并保存 color_seg = (color_seg * 255).astype(np.uint8) cv2.imwrite("luna_seg_color.png", cv2.cvtColor(color_seg, cv2.COLOR_RGB2BGR))
内容的提问来源于stack exchange,提问作者Fusberta Gaudreau
相关产品推荐
相关产品推荐

