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

我想使用高斯混合模型(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')

但问题是我无法在原始二值图像上绘制从GMM获得的聚类中心点。我该怎么做?enter image description here

**现在假设我有一系列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

我能够得到10张图像的分割结果,但无法将平均值存储在单元数组xc和xb中。它们只存储了[]而不是平均值的位置信息


回答:

我决定回答你的问题(你的问题是通过最大似然估计确定的:P),但我写了一个详细的介绍。请仔细阅读,因为我认为你对你想使用的方法理解有困难,而且你也难以理解为什么别人无法用你通常的提问方式帮助你。你的问题有几个问题,包括代码相关和概念上的问题。让我们从后者开始。

问题的症结

你说你想用高斯混合模型对图像进行聚类。虽然我对聚类不太熟悉,但在查看了你的参考资料你在他处引用的精彩的SO回答(以及来自@rayryeng的快速入门)后,我认为你完全走错了路。

高斯混合模型,正如其名,是用高斯(即正态)分布的混合来建模你的数据集。这种方法之所以流行,是因为当你对各种量进行测量时,在许多情况下,你会发现你的数据大多像正态分布(这实际上是它被称为正态的原因)。其背后的原因是中心极限定理,它暗示在许多情况下,合理独立的随机变量的总和往往是正态的。

现在,聚类另一方面,仅仅意味着根据某些标准将你的数据集分成不相交的较小组。主要标准通常是(某种形式的)距离,所以你想在你的大数据集中找到“接近的数据块”。你通常需要在执行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);

你读取你的二值图像,将其转换为双精度,然后将其拉伸成一个向量并计算该向量的均值和标准差。你基本上是将整个图像抹成了两个值:一个平均强度和一个偏差。然后你用这些参数生成111*10个标准正态点,并尝试对前两组111个点进行GMM。这两组都是独立的正态分布,具有相同的参数。所以你可能会得到两个重叠的高斯分布,围绕着相同的均值和相同的偏差。

我认为你在线找到的例子让你感到困惑。当你进行GMM时,你已经有了你的数据,所以不应该涉及伪正态数。但当人们发布示例时,他们也试图提供可重现的输入(嗯,其中一些人会这样做,暗示暗示)。一种简单的方法是生成简单高斯分布的联合,然后将其输入到GMM中。

所以,我的观点是,你不需要生成随机数,而是应该使用图像数据本身作为你的程序的输入。而且你可能只是想聚类你的图像,而不是实际使用GMM在你的聚类上画土豆,因为你想在关于人的图像中聚类身体部位。大多数身体部位像多元高斯分布(对于男性和女性有一些明显的例外)。

我认为你应该做的事情

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

%set infile to what your image file will beinfile='sil10001.pbm';%read fileI=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 channelsfor 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 clumpsK = 10;               % number of mixtures/clusterscInd = kmeans([datax datay], K, 'EmptyAction','singleton',...    'maxiter',1000,'start','cluster');%get clusterwise meansmeanx=zeros(K,1);meany=zeros(K,1);for i=1:K    meanx(i)=mean(datax(cInd==i));    meany(i)=mean(datay(cInd==i));endfigure;gscatter(datay,-datax,cInd); %funky coordinates for plotting according to imageaxis equal;hold on;scatter(meany,-meanx,20,'ko'); %same funky coordinates

这是它所做的。它首先像你的一样读取你的图像为双精度。然后它尝试通过检查每个颜色通道(可以是1、3或4)的亮度是否大于0.5来确定“白色”像素。然后你输入到聚类中的数据点将是你的白色像素的xy“坐标”(即索引)。

接下来它通过kmeans进行聚类。这部分代码大致基于已经引用的Amro的回答。我不得不设置一个大的最大迭代次数,因为这个问题在图片中没有10个明显的聚类的情况下是病态的。然后我们计算每个聚类的mean,并使用gscatter绘制聚类,使用scatter绘制均值。请注意,为了在scatter图中使图片朝向正确的方向,你必须调整输入坐标。或者你可以在开始时相应地定义dataxdatay

这是我的输出,使用你问题中提供的已经处理过的图运行的:output

Related Posts

使用LSTM在Python中预测未来值

这段代码可以预测指定股票的当前日期之前的值,但不能预测…

如何在gensim的word2vec模型中查找双词组的相似性

我有一个word2vec模型,假设我使用的是googl…

dask_xgboost.predict 可以工作但无法显示 – 数据必须是一维的

我试图使用 XGBoost 创建模型。 看起来我成功地…

ML Tuning – Cross Validation in Spark

我在https://spark.apache.org/…

如何在React JS中使用fetch从REST API获取预测

我正在开发一个应用程序,其中Flask REST AP…

如何分析ML.NET中多类分类预测得分数组?

我在ML.NET中创建了一个多类分类项目。该项目可以对…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注