本页对应的英文页面已更新,但尚未翻译。 若要查看最新内容,请点击此处访问英文页面。

使用 K 均值聚类实现基于颜色的分割

此示例说明如何使用 L*a*b* 颜色空间和 K 均值聚类自动分割颜色。

步骤 1:读取图像

hestain.png 中读取,这是一个带有苏木精和曙红染色组织 (H&E) 的图像。这种染色方法有助于病理学家区分不同组织类型。

he = imread('hestain.png');
imshow(he), title('H&E image');
text(size(he,2),size(he,1)+15,...
     'Image courtesy of Alan Partin, Johns Hopkins University', ...
     'FontSize',7,'HorizontalAlignment','right');

步骤 2:将图像从 RGB 颜色空间转换为 L*a*b* 颜色空间

如果忽略亮度的变化,您会在图像中看到多少种颜色?有三种颜色:白色、蓝色和粉色。请注意,您可以很轻松地在视觉上区分这些颜色。L*a*b* 颜色空间(也称为 CIELAB 或 CIE L*a*b*)使您能够量化这些视觉差异。

L*a*b* 颜色空间是从 CIE XYZ 三色值派生的。L*a*b* 空间包含光度层 'L*'、色度层 'a*'(表示颜色落在沿红-绿轴的位置)和色度层 'b*'(表示颜色落在沿蓝-黄轴的位置)。所有颜色信息都在 'a*' 和 'b*' 层。您可以使用欧几里德距离度量来测量两种颜色之间的差异。

使用 rgb2lab 将图像转换为 L*a*b* 颜色空间。

lab_he = rgb2lab(he);

步骤 3:用 K 均值聚类对基于 'a*b*' 空间的颜色进行分类

聚类是一种分离对象组的方法。K 均值聚类将每个对象视为在空间中有一个位置。它将对象划分为若干分区,使每个簇中的对象尽可能彼此靠近,并尽可能远离其他簇中的对象。K 均值聚类要求您指定要划分的簇数和用于量化两个对象之间距离的距离度量。

由于颜色信息基于 'a*b*' 颜色空间,因此您的对象是具有 'a*' 和 'b*' 值的像素。将数据转换为数据类型 single,以便与 imsegkmeans 结合使用。使用 imsegkmeans 对对象进行聚类以分为三个簇。

ab = lab_he(:,:,2:3);
ab = im2single(ab);
nColors = 3;
% repeat the clustering 3 times to avoid local minima
pixel_labels = imsegkmeans(ab,nColors,'NumAttempts',3);

对于您的输入中的每个对象,imsegkmeans 会返回一个对应于簇的索引或标签。用像素的标签标注图像中的每个像素。

imshow(pixel_labels,[])
title('Image Labeled by Cluster Index');

步骤 4:创建按颜色分割 H&E 图像的图像

使用 pixel_labels,您可以按颜色分离 hestain.png 中的对象,这将产生三个图像。

mask1 = pixel_labels==1;
cluster1 = he .* uint8(mask1);
imshow(cluster1)
title('Objects in Cluster 1');

mask2 = pixel_labels==2;
cluster2 = he .* uint8(mask2);
imshow(cluster2)
title('Objects in Cluster 2');

mask3 = pixel_labels==3;
cluster3 = he .* uint8(mask3);
imshow(cluster3)
title('Objects in Cluster 3');

步骤 5:分割核

簇 3 包含蓝色对象。请注意,有深蓝色和浅蓝色对象。您可以使用 L*a*b* 颜色空间中的 'L*' 层来分离深蓝色和浅蓝色。细胞核为深蓝色。

前面提到过,'L*' 层包含每种颜色的亮度值。提取此簇中像素的亮度值,并使用 imbinarize 用全局阈值对其设置阈值。掩膜 is_light_blue 给出了浅蓝色像素的索引。

L = lab_he(:,:,1);
L_blue = L .* double(mask3);
L_blue = rescale(L_blue);
idx_light_blue = imbinarize(nonzeros(L_blue));

复制蓝色对象的掩膜 mask3,然后从掩膜中删除浅蓝色像素。将新掩膜应用于原始图像并显示结果。只有深蓝色细胞核可见。

blue_idx = find(mask3);
mask_dark_blue = mask3;
mask_dark_blue(blue_idx(idx_light_blue)) = 0;

blue_nuclei = he .* uint8(mask_dark_blue);
imshow(blue_nuclei)
title('Blue Nuclei');