使用高斯混合模型对图像进行聚类

nin*_*nja 1 matlab classification cluster-analysis machine-learning mixture-model

我想使用GMM(高斯混合模型来聚类二进制图像,并且还想在二进制图像本身上绘制聚类质心).

我使用它作为我的参考:http: //in.mathworks.com/help/stats/gaussian-mixture-models.html

这是我的初始代码

 I=im2double(imread('sil10001.pbm'));
  K = I(:);
  mu=mean(K);
  sigma=std(K);
  P=normpdf(K, mu, sigma);
   Z = norminv(P,mu,sigma);
  X = mvnrnd(mu,sigma,1110);
  X=reshape(X,111,10);


 scatter(X(:,1),X(:,2),10,'ko');

options = statset('Display','final');
gm = fitgmdist(X,2,'Options',options);



idx = cluster(gm,X);
cluster1 = (idx == 1);
cluster2 = (idx == 2);


 scatter(X(cluster1,1),X(cluster1,2),10,'r+');
 hold on

  scatter(X(cluster2,1),X(cluster2,2),10,'bo');
  hold off
  legend('Cluster 1','Cluster 2','Location','NW')


  P = posterior(gm,X);

 scatter(X(cluster1,1),X(cluster1,2),10,P(cluster1,1),'+')
 hold on
 scatter(X(cluster2,1),X(cluster2,2),10,P(cluster2,1),'o')
 hold off
 legend('Cluster 1','Cluster 2','Location','NW')
 clrmap = jet(80); colormap(clrmap(9:72,:))
 ylabel(colorbar,'Component 1 Posterior Probability')
Run Code Online (Sandbox Code Playgroud)

但问题是我无法在主二进制图像中绘制从GMM接收的聚类质心.我该怎么做? 在此输入图像描述

**现在假设我有一个序列中的10个这样的图像我想将它们的平均位置的信息存储在两个单元格数组中然后我该怎么做.这是我的代码我的新问题**

    images=load('gait2go.mat');%load the matrix file
    for i=1:10

   I{i}=images.result{i};
  I{i}=im2double(I{i});

   %determine 'white' pixels, size of image can be [M N], [M N 3] or [M N 4]
  Idims=size(I{i});
  whites=true(Idims(1),Idims(2));

    df=I{i};
      %we add up the various color channels
 for colori=1:size(df,3)
  whites=whites & df(:,:,colori)>0.5;
 end

%choose indices of 'white' pixels as coordinates of data
[datax datay]=find(whites);

%cluster data into 10 clumps
  K = 10;               % number of mixtures/clusters
  cInd = kmeans([datax datay], K, 'EmptyAction','singleton',...
   'maxiter',1000,'start','cluster');

%get clusterwise means
 meanx=zeros(K,1);
 meany=zeros(K,1);  
  for i=1:K
   meanx(i)=mean(datax(cInd==i));
   meany(i)=mean(datay(cInd==i));

 end

 xc{i}=meanx(i);%cell array contaning the position of the mean for the 10    
 images
  xb{i}=meany(i);

figure;
gscatter(datay,-datax,cInd); %funky coordinates for plotting according to      
 image
 axis equal;
  hold on;
  scatter(meany,-meanx,20,'+'); %same funky coordinates


 end
Run Code Online (Sandbox Code Playgroud)

我能够分割10个图像,但没有存储在单元格数组xc和xb中的themean值.它们只存储[]代替均值的值

And*_*eak 10

我决定在你的问题上发一个答案(你的问题是由最大可能猜测决定的:P),但我写了一篇大量的介绍.请仔细阅读,因为我认为您很难理解您想要使用的方法,并且您很难理解为什么其他人无法帮助您解决问题的常用方法.您的问题存在一些问题,包括代码相关问题和概念问题.让我们从后者开始吧.

这个问题的问题

你说你想用高斯混合建模来聚类你的图像.虽然我通常不熟悉聚类,但在查看了你的参考资料以及你在别处引用的精彩SO答案(以及来自@rayryeng的快速101 )后,我认为你完全走错了轨道.

高斯混合建模,顾名思义,用高斯(即正态)分布的混合模拟您的数据集.这种方法流行的原因在于,当您对各种数量进行测量时,在许多情况下,您会发现您的数据主要分布为正态分布(这实际上是它被称为正常分布的原因).这背后的原因是中心极限定理,这意味着在许多情况下,合理独立的随机变量的总和趋向于正常.

现在,聚类只是意味着根据某些标准将数据集分成不相交的较小的束.主要标准通常是(某种)距离,因此您希望在较大的数据集中找到"紧密的数据块".您通常需要在执行GMM之前对数据进行聚类,因为已经很难找到基础数据的高斯,而不必猜测聚类.如果你让它们处理你的原始数据,我对所涉及的程序不太熟悉GMM算法可以如何工作(但我希望许多实现始终以聚类步骤开始).

