Matlab:基于颜色的分割

hs1*_*100 3 matlab image-processing k-means

今天早些时候我正在研究这个基于http://www.mathworks.com/products/demos/image/color_seg_k/ipexhistology.html和Matlab答案的脚本:

clc;
clear;
close all;
input_im=imread('C:\Users\Udell\Desktop\T2.jpg');
sz_im=size(input_im);

cform = makecform('srgb2lab');
lab_he = applycform(input_im,cform);
ab = double(lab_he(:,:,2:3));
nrows = size(ab,1);
ncols = size(ab,2);
ab = reshape(ab,nrows*ncols,2);

nColors = 3;
% repeat the clustering 3 times to avoid local minima
[cluster_idx, cluster_center] = kmeans(ab,nColors,'distance','sqEuclidean', 'Replicates',3);

pixel_labels = reshape(cluster_idx,nrows,ncols);
%imshow(pixel_labels,[]), title('image labeled by cluster index');
segmented_images = cell(1,3);
rgb_label = repmat(pixel_labels,[1 1 3]);

for k = 1:nColors
    color = input_im;
    color(rgb_label ~= k) = 0;
    segmented_images{k} = color;
end

for k=1:nColors
%figure
title_string=sprintf('objects in cluster %d',k);
%imshow(segmented_images{k}), title(title_string);
end


finalSegmentedImage=segmented_images{1};
%imshow(finalSegmentedImage);
close all;

Icombine = [input_im finalSegmentedImage];
imshow(Icombine);
Run Code Online (Sandbox Code Playgroud)

在多次运行脚本时,我注意到当组合图像(Icombine)的finalSegmentedImage = segmented_images {1}时,我得到不同的图像.为什么?我怎样才能解决结果重复的问题(例如,segmented_images {1}图像总是一样的)?

非常感谢.

图片:

在此输入图像描述

ray*_*ica 7

您得到不同结果的原因是您的颜色分割算法使用k -means聚类.我会假设你不知道这是什么,因为熟悉其工作原理的人会立即告诉你这就是为什么你每次都会得到不同的结果.事实上,每次运行此代码后得到的不同结果都是k -means聚类的自然结果,我将解释原因.

它的工作原理是,对于您拥有的某些数据,您希望将它们分组为k个组.您最初在数据中选择k个随机点,这些点将包含标签1,2,...,k.这就是我们所说的质心.然后,确定其余数据与这些点之间的接近程度.然后,您将这些点分组,以便无论哪个点最接近这些k点中的任何一个,都可以将这些点分配为属于该特定组(1,2,...,k).之后,对于每个组的所有点,您更新质心,实际上这些质心被定义为每个组的代表点.对于每个组,您计算每个k组中所有点的平均值.这些成为下一次迭代的质心.在下一次迭代中,您可以确定数据中每个点与每个质心的接近程度.你继续迭代并重复这种行为,直到质心不再移动,或者它们移动很少.

这适用于上面的代码是您正在拍摄图像,并且您希望仅使用k种可能的颜色来表示图像.因此,这些可能的颜色中的每一种都是质心.一旦找到每个像素所属的聚类,就可以将像素的颜色替换为像素所属的聚类的质心.因此,对于图像中的每个颜色像素,您需要确定该像素最佳表示的k种可能颜色中的哪一种.这是一种颜色分割的原因是因为您图像分割为仅属于k种可能的颜色.在更一般的意义上,这就是所谓的无监督分割.

现在,回到k -means.如何选择初始质心是您获得不同结果的原因.您以默认方式调用k -means,它自动确定算法将从中选择哪些初始点.因此,每次调用算法时都不能保证生成相同的初始点.如果您想重复相同的分段,无论您调用多少次kmeans,您都需要自己指定初始点.因此,您需要修改k -means调用,使其看起来像这样:

[cluster_idx, cluster_center] = kmeans(ab,nColors,'distance','sqEuclidean', ...
                                      'Replicates', 3, 'start', seeds);
Run Code Online (Sandbox Code Playgroud)

请注意,调用是相同的,但我们在k -means调用中添加了两个附加参数.该标志start表示您正在指定初始点,并且seeds是一个k x p数组,其中k是您想要的组数.在这种情况下,这与3相同nColors,即 p数据的维度.由于您正在转换和重塑数据的方式,这将是2.因此,您最终指定了一个3 x 2矩阵.但是,你有Replicate一面旗帜.这意味着k -means算法将运行您指定的特定次数,并将输出具有最小错误量的分段.因此,我们将重复kmeans调用此标志指定的次数.上述结构seeds将不再k x p,但是k x p x n,在这里n是要运行分割的次数.现在这是一个3D矩阵,其中每个2D切片确定算法的每次运行的初始点.请记住以下内容.

您如何选择这些积分取决于您.但是,如果您想随机选择这些而不是由您自己决定,但是每次调用此函数时想要重现相同的结果,则应将随机种子生成器设置为已知数字,例如123.这样,当您生成随机点时,它将始终生成相同的点序列,因此是可重现的.因此,我会在调用之前将其添加到您的代码中kmeans.

rng(123); %// Set seed for reproducibility
numReplicates = 3;
ind = randperm(size(ab,1), numReplicates*nColors); %// Randomly choose nColors colours from data
                                                   %// We are also repeating the experiment numReplicates times

%// Make a 3D matrix where each slice denotes the initial centres for each iteration
seeds = permute(reshape(ab(ind,:).', [2 nColors numReplicates]), [2 1 3]);

%// Now call kmeans
[cluster_idx, cluster_center] = kmeans(ab,nColors,'distance','sqEuclidean', ...
                                      'Replicates', numReplicates, 'start', seeds);
Run Code Online (Sandbox Code Playgroud)

请记住,您指定了Replicates标志,我们希望重复此算法一定次数.这是3.因此,我们需要做的是为算法的每次运行指定初始点.因为我们将有3个点集群,并且我们将运行此算法3次,所以我们nColors * numReplicates总共需要9个初始点(或).每组初始点必须是3D数组中的切片,这就是您在kmeans调用之前看到复杂语句的原因.

我将复制的数量作为一个变量,这样你就可以改变这个和心脏的内容,它仍然可以工作.复杂的声明,permutereshape允许我们非常容易地创建这个3D点矩阵.

请记住,randpermMATLAB 中的调用仅接受最近的第二个参数.如果上述调用randperm不起作用,请执行以下操作:

rng(123); %// Set seed for reproducibility
numReplicates = 3;
ind = randperm(size(ab,1)); %// Randomly choose nColors colours from data
ind = ind(1:numReplicates*nColors); %// We are also repeating the experiment numReplicates times

%// Make a 3D matrix where each slice denotes the initial centres for each iteration
seeds = permute(reshape(ab(ind,:).', [2 nColors numReplicates]), [2 1 3]);

%// Now call kmeans
[cluster_idx, cluster_center] = kmeans(ab,nColors,'distance','sqEuclidean', ...
                                      'Replicates', numReplicates, 'start', seeds);
Run Code Online (Sandbox Code Playgroud)

现在使用上面的代码,您应该能够每次生成相同的颜色分割结果.

祝好运!