1.myfcm 函数
function [center, U, obj_fcn] = myfcm(data, cluster_n, options)
%data 为聚类数据,cluster_n 为类别数
%判断函数参数个数
if nargin ~= 2 & nargin ~= 3,
error('参数太多或太少');
end
data_n = size(data, 1); %data 第一维大小
in_n = size(data, 2); %data 第二维大小
% 可以改变下列数据设置默认的 options 参数
default_options = [2; % FCM 中的参数 m
100; % 最大迭代次数
1e-5;
1]; % 迭代过程中显示
% 判别误差 epsonal
if nargin == 2,
options = default_options;
else
% 如果"options" 没有完全指定,则以 default_options 中的部分进行补充
if length(options) < 4,
tmp = default_options;
tmp(1:length(options)) = options;
options = tmp;
end
% 如果 options 中的一些参数不是数字,则以 default_options 中的代替
nan_index = find(isnan(options)==1); %找到 options 中的非数字元素下标
options(nan_index) = default_options(nan_index);
if options(1) <= 1
error('FCM 中参数 m 应大于 1!');
end
end
expo = options(1);
max_iter = options(2);
min_impro = options(3);
display = options(4);
% expo 存放参数 m
% 最大迭代次数
% 判别误差
% 迭代过程是否显示
obj_fcn = zeros(max_iter, 1); % obj_fcn 为目标函数值数组
U = myfcminit (cluster_n, data_n);
%调用 myfcminit 函数初始化隶属度矩阵 U
for i = 1:max_iter
[U, center, obj_fcn(i)] = myfcmstep(data, U, cluster_n, expo); %调用 myfcmstep 函数进行一
次迭代
if display==1
fprintf('迭代次数 = %d, obj. fcn = %f\n', i, obj_fcn(i));
end
% 检查迭代终止条件
if i > 1,
if abs(obj_fcn(i) - obj_fcn(i-1)) < min_impro
break;
end
end
end
iter_n = i;% iter_n 为实际迭代次数
obj_fcn(iter_n+1:max_iter) = [];
2.myfcminit 函数,用于对隶属度矩阵进行初始化
function U = myfcminit (cluster_n, data_n)
%
% U 为隶属度矩阵,大小为:类别数*被聚类数据元素个数
%参数 cluster_n 为聚类类别数
%data_n 为被聚类数据的元素个数
%
U = rand(cluster_n, data_n); %随机生成隶属度矩阵 U
col_sum = sum(U);%计算 U 中每列元素和
U = U./col_sum(ones(cluster_n, 1), :); %保证 U 中每列的隶属度值之和为 1
3. myfcmstep 函数用于聚类过程中的每次迭代
function [U_new, center, obj_fcn] = myfcmstep (data, U, cluster_n, expo)
%
% data 为被聚类数据,U 为隶属度矩阵,cluster_n 为聚类类别数,expo 为 FCM 中的参数 m
% 函数调用后得到新的隶属度矩阵 U_new,聚类中心 center,目标函数值 obj_fcn
%
mf = U.^expo;
center = mf*data./((ones(size(data, 2), 1)*sum(mf'))'); % 得到聚类中心
dist = myfcmdist (center, data);
距离
obj_fcn = sum(sum((dist.^2).*mf)); % 得到目标函数值
tmp = dist.^(-2/(expo-1));
U_new = tmp./(ones(cluster_n, 1)*sum(tmp)); % U_new 为新的隶属度矩阵
% 如果迭代次数不为 1,计算新的隶属度矩阵
% FMC 中的 U^m
% 调用 myfcmdist 函数计算聚类中心与被聚类数据的
4.myfcmdist 函数用于计算聚类中心与被聚类数据的距离
function out =myfcmdist (center, data)
%
% center 为聚类中心,data 为被聚类数据
%
out = zeros(size(center, 1), size(data, 1));
if size(center, 2) > 1, %若聚类中心数据大于 1,即聚类类别>=2
for k = 1:size(center, 1),
out(k, :) = sqrt(sum(((data-ones(size(data, 1), 1)*center(k, :)).^2)'));
end
else % data 为一维数据
for k = 1:size(center, 1),
out(k, :) = abs(center(k)-data)';
end
end
5.fcmapp 函数实现聚类分割图像
function myfcmseg(file, cluster_n)
% file: 图像文件.
% cluster_n: 聚类类别数.
eval(['info=imfinfo(''',file, ''');']); %获取文件信息
switch info.ColorType
case 'truecolor' %真彩色图像
eval(['RGB=imread(''',file, ''');']);
I = rgb2gray(RGB);
clear RGB;
case 'indexed' %索引图像
eval(['[X, map]=imread(''',file, ''');']);
I = ind2gray(X, map);
clear X;
case 'grayscale' %灰度图像
eval(['I=imread(''',file, ''');']);
end;
I = im2double(I);
filename = file(1 : find(file=='.')-1); %获取主文件名
data = reshape(I, numel(I), 1); %将图像数据转为一列数据
tic %计时开始
options=[2; % FCM 中的参数 m
100; % 最大迭代次数
1e-5;
1];
% 判别误差 epsonal
[center, U, obj_fcn]=myfcm(data, cluster_n,options); %调用 myfcm 函数进行聚类
elapsedtime = toc; %聚类结束,计时结束,elapsedtime 为进行聚类,所花时间
%聚类所获得数据保存在 filename.mat 文件中
%eval(['save(', filename, int2str(cluster_n),'.mat'', ''center'', ''U'', ''obj_fcn'', ''elapsedtime'');']);
%fprintf('聚类耗时 = %d', elapsedtime);
maxU=max(U);
temp = sort(center);
for n = 1:cluster_n; %按聚类结果分割图像
eval(['cluster',int2str(n), '_index = find(U(', int2str(n), ',:) == maxU);']);
index = find(temp == center(n));
switch index
case 1
color_class = 0;
case cluster_n
color_class = 255;
otherwise
color_class = fix(255*(index-1)/(cluster_n-1));
end
eval(['I(cluster',int2str(n), '_index(:))=', int2str(color_class),';']);
end;
I = mat2gray(I);
%eval(['imwrite(I,', filename,'_seg', int2str(cluster_n), '.bmp'');']); %保存生成的分割图像
imshow(I);%显示生成的分割的图像