Matlab:基于颜色的细分

hs100

今天早些时候,我正在基于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);

在运行脚本的过程中,我发现当针对组合图像(Icombine)的finalSegmentedImage = segmented_images {1}时,会得到不同的图像。为什么?我该如何解决它的结果将是重复的(例如,segmented_images {1}图像将始终相同)?

非常感谢。

图片:

在此处输入图片说明

雷瑞恩

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

它的工作方式是,对于您拥有的某些数据,您要将其分组为k个组。最初,您在数据中选择了k个随机点,这些随机点的标签为1,2,...,k这些就是我们所说的质心然后,您确定其余数据与这些点的距离有多近。然后,您可以对这些点进行分组,以便无论哪个点最接近这k个点中的任何一个,都可以将这些点分配为属于该特定组(1,2,...,k)。之后,针对每个组的所有点,更新质心,实际上质心定义为每个组的代表点。对于每个组,您需要计算k个点中所有点的平均值组。这些成为下一次迭代质心。在下一次迭代中,您将确定数据中的每个点与每个形心的接近程度您不断迭代并重复此行为,直到质心不再移动或它们很少移动为止。

这对上面的代码的适用方式是您正在拍摄图像,并且只想使用k种可能的颜色表示图像因此,这些可能的颜色中的每一个将是一个质心。一旦找到每个像素所属的群集,就可以将像素的颜色替换为该像素所属的群集的质心。因此,对于图像中的每个彩色像素,您都需要决定用哪种像素可以最好地代表k种可能的颜色。之所以进行颜色分割,是因为您图像分割为仅属于k种可能的颜色。从更一般的意义上讲,这就是所谓的无监督分割

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

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

注意,调用是相同的,但是我们在k -means调用中添加了两个附加参数该标志start意味着您正在指定初始点,并且seeds是一个k x p数组,其中k是您想要的组数。在这种情况下,这与相同nColors,即3.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);

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

我将重复次数设置为变量,以便您可以更改此设置以及您的内心需求,并且仍然可以使用。纷繁复杂的语句permute,并reshape让我们能够很容易地创建点的这个3D矩阵。

请记住,randperm最近在MATLAB中对的调用仅接受第二个参数。如果上述对的调用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);

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

祝你好运!

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章