You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何skimage的slic函数处理RGB图像时返回单通道灰度输出?

SLIC分割结果为单通道灰度图的原因及解决方法

问题描述

使用Python的skimage.segmentation模块的slic函数处理RGB图像时,即使设置了multichannel=True,输出结果的形状仍为(512, 512)而非预期的(512, 512, 3),保存后的图像为完全灰度图。

输入图像:
输入的RGB图像

原代码:

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 13:03:17