SLIC超像素算法学习笔记

一、算法步骤

1.将输入图像转化为CEILAB空间

2.输入k并计算出S:在这里插入图片描述

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

1.输入图像并转化为CEILAB空间

%% Read Input Image and convert to CieLAB Space

[file,path] = uigetfile('*.*');  /*选择文件*/
f = fullfile(path,file);/*输入路径,文件*/
a = imread(f);/*合并两个参数*/
a_lab = rgb2lab(a);

​ 参数:在这里插入图片描述

2.输入k并计算出S

(1) 设置m、迭代次数n、超像素数量k、总像素数量N、距离s

%% Parameters

m = 15;
n = 5;     %threshold on no. of iterations:迭代次数
k = 1000;

​ 参数:m:距离公式里的m:在这里插入图片描述

​ n:迭代次数;k:超像素数量

%% 
N = size(a,1)*size(a,2);%行数×列数

s = sqrt(N/k);

​ 参数:N:像素;s:距离

(2) 设置梯度

%% 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);

​ 梯度公式:在这里插入图片描述

3.创造一个以s为间距的网格

(1) 初始化聚类中心

​ 为了避免影响后续的聚类结果,种子点在邻域内的窗口内移动,同时计算所有像素点的梯度值,并且保证移动到梯度值最小的位置上,防止种子点被分配到影像的边缘位置或噪声点的位置。并且分配标签到每个种子点上。

%% 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

在这里插入图片描述

​ 参数c:每一行都代表一个像素
在这里插入图片描述

(2)生成网格

%% 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中每一列的最小值

在这里插入图片描述

b1:最小值所在的行数
在这里插入图片描述

c:移动聚类中心后的像素值

在这里插入图片描述

(3)设置进度条

msg = 'Segmenting ...';
x = 0;%x代表进度
f = waitbar(x,msg);

4.对图像中的每个像素在2s的邻域内进行搜索,并将该平均值分配给该像素

​ 相似性度量:对每个像素进行搜索,计算像素点与种子点之间的相似程度,包括颜色距离和空间距离,不断迭代直到收敛

在这里插入图片描述

参数设置会影响到超像素分割的结果

(1)在2s邻域内进行搜索,并将平均值分给该像素

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
 
 

距离公式:在这里插入图片描述

(2)像k-means算法一样更新平均数位置

在此循环中所有的主要位置都得到更新

 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

(3)每次迭代都输出一次图像

%% 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);

(4)迭代并输出图像

%%
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));  %转换图片输出

5.给图像加边缘线

%% 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))
  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值