【问题标题】:Matlab: Color-Based SegmentationMatlab:基于颜色的分割
【发布时间】:2014-10-30 18:04:16
【问题描述】:

今天早些时候,我正在根据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} 图像总是相同的)?

非常感谢。

图片:

【问题讨论】:

    标签: matlab image-processing k-means


    【解决方案1】:

    您得到不同结果的原因是您的颜色分割算法使用了k-means clustering。我假设你不知道这是什么,因为熟悉它的工作原理的人会立即告诉你,这就是为什么你每次都会得到不同的结果。事实上,每次运行这段代码后得到的不同结果是 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 切片确定算法每次运行的初始点。请记住这一点,以备后用。

    如何选择这些积分取决于您。但是,如果您想随机选择这些而不是由您自己决定,而是想在每次调用此函数时重现相同的结果,您应该将random seed generator 设置为已知数字,例如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 次,所以我们总共需要 9 个初始点(或nColors * numReplicates)。每组初始点都必须是 3D 数组中的一个切片,这就是为什么您会在 kmeans 调用之前看到那个复杂的语句。

    我将重复次数设为变量,这样您就可以随心所欲地更改它,它仍然可以工作。 permutereshape 的复杂语句使我们能够非常轻松地创建这个 3D 点矩阵。

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

    现在有了上面的代码,你应该可以每次都生成相同的颜色分割结果了。

    祝你好运!

    【讨论】:

    • 嗨,非常感谢。我正在使用 2012a,在添加最后一行代码时出现此错误: 使用 kmeans 时出错(第 192 行)“开始”数组的第三个维度必须与“复制”参数值匹配。 countRed 错误(第 24 行)[cluster_idx, cluster_center] = kmeans(ab,nColors,'distance','sqEuclidean', 'Replicates', 3, 'start', seed);怎么解决?
    • @user2916044 - 啊,我错过了。让我编辑我的代码。 Replicates 表示您想要多次重复分割,每次使用不同的初始点集。让我修改一下。
    • @user2916044 - 完成。这应该有希望工作。我忘记了Replicates 标志。
    • @user2916044 考虑为这些太好的答案投票 :)
    • @rayryeng 是的,最好的事情是你似乎喜欢它!人们当然会在这个过程中受益:)
    猜你喜欢
    • 1970-01-01
    • 2011-08-02
    • 2017-07-24
    • 2018-01-12
    • 1970-01-01
    • 1970-01-01
    • 2013-12-24
    • 2017-03-14
    • 1970-01-01
    相关资源
    最近更新 更多