基于KMeans(K均值)的图像分割matlab程序

KMeans图像分割算法是一种典型的分割算法。其主要思想就是首先随机(起始值其实很重要)选取K个特征值作为聚类中心,然后对于每个像素点计算其到各聚类中心的距离,将其划归到距离最近的类中(也可以进行软分类,即给出其属于各类的概率),然后计算各类中元素的(加权)均值作为新的聚类中心。重复上述操作直到收敛或者达到设定迭代次数。下面给出本人编写的一个matlab示例程序及处理结果。

代码:

function [sg,normMuDiff]=KMeansSeg(img,k,Mu,eps)
normMuDiff=[];
m=size(img,1);
n=size(img,2);
img=double(img);
M=reshape(img,m*n,size(img,3));
% index=randperm(m*n);
% Mu=M(index(1:k),:);
flag=1;
Cov=repmat(eye(size(img,3)),1,1,k); %k个聚类的协方差
Label=zeros(m*n,1);

iter=1;
figure;
while flag
    old_Mu=Mu;
    Num=zeros(1,k);
    ClassedPixs=zeros(m*n,size(img,3),k); %分到k个类中的像素值
    w=zeros(m*n,k); %各像素点对于聚类的权重矩阵
    C=zeros(size(img,3),size(img,3),k);
    for j=1:k
        invCov=inv(Cov(:,:,j));
        C(:,:,j)=invCov/norm(invCov);%使用Mahalanobis距离(即马氏距离)度量
    end
    for i=1:m*n
        dis=zeros(k,1);
        for j=1:k
            dis(j)=(M(i,:)-Mu(j,:))*C(:,:,j)*(M(i,:)-Mu(j,:))'; 
        end
        maxIdx=find(dis==min(dis));
        label=maxIdx(1);
        Label(i)=label;
        Num(label)=Num(label)+1;
        ClassedPixs(Num(label),:,label)=M(i,:);
        w(Num(label),label)=1/(sqrt(min(dis))+1); %避免被0除的情况
    end
    w=w./repmat(sum(w),m*n,1); %权重归一化
    % 更新协方差Cov
    for j=1:k
        PixsThisClass=ClassedPixs(1:Num(j),:,j);
        if Num(j)~=0      
            Cov(:,:,j)=cov(PixsThisClass)+0.01*rand(size(img,3)); %加随机量以防止矩阵奇异
            Mu(j,:)=sum(repmat(w(1:Num(j),j),1,size(img,3)).*PixsThisClass);
        end
    end
    normDiff=norm(old_Mu-Mu);
    if  normDiff<eps
        flag=0;
    end
    normMuDiff=[normMuDiff;normDiff];
    sg=reshape(Label,m,n);
    
    % 录制gif
    imshow(mat2gray(sg));
    F=getframe(gcf);
    I=frame2im(F);
    [I,map]=rgb2ind(I,256);
    if iter == 1
        imwrite(I,map,'test.gif','gif','Loopcount',inf,'DelayTime',0.2);
    else
        imwrite(I,map,'test.gif','gif','WriteMode','append','DelayTime',0.2);
    end
    iter=iter+1;
end

脚本:

clear all;close all;clc;
img=imread('onion.png');
% 初始值是在图中黄、绿、红、白、紫部分随机取一点得到的RGB值
Mu=[255 220 50;...
    115 124 31;...
    216 50 39;...
    247 215 185;...
    75 45 75];
[sg,normMuDiff]=KMeansSeg(img,5,Mu,10^-2);
figure,imshow(mat2gray(sg));
figure,plot(1:length(normMuDiff),normMuDiff,'g-');

原图:

标题

运行结果:

可以看出,误差值随迭代总体呈下降趋势,但也可能出现回弹,所以推荐使用固定迭代次数以结束循环。

  • 13
    点赞
  • 91
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
K均值聚类(K-means clustering)是一种常用于图像分割的算法。在Matlab中,可以使用以下步骤进行基于K均值图像分割。 1. 导入图像:使用imread函数导入待分割的图像。 2. 数据预处理:对图像进行预处理来消除噪声等干扰。可以使用图像滤波方法如中值滤波或高斯滤波来平滑图像。 3. 初始化聚类中心点:选择K个初始点作为聚类中心。可以随机选择数据点作为初始聚类中心,或者使用其他启发式方法。 4. 样本分配:将每个像素点分配给距离最近的聚类中心。可以使用欧式距离来衡量样本与聚类中心的相似度。 5. 更新聚类中心:计算每个聚类的平均值,并将其作为新的聚类中心。 6. 重复步骤4和5,直到聚类中心不再发生变化,或达到最大迭代次数。 7. 图像分割:将每个像素点标记为与之最近的聚类中心类别。可以使用不同的颜色或灰度值来表示不同类别。 8. 显示结果:通过imshow函数显示分割结果图像。 需要注意的是,K均值聚类算法对初始聚类中心的选择非常敏感,不同的初始点可能会导致不同的分割结果。因此,在实际应用中,可能需要多次运行算法并选择最好的结果。 另外,K均值聚类算法在面对图像复杂性较高、含有重叠区域或阴影等情况时,可能会出现一些局限性。因此,对于复杂的图像分割问题,可能需要考虑使用其他更高级的分割算法。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值