Main Content

このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。

k-means クラスタリングを使った色ベースのセグメンテーション

この例では、k-means クラスタリングを使って自動的に色をセグメント化する方法を示します。

クラスタリングはオブジェクトのグループを区分する方法です。k-means クラスタリングは、各オブジェクトを空間配置されたオブジェクトとして取り扱います。これは、各クラスター内のオブジェクトができるだけ互いに近くにあり、他のクラスターのオブジェクトからはできるだけ遠くにある分割を探します。関数 imsegkmeans を使用して、イメージ ピクセルを値ごとに色空間内のクラスターに分けます。この例では、RGB 色空間と L*a*b* 色空間でイメージの k-means クラスタリングを実行することで、異なる色空間の使用によりセグメンテーション結果をどのように改善できるのかを説明します。

手順 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")

Figure contains an axes object. The axes object with title H&E Image contains 2 objects of type image, text.

手順 2: k-means クラスタリングを使用した RGB 色空間での色の分類

RGB 色空間で k-means クラスタリングを使用してイメージを 3 つの領域にセグメント化します。入力イメージのピクセルごとに、関数 imsegkmeans はクラスターに対応するラベルを返します。

ラベル イメージを、元のイメージの上にオーバーレイとして表示します。ラベル イメージでは誤って、白、明るい青紫、明るいピンクの領域が一緒にグループ化されています。RGB 色空間は各チャネル (赤、緑、青) 内で明るさと色情報を組み合わせるので、異なる 2 色は明るいバージョンになるほど近づくことになり、明るいバージョンは、同じ 2 色の暗いバージョンよりセグメント化するのが難しくなります。

numColors = 3;
L = imsegkmeans(he,numColors);
B = labeloverlay(he,L);
imshow(B)
title("Labeled Image RGB")

Figure contains an axes object. The axes object with title Labeled Image RGB contains an object of type image.

手順 3: イメージを RGB 色空間から L*a*b* 色空間に変換

L*a*b* 色空間は、イメージの輝度と色を分離します。このため、明るさに関係なく、色によって領域をセグメント化することが容易になります。また、この色空間は、イメージ内の白、青紫、ピンクの個々の領域に対する人間の視知覚により近いものとなります。

L*a*b* 色空間は CIE XYZ 三刺激値から導出されます。L*a*b* 空間は、輝度レイヤー L*、赤-緑軸方向における色の位置を示す色度レイヤー a*、および青-黄軸方向における色の位置を示す色度レイヤー b* から構成されます。すべての色情報は、a* および b* レイヤーにあります。

関数 rgb2lab を使用して、イメージを L*a*b* 色空間に変換します。

lab_he = rgb2lab(he);

手順 4: k-means クラスタリングを使用した a*b* 空間での色の分類

色情報のみを使用してイメージをセグメント化するには、イメージを lab_he の a* および b* の値に制限します。関数 imsegkmeans で使用するためにイメージをデータ型 single に変換します。関数 imsegkmeans を使用して、イメージ ピクセルを 3 つのクラスターに分けます。局所的最小値への適合を避けるために、名前と値の引数 NumAttempts の値を、初期クラスター重心位置を変えてクラスタリングを 3 回繰り返すように設定します。

ab = lab_he(:,:,2:3);
ab = im2single(ab);
pixel_labels = imsegkmeans(ab,numColors,NumAttempts=3);

ラベル イメージを、元のイメージの上にオーバーレイとして表示します。新しいラベル イメージでは、白、青紫、ピンクで染色された組織の領域が、よりはっきりと分離されています。

B2 = labeloverlay(he,pixel_labels);
imshow(B2)
title("Labeled Image a*b*")

Figure contains an axes object. The axes object with title Labeled Image a*b* contains an object of type image.

手順 5: H&E イメージを色でセグメント化するイメージの作成

pixel_labels を使用して、元のイメージ hestain.png 内のオブジェクトを色で分けることができます。この結果は、3 つのマスクされたイメージになります。

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

Figure contains an axes object. The axes object with title Objects in Cluster 1 contains an object of type image.

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

Figure contains an axes object. The axes object with title Objects in Cluster 2 contains an object of type image.

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

Figure contains an axes object. The axes object with title Objects in Cluster 3 contains an object of type image.

手順 6: 細胞核のセグメント化

クラスター 3 には青いオブジェクトのみが含まれています。紺色と水色のオブジェクトがあることに注目してください。L*a*b* 色空間の L* レイヤーを使用して、水色から紺色を分離します。細胞核は紺色です。

L* レイヤーには各ピクセルの明度の値が含まれています。このクラスターのピクセルの明度の値を抽出し、関数 imbinarize を使用して、それらの値をグローバルしきい値でしきい値処理します。マスク idx_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")

Figure contains an axes object. The axes object with title Blue Nuclei contains an object of type image.

参考

関連するトピック