图像模糊C均值聚类分割代码

 

转自:直觉模糊C均值聚类与图像阈值分割 - liyuefeilong的专栏 - CSDN博客 https://blog.csdn.net/liyuefeilong/article/details/43816495

 

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% 主函数
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function main
ima = imread('MR6.jpg');
% 先设定FCM的几个初始参数
options=[2;    % FCM公式中的参数m
         100;    % 最大迭代次数
         1e-5];    % 目标函数的最小误差        
class_number = 4;  % 分为4类
imt = ImageSegmentation(ima,class_number,options)
subplot(1,2,1),imshow(ima),title('原图');
subplot(1,2,2),imshow(imt); %显示生成的分割的图像
kk = strcat('分割成',int2str(class_number),'类的输出图像');
title(kk);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% ImageSegmentation()函数:实现聚类分割图像
% 输入:file为灰度图像文件 cluster_n为聚类类别个数 options为预设的初始参数
% 输出分割后的图像  
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function imt = ImageSegmentation(file, cluster_n, options) 
ima = file;
I = im2double(file); 
[x,y] = size(ima);
number = x * y;  % 图像的元素个数numel(I)
data = reshape(I,number,1); %将矩阵元素转换为一列数据
[center, U] = FCMprocess(data,cluster_n,options); %调用FCMData函数进行聚类
% 对于每个元素对不同聚类中心的隶属度,找出最大的那个隶属度
maxU = max(U); % 找出每一列的最大隶属度
temp = sort(center); 
for i = 1:cluster_n; % 按聚类结果分割图像
    % 前面求出每个元素的最大隶属度,属于各聚类中心的元素坐标,并存放这些坐标
    % 调用eval函数将括号里的字符串转化为命令执行
    eval(['class_',int2str(i), '= find(U(', int2str(i), ',:) == maxU);']); 
    %gray = round(255 * (i-1) / (cluster_n-1));
        index = find(temp == center(i)); 
    switch index 
        case 1 
            gray = 0; 
        case cluster_n 
            gray = 255; 
        otherwise 
            gray = fix(255*(index-1)/(cluster_n-1)); 
    end 
    eval(['I(class_',int2str(i), '(:))=', int2str(gray),';']); 
end; 
imt = mat2gray(I); 

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% 用于计算聚类中心、隶属度矩阵和目标函数
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [center, U] = FCMprocess(data, cluster_num, options) 
%data为聚类数据,cluster_num为类别数
m = options(1);        % 参数m
max_iteration = options(2);        % 最终的迭代次数
min_deviation = options(3);        % 最小判别误差
data_number = size(data, 1);    % 元素个数
obj_function = zeros(max_iteration, 1); % obj_function用于存放目标函数的值
% 生成隶属度矩阵U
U = rand(cluster_num, data_number); % 随机生成隶属度矩阵U
sumU = sum(U,1);   % 计算U中每列元素和
for k = 1:data_number
    U(:,k) = U(:,k) ./ sumU(k);  % 对隶属矩阵U进行归一化处理
end

for i = 1:max_iteration
    [U, center, obj_function(i)] = FCMStep(data, U, cluster_num, m); %调用FCMStep函数进行迭代
        fprintf('第%d次迭代, 目标函数值为%f\n', i, obj_function(i));
    % 检查迭代终止条件
    if i > 1,
        if abs(obj_function(i) - obj_function(i-1)) < min_deviation
        break; 
        end
    end
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% 该函数用于每次迭代过程
function [newU,center,obj_function] = FCMStep(data, U, cluster_num, m)
% data为被聚类数据,U为隶属度矩阵,cluster_num为聚类类别数,m为FCM中的参数m
% 函数调用后得到新的隶属度矩阵newU,聚类中心center,目标函数值obj_function
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% 以下是计算模糊隶属度Ut
    [x,y] = size(U);
    A = ones(x,y);
          a = 0.85;
            Ut = abs(A - U -(A - (U).^a).^(1/a));
            Ud = U  + Ut;
            [j,k,l] = size(data);
            pp =  y;
            pai = (sum(Ut,2)) ./pp;
            obj = sum(pai.*exp(1-pai));
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%            Ud = U;
%            obj = 0;
 nf = Ud;
mf = Ud.^m;       % FMC中的U^m
%  center = nf*data./((ones(size(data, 2), 1)*sum(nf'))'); % 得到聚类中心

   data1 = zeros(x,y);
   data1(1,:) = data';
   data1(2,:) = data';
   data1(3,:) = data';
   data1(4,:) = data';
%   data1(5,:) = data';
  center = sum(nf.*data1,2)./sum(nf,2); % 得到聚类中心

dist = Distance(center, data);      % 调用myfcmdist函数计算聚类中心与被聚类数据的距离
obj_function = sum(sum((dist.^2).*mf))+obj;  % 得到目标函数值
tmp = dist.^(-2/(m-1));      % 如果迭代次数不为1,计算新的隶属度矩阵
 newU = tmp./(ones(cluster_num, 1)*sum(tmp)); % U_new为新的隶属度矩阵

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Distance()函数用于计算聚类中心与被聚类数据的距离
% center为聚类中心,data为被聚类数据,输出各元素到聚类中心的距离out
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function out = Distance(center, data)
  
 data_number = size(data,1);
 class_number = size(center, 1);
 kk = ones(data_number,1); % 构造与数据大小相同的全1矩阵kk
 out = zeros(class_number, data_number);
  if size(center, 2) > 1, %若类别数大于1
      for k = 1:class_number
           out(k, :) = sqrt(sum(((data - kk...
                       *center(k,:)).^2)'));
     end
  else    % data为一维数据
      for k = 1:class_number
           out(k, :) = abs(center(k) - data)';
      end
  end

 

posted @ 2019-06-10 21:11  ostartech  阅读(1962)  评论(0编辑  收藏  举报