Matlab:基于颜色的分割 [英] Matlab: Color-Based Segmentation

查看:232
本文介绍了Matlab:基于颜色的分割的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

今天早些时候,我正在根据。我会假设你不知道这是什么,因为熟悉其工作原理的人会立即告诉你这就是为什么你每次都会得到不同的结果。事实上,每次运行此代码后得到的不同结果都是 k -means聚类的自然结果,我将解释原因。



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



这适用于上面的代码是你正在采取的图像,您希望仅使用 k 可能的颜色来表示图像。因此,这些可能的颜色中的每一种都是质心。一旦找到每个像素所属的簇,就可以将像素的颜色替换为像素所属的簇的质心。因此,对于图像中的每个颜色像素,您需要确定哪个 k 可能的颜色,这个像素最好用哪个颜色表示。这是一种颜色分割的原因是因为您分割图像只属于 k 可能的颜色。在更广泛的意义上,这就是所谓的无监督分割



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

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

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



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

  RNG(123); %//为再现性设置种子
numReplicates = 3;
ind = randperm(size(ab,1),numReplicates * nColors); %//从数据中随机选择nColors颜色
%//我们也在重复实验numReplicates次

%//制作一个3D矩阵,其中每个切片表示每次迭代的初始中心
seeds = permute(reshape(ab(ind,:)。',[2 nColors numReplicates]),[2 1 3]);

%//现在调用kmeans
[cluster_idx,cluster_center] = kmeans(ab,nColors,'distance','sqEuclidean',...
'Replicates',numReplicates ,'开始',种子);

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

我将重复次数作为一个变量,这样你就可以改变它并改变你内心的内容,它仍然有效。 permute <的复杂陈述/ a>和 重塑 允许我们非常轻松地创建这个3D点矩阵。



请记住调用 randperm 仅接受了最近的第二个参数。如果以上对 randperm 的调用不起作用,请改为:

  RNG(123); %//为再现性设置种子
numReplicates = 3;
ind = randperm(size(ab,1)); %//从数据中随机选择nColors颜色
ind = ind(1:numReplicates * nColors); %//我们也在重复实验numReplicates次

%//制作一个3D矩阵,其中每个切片表示每次迭代的初始中心
seeds = permute(重新形成(ab,ind, :)。',[2 nColors numReplicates]),[2 1 3]);

%//现在调用kmeans
[cluster_idx,cluster_center] = kmeans(ab,nColors,'distance','sqEuclidean',...
'Replicates',numReplicates ,'开始',种子);






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



祝你好运!


Earlier today I was working on this script based on http://www.mathworks.com/products/demos/image/color_seg_k/ipexhistology.html and Matlab answers:

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);

While running the script multiply times I noticed that I get different images when finalSegmentedImage=segmented_images{1} for the combined image (Icombine). Why? And how can I fix it that the results will be repetitive (e.g., segmented_images{1} image will be always the same)?

Thanks a lot.

The image:

解决方案

The reason why you are getting different results is the fact that your colour segmentation algorithm uses k-means clustering. I'm going to assume you don't know what this is as someone familiar in how it works would instantly tell you that this is why you're getting different results every time. In fact, the different results you are getting after you run this code each time are a natural consequence to k-means clustering, and I'll explain why.

How it works is that for some data that you have, you want to group them into k groups. You initially choose k random points in your data, and these will have labels from 1,2,...,k. These are what we call the centroids. Then, you determine how close the rest of the data are to each of these points. You then group those points so that whichever points are closest to any of these k points, you assign those points to belong to that particular group (1,2,...,k). After, for all of the points for each group, you update the centroids, which actually is defined as the representative point for each group. For each group, you compute the average of all of the points in each of the k groups. These become the new centroids for the next iteration. In the next iteration, you determine how close each point in your data is to each of the centroids. You keep iterating and repeating this behaviour until the centroids don't move anymore, or they move very little.

How this applies to the above code is that you are taking the image and you want to represent the image using only k possible colours. Each of these possible colours would thus be a centroid. Once you find which cluster each pixel belongs to, you would replace the pixel's colour with the centroid of the cluster that pixel belongs to. Therefore, for each colour pixel in your image, you want to decide which out of the k possible colours this pixel would be best represented with. The reason why this is a colour segmentation is because you are segmenting the image to belong to only k possible colours. This, in a more general sense, is what is called unsupervised segmentation.

Now, back to k-means. How you choose the initial centroids is the reason why you are getting different results. You are calling k-means in the default way, which automatically determines which initial points the algorithm will choose from. Because of this, you are not guaranteed to generate the same initial points each time you call the algorithm. If you want to repeat the same segmentation no matter how many times you call kmeans, you will need to specify the initial points yourself. As such, you would need to modify the k-means call so that it looks like this:

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

Note that the call is the same, but we have added two additional parameters to the k-means call. The flag start means that you are specifying the initial points, and seeds is a k x p array where k is how many groups you want. In this case, this is the same as nColors, which is 3. p is the dimension of your data. Because of the way you are transforming and reshaping your data, this is going to be 2. As such, you are ultimately specifying a 3 x 2 matrix. However, you have a Replicate flag there. This means that the k-means algorithm will run a certain number of times specified by you, and it will output the segmentation that has the least amount of error. As such, we will repeat the kmeans calls for as many times as specified with this flag. The above structure of seeds will no longer be k x p but k x p x n, where n is the number of times you want to run the segmentation. This is now a 3D matrix, where each 2D slice determines the initial points for each run of the algorithm. Keep this in mind for later.

How you choose these points is up to you. However, if you want to randomly choose these and not leave it up to you, but want to reproduce the same results every time you call this function, you should set the random seed generator to be a known number, like 123. That way, when you generate random points, it will always generate the same sequence of points, and is thus reproducible. Therefore, I would add this to your code before calling 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);

Bear in mind that you specified the Replicates flag, and we want to repeat this algorithm a certain number of times. This is 3. Therefore, what we need to do is specify initial points for each run of the algorithm. Because we are going to have 3 clusters of points, and we are going to run this algorithm 3 times, we need 9 initial points (or nColors * numReplicates) in total. Each set of initial points has to be a slice in a 3D array, which is why you see that complicated statement just before the kmeans call.

I made the number of replicates as a variable so that you can change this and to your heart's content and it'll still work. The complicated statement with permute and reshape allows us to create this 3D matrix of points very easily.

Bear in mind that the call to randperm in MATLAB only accepted the second parameter as of recently. If the above call to randperm doesn't work, do this instead:

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);


Now with the above code, you should be able to generate the same colour segmentation results every time.

Good luck!

这篇关于Matlab:基于颜色的分割的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