1.将输入图像转化为CEILAB空间
3.创造一个以s为间距的网格
4.移动边缘的平均值
5.对图像中的每个像素在2s的邻域内进行搜索,并将该平均值分配给该像素
6.取分配给一个平均数的像素的样本平均数,并更新平均数的位置
7.转到第5步,重复一定数量的迭代次数
% Written by Pratik Jain
% Subscribe me on YouTube
% https://www.youtube.com/PratikJainTutorials
clc
clear
close all
tic
%% Read Input Image and convert to CieLAB Space
[file,path] = uigetfile('*.*'); /*选择文件*/
f = fullfile(path,file);/*输入路径,文件*/
a = imread(f);/*合并两个参数*/
a_lab = rgb2lab(a);
%% Parameters
m = 15;
n = 5; %threshold on no. of iterations:迭代次数
k = 1000;
n:迭代次数;k:超像素数量
%%
N = size(a,1)*size(a,2);%行数×列数
s = sqrt(N/k);
参数:N:像素;s:距离
%% Gradient Image
G = zeros(size(a,1)-1,size(a,2)-1);
for i = 2:size(a,1)-1
for j = 2:size(a,2)-1
gx = (squeeze(a_lab(i+1,j,:))-squeeze(a_lab(i-1,j,:)));
gy = (squeeze(a_lab(i,j+1,:))-squeeze(a_lab(i,j-1,:)));
G(i,j) = gx(1)^2 + gx(2)^2 + gx(3)^2 + gy(1)^2 + gy(2)^2 + gy(3)^2;
end
end
% figure;
% imagesc(G);
为了避免影响后续的聚类结果,种子点在邻域内的窗口内移动,同时计算所有像素点的梯度值,并且保证移动到梯度值最小的位置上,防止种子点被分配到影像的边缘位置或噪声点的位置。并且分配标签到每个种子点上。
%% Initializing the Centers
s = ceil(s); %四舍五入
cx = s:s:size(a,1)-s; %x网格; size函数:获取矩阵的行数和列数
cy = s:s:size(a,2)-s; %y网格
p=1;
for i = 1:size(cx,2)
for j = 1:size(cy,2)
loc(p,:) = [cx(i),cy(j)]; %loc里面存着坐标;loc函数是利用index的名字,来获取想要的行或列
p=p+1;
end
end %循环后生成了网格
for i = 1:size(loc,1)
c(i,:) = [a_lab(loc(i,1),loc(i,2),1) a_lab(loc(i,1),loc(i,2),2) a_lab(loc(i,1),loc(i,2),3) loc(i,1) loc(i,2)]; %5个参数分别代表着red green blue x y
end
运行结果:
参数loc
%% SLIC Algorithm
win = 7;
n1 = floor(win/2);
%%在7x7的窗口中搜索,将把聚类中心移到最小梯度的地方
lochange = -n1:n1;%lochange告诉坐标将在哪里转移
%%此循环是为了把每一个聚类中心移动到最小梯度的地方
for i = 1:size(loc,1)
H = G(loc(i,1)-n1:loc(i,1)+n1,loc(i,2)-n1:loc(i,2)+n1);%7X7的网格
[a1,b1] = min(H);%a1:H中每一列的最小值;b1:最小值所在的行数
[a2,b2] = min(a1);
loc(i,1) = loc(i,1) + lochange(b1(b2));
loc(i,2) = loc(i,2) + lochange(b2); %控制像素从一个位置到另一个位置
c(i,:) = [a_lab(loc(i,1),loc(i,2),1) a_lab(loc(i,1),loc(i,2),2) a_lab(loc(i,1),loc(i,2),3) loc(i,1) loc(i,2)];%%把值放到c中,网格创建完成
end
理解:聚类中心就是每一个红点,我们要做的就是把每一个聚类中心都移动到梯度最小的地方
运行结果:
lochange: 表示坐标将在 -3,-2,-1,0,1,2,3处转移
H: 7X7的网格
a1: H中每一列的最小值
c:移动聚类中心后的像素值
msg = 'Segmenting ...';
x = 0;%x代表进度
f = waitbar(x,msg);
相似性度量:对每个像素进行搜索,计算像素点与种子点之间的相似程度,包括颜色距离和空间距离,不断迭代直到收敛
参数设置会影响到超像素分割的结果
while iter < n
for i2 = 1:size(a,1) %%算距离,用公式
for j2 = 1:size(a,2)
dis = [];
for k2 = 1:size(loc,1)
if sqrt((i2-loc(k2,1))^2 + (j2 - loc(k2,2))^2) < 2*s
d = sqrt((a_lab(i2,j2,1)-c(k2,1))^2 + (a_lab(i2,j2,2)-c(k2,2))^2 + (a_lab(i2,j2,3)-c(k2,3))^2) + m/s*sqrt((i2-c(k2,4))^2 + (j2-c(k2,5))^2);
dis = [dis;d k2];%% 参数 dis:有多少平均值接近;d:实际距离;k2:它接近于哪一个平均值
end
end
if isempty(dis) %如果是处于边界的像素,有时距离为0,这时什么也不运行
else %如果不是空的
[mind,I] = min(dis(:,1)); %提取最小值
o(i2,j2) = dis(I,2); %通过dis命令得到k2;把平均值分给每个像素
end
end
end
在此循环中所有的主要位置都得到更新
for i3 = 1:size(loc,1)
[row,col] = find(o==i3); %得到了行和列的索引;有多少像素在这个平均数上
if isempty(row) && isempty(col)
else
rowmean = round(mean(row)); %行更新平均值
colmean = round(mean(col)); %列更新平均值
c(i3,:)=[a_lab(rowmean,colmean,1) a_lab(rowmean,colmean,2) a_lab(rowmean,colmean,3) rowmean colmean];
end
end
%% Uncomment Following lines to see the image at every step
for i4 = 1:size(a,1)
for j4 = 1:size(a,2)
for k4 = 1:3
if o(i4,j4)~=0
out(i4,j4,k4) = c(o(i4,j4),k4);
end
end
end
end
%%
out1 = lab2rgb(out)*255;
figure;
imshow(uint8(out1));
%%
outvid(:,:,:,iter) = uint8(out1);
%%
for i4 = 1:size(a,1) %i4代表每一次迭代
for j4 = 1:size(a,2)
for k4 = 1:3
if o(i4,j4)~=0
out(i4,j4,k4) = c(o(i4,j4),k4);
end
end
end
end
%
% cform = makecform('lab2srgb');
% out1 = applycform(out,cform);
out1 = lab2rgb(out)*255;
imshow(uint8(out1)); %转换图片输出
%% Edges on the image
d = double(edge((rgb2gray(uint8(out1))),'canny'));
d(find(d==1)) = 255;
d(find(d==0)) = 1;
d(find(d==255)) = 0;
f1 = out1.*d;
figure;
imshow(uint8(f1))
,cform);
out1 = lab2rgb(out)*255;
imshow(uint8(out1)); %转换图片输出
## 5.给图像加边缘线
```matlab
%% Edges on the image
d = double(edge((rgb2gray(uint8(out1))),'canny'));
d(find(d==1)) = 255;
d(find(d==0)) = 1;
d(find(d==255)) = 0;
f1 = out1.*d;
figure;
imshow(uint8(f1))