为了更接近你的问题:我想你想做某种图像识别.看图片,你想得到更强烈相关的肿块.这是集群.如果你看一个动物园的照片,你会看到一头大象和一条蛇.两者都有其独特的形状,并且它们彼此很好地分开.如果你将你的图像聚集在一起(并且蛇没有骑大象,它也没有吃掉它),你会发现两个肿块:一个是大象状的肿块,另一个是蛇状的.现在,在这些数据集上使用GMM是没有意义的:大象,特别是蛇,形状不像多元高斯分布.但是,如果您只是想知道图片中不同动物的位置,那么您首先不需要这个.

仍然坚持这个例子,你应该确保将数据集中到适当数量的子集中.如果你试图将你的动物园图片聚为3个星团,你可能会得到第二条虚假的蛇:大象的鼻子.随着群集数量的增加,您的分区可能越来越不合理.

你的方法

你的代码没有给你任何合理的东西,并且有一个很好的理由:它从一开始就没有意义.看一下开头:

I=im2double(imread('sil10001.pbm'));
K = I(:);
mu=mean(K);
sigma=std(K);
X = mvnrnd(mu,sigma,1110);
X=reshape(X,111,10);
Run Code Online (Sandbox Code Playgroud)

您读取二进制图像,将其转换为double,然后将其拉伸为矢量并计算该矢量的平均值和偏差.您基本上将您的服装图像涂抹成2个值:平均强度和偏差.然后,您111*10使用这些参数生成标准法线点,并尝试在前两组111上进行GMM.这两个参数都是相同的正常参数.所以你可能得到两个重叠的高斯,围绕相同的均值,具有相同的偏差.

我认为你在网上找到的例子让你很困惑.当您执行GMM时,您已经拥有了数据,因此不应涉及伪正常数字.但是当人们发布示例时,他们也会尝试提供可重复的输入(好吧,其中一些确实如此,轻推推动眨眼).一种简单的方法是生成简单高斯的并集,然后可以将其输入GMM.

所以,我的观点是,您不必生成随机数,但必须使用图像数据本身作为您的过程的输入.而且您可能只想对图像进行聚类,而不是实际使用GMM在群集上绘制土豆,因为您想要将图像中的身体部位聚类为人体.大多数身体部位没有形如多元高斯(与男性和女性一些明显的例外).

我认为你应该做什么

如果你真的想要对你的图像进行聚类,就像你在问题中添加的图一样,那么你应该使用像k-means这样的方法.但话说回来,你已经有一个程序可以做到这一点,不是吗?所以我真的不认为我能回答这个问题,"如何用GMM对我的图像进行聚类?".相反,这里是"如何聚类我的图像?"的答案.用k-means,但至少会有一段代码在这里.

%set infile to what your image file will be
infile='sil10001.pbm';

%read file
I=im2double(imread(infile));

%determine 'white' pixels, size of image can be [M N], [M N 3] or [M N 4]
Idims=size(I);
whites=true(Idims(1),Idims(2));

%we add up the various color channels
for colori=1:Idims(3)
    whites=whites & I(:,:,colori)>0.5;
end

%choose indices of 'white' pixels as coordinates of data
[datax datay]=find(whites);

%cluster data into 10 clumps
K = 10;               % number of mixtures/clusters
cInd = kmeans([datax datay], K, 'EmptyAction','singleton',...
    'maxiter',1000,'start','cluster');

%get clusterwise means
meanx=zeros(K,1);
meany=zeros(K,1);
for i=1:K
    meanx(i)=mean(datax(cInd==i));
    meany(i)=mean(datay(cInd==i));
end

figure;
gscatter(datay,-datax,cInd); %funky coordinates for plotting according to image
axis equal;
hold on;
scatter(meany,-meanx,20,'ko'); %same funky coordinates
Run Code Online (Sandbox Code Playgroud)

这就是它的作用.它首先像你的一样读取你的图像.然后它通过检查每个颜色通道(其中可以是1,3或4)是否比0.5更亮来尝试确定"白色"像素.然后输入数据指向集群将是xy"坐标"你的白色像素(即指数).

接下来它通过集群进行kmeans.这部分代码基于已经引用的Amro答案.我不得不设置一个大的最大迭代次数,因为在图片中没有10个清晰的簇的意义上问题是不适定的.然后我们mean为每个聚类计算,并绘制聚类gscatter,并用方法绘制scatter.请注意,为了使图片在scatter绘图中朝向正确的方向,您必须在输入坐标周围移动.或者,您可以在开头定义dataxdatay相应地进行定义.

这是我的输出,使用您在问题中提供的已经处理的数字运行: 产量