matlab 图像显著性检测ft_关于图像显著性(MR)matlab代码详解

本代码内容是关于Saliency Detection via Graph-Based Manifold Ranking的算法详解,想要运行此代码还需要一系列的文件,单纯此代码无法演示结果的。

可以在网上搜索完整文件,简单来说就是基本的SLIC小程序,其余的不是必要项。

将数据集直接放入test文件夹中,运行sample或者demo都可以吧,我的是师兄传给我的,跟各位下载的结果应该差别不大。

(为了避免大家浪费时间,这里贴出百度云下载链接,链接:

关注并且私信我发链接

clear all;close all;clc;

addpath('./function/');

%%------------------------设置参数---------------------%%

theta = 0.1; % 控制边缘的权重

alpha = 0.99; % 控制流行排序成本函数两个项的平衡

spnumber = 200; % 超像素的数量

imgRoot = './test/'; % 测试图像的路径

saldir = './saliencymap/'; % 显著性图像的输出路径

supdir = './superpixels/'; % 超像素标签的文件路径

mkdir(supdir);

mkdir(saldir);

imnames = dir([imgRoot '*' 'jpg']);

disp(imnames);

imname = [imgRoot imnames.name];

[input_im,w] = removeframe(imname); %预处理去掉边框

[m,n,k] = size(input_im);

%%----------------------生成超像素--------------------%%

imname = [imname(1:end-4) '.bmp']; %SLIC软件仅支持bmp格式的图片

comm = ['SLICSuperpixelSegmentation' ' ' imname ' ' int2str(20) ' ' int2str(spnumber) ' ' supdir]; %设置启用SLIC.exe前参数

%

system(comm); %启用SLIC.exe,将每一个像素按照超像素的区域分类,同一区域的超像素赋相同的值,值与此区域的颜色亮度无关

spname = [supdir imnames.name(1:end-4) '.dat'];

%超像素标签矩阵

fid = fopen(spname,'r');%fid是文件代号(句柄)

A = fread(fid, m * n, 'uint32'); %fread(fid, N, 'str') N代表读入元素个数, 'str'是格式类型,将此文件顺序读出来,m*n个像素点逐行扫描

A = A+1; %把A变成正整数或逻辑值

B = reshape(A,[n, m]);%将顺序读出的值改为原图像的二维格式

superpixels = B';%B的转置矩阵,转成m*n,从列开始,在同一超像素区域内的像素赋同一值,值仅作为计数用,值为n,表示第n个超像素

fclose(fid);

spnum = max(superpixels(:)); %实际的超像素数目

%%----------------------设计图形模型--------------------------%%

%计算特征值 (mean color in lab color space)

%对于每个超像素

input_vals = reshape(input_im, m*n, k);%将原图像按行扫描转换为(m*n)*3的矩阵,即m*n行,3列的矩阵,分别为rgb

%input_im的值为0-1之间,是正常的rgb取值范围,全0表示黑,全1表示白

rgb_vals = zeros(spnum,1,3);

inds = cell(spnum,1);

for i = 1:spnum%从1到spnum,找到superpixels值相同的像素,放到一个cell中

inds{i} = find(superpixels==i);

rgb_vals(i,1,:) = mean(input_vals(inds{i},:),1);%input_vals每一行代表一个像素,将inds{i}中的所有对应的input_vals中的第几行,也就是

%第几个像素,取平均值,rgb_vals(i,1,1)也就是第i个超像素的r值

end

lab_vals = colorspace('Lab

seg_vals = reshape(lab_vals,spnum,3); % 每个超像素点的特征,将三维向量lab_vals变为二维向量,

%也就是以每一个超像素(一行Lab为特征)为单位,seg_vals(1,1)表示第1个超像素的L值

% 求得边界

%求邻接矩阵

adjloop = zeros(spnum,spnum);%邻接矩阵,不相连为0,相连为1,默认自身不相连

[m1,n1] = size(superpixels);

for i = 1:m1-1

for j = 1:n1-1

if(superpixels(i,j)~=superpixels(i,j+1))%从列开始搜索,临近一个像素的超像素标记值不相等,说明这个像素是两个超像素的边界线上点,即这两个超像素相连

adjloop(superpixels(i,j),superpixels(i,j+1)) = 1;%superpixels(i,j)的值代表第几个超像素

adjloop(superpixels(i,j+1),superpixels(i,j)) = 1;

end;%横方向

if(superpixels(i,j)~=superpixels(i+1,j))

adjloop(superpixels(i,j),superpixels(i+1,j)) = 1;

adjloop(superpixels(i+1,j),superpixels(i,j)) = 1;

end;%竖方向

if(superpixels(i,j)~=superpixels(i+1,j+1))

adjloop(superpixels(i,j),superpixels(i+1,j+1)) = 1;

adjloop(superpixels(i+1,j+1),superpixels(i,j)) = 1;

end;%捺方向

if(superpixels(i+1,j)~=superpixels(i,j+1))

adjloop(superpixels(i+1,j),superpixels(i,j+1)) = 1;

adjloop(superpixels(i,j+1),superpixels(i+1,j)) = 1;

end;%撇方向

end;

end;

bd = unique([superpixels(1,:),superpixels(m,:),superpixels(:,1)',superpixels(:,n)']);%边界的超像素的标记值

for i = 1:length(bd)

for j = i+1:length(bd)

adjloop(bd(i),bd(j)) = 1;

adjloop(bd(j),bd(i)) = 1;

end

end %将边界超像素赋值1,是将边界超像素相连

edges = [];

for i = 1:spnum; %真实超像素总数

indext = [];

ind = find(adjloop(i,:)==1);%邻接矩阵行i为1的项,也就是找到所有与第i个超像素相连接的超像素

for j = 1:length(ind)

indj = find(adjloop(ind(j),:)==1);%indj仅仅起到过渡作用,将与第i个超像素相连接的所有像素的连接情况一行一行的传递到indext中

indext = [indext,indj];

end

indext = [indext,ind];%indext是第i个超像素连接的超像素的连接情况,ind是第i个超像素的连接情况

indext = indext((indext>i));%只保留indext中值大于i的项

indext = unique(indext);%合并重复项,只保留不重复的项,即获取矩阵indext的不同元素构成的向量

%其目的是将第i个超像素的两圈节点与i连接,例如1超像素周围一圈再加边界一共52个与1相连,再加上这52个节点的周围节点也与1相连接,一共92个节点与1相连

if(~isempty(indext))

ed = ones(length(indext),2);%

ed(:,2) = i*ed(:,2);

ed(:,1) = indext;%第一列是列举了与i节点相连接的节点,第二列的值就全为i,因为1*i=i

edges = [edges;ed];%edges是加上第二圈后的连接边矩阵,一共两列,第一列是加上第二圈后与第i个节点相连接的所有节点(为避免重复运算增加运算速度,列举出第i个节点的所有连接点后,列举第i+1个节点的所有连接点时,去掉第i个节点),第二列是i

end

end

% 计算关联矩阵

valDistances = sqrt(sum((seg_vals(edges(:,1),:)-seg_vals(edges(:,2),:)).^2,2));

%b=sum(a,dim); a表示矩阵;dim等于1或者2,1表示每一列进行求和,2表示每一行进行求和

%对于valDistances来说,valDistances(1)=sqrt(([1连接的超像素列的第一个的L]-[1的L])^2+[1连接的超像素列的第一个的a]-[1的a])^2+[1连接的超像素列的第一个的b]-[1的b])^2)

valDistances = normalize(valDistances); %Normalize to [0,1]

weights = exp(-valDistances/theta);%theta=0.1

W=sparse([edges(:,1);edges(:,2)],[edges(:,2);edges(:,1)], ...%将weight和edges合并,更加直观

[weights;weights],spnum,spnum);

% sparse函数用法:

% 例如:

% 0, 0, 0, 0;

% 0, 0, 1, 0;

% 0, 0, 0, 0;

% 0, 1, 0, 2;

% 计算机存储稀疏矩阵可以有两种思路:

% 1.按照存储一个普通矩阵一样存储一个稀疏矩阵,比如上面这个稀疏矩阵中总共十六个元素(三个非零元素),把这些元素全部放入存储空间中。这种存储方式,在matlab就叫做full storage organization。

% 2.只存储非零元素,那么怎么存储呢?

% (4,2) 1

% (2,3) 1

% (4,4) 2

% 最优化关联矩阵 (公式3) f∗ = y/(D − αW) .

dd = sum(W); %sum函数不写第二个参数默认为列求和

D = sparse(1:spnum,1:spnum,dd);

clear dd; %S = sparse(i,j,s,m,n,nzmax)由向量i,j,s生成一个m*n的含有nzmax个非零元素的稀疏矩阵S;即矩阵A中任何0元素被去除,非零元素及其下标组成矩阵S

optAff = eye(spnum)/(D-alpha*W);% eye函数返回单位矩阵,Y = eye(n):返回n*n单位矩阵

mz = diag(ones(spnum,1));%将mz设置为方阵,方阵大小为spnum*spnum,内容全为1

mz = ~mz; %将A的对角元素设置为0

optAff = optAff.*mz;%将optAff的对角元素归零,因为超像素自身和自身之间的关联性并不考虑,要考虑的话也应该是无限大,没有数值,此矩阵用来表示各个超像素之间的关联性

%%-----------------------------显著性检测第一阶段--------------------------%%

% 为每个超像素计算显著性值

% 作为种子点的上边界

% top

Yt = zeros(spnum,1);%指示向量

bst = unique(superpixels(1,1:n));

Yt(bst) = 1;%将上边界的超像素赋值为1

bsalt = optAff*Yt;%(spnum*spnum)*(spnum*1),表示从1到spnum的所有超像素对于上边界超像素的关联性和

bsalt = (bsalt-min(bsalt(:)))/(max(bsalt(:))-min(bsalt(:))); %括号内只有一个冒号表示历遍所有元素,将所有元素放进【0,1】中,即正规化数据

bsalt = 1-bsalt; %补码为显著性度量

% down

Yd = zeros(spnum,1);

bsd = unique(superpixels(m,1:n));

Yd(bsd) = 1;

bsald = optAff*Yd; %f*(i) 此向量中的每个元素表示节点与背景种子点的相关性

bsald = (bsald-min(bsald(:)))/(max(bsald(:))-min(bsald(:)));

bsald = 1-bsald;

% right

Yr = zeros(spnum,1);

bsr = unique(superpixels(1:m,1));

Yr(bsr) = 1;

bsalr = optAff*Yr;

bsalr = (bsalr-min(bsalr(:)))/(max(bsalr(:))-min(bsalr(:)));

bsalr = 1-bsalr;

% left

Yl = zeros(spnum,1);

bsl = unique(superpixels(1:m,n));

Yl(bsl) = 1;

bsall = optAff*Yl;

bsall = (bsall-min(bsall(:)))/(max(bsall(:))-min(bsall(:)));

bsall = 1-bsall;

% combine

bsalc = (bsalt.*bsald.*bsall.*bsalr);

bsalc = (bsalc-min(bsalc(:)))/(max(bsalc(:))-min(bsalc(:)));

% 为每个像素分配显著性值

tmapstage1 = zeros(m,n);

for i = 1:spnum

tmapstage1(inds{i}) = bsalc(i);

end

tmapstage1 = (tmapstage1-min(tmapstage1(:)))/(max(tmapstage1(:))-min(tmapstage1(:)));%正规化

mapstage1 = zeros(w(1),w(2));

mapstage1(w(3):w(4),w(5):w(6)) = tmapstage1;

mapstage1 = uint8(mapstage1*255); %显著性值的高低俩分配灰度值,越显著值越大

outname = [saldir imnames.name(1:end-4) '_stage1' '.png'];

imwrite(mapstage1,outname);

%%----------------------显著性检测第二阶段-------------------------%%

% 自适应阈值二值化

th = mean(bsalc); %阈值被设置为整个显著图上的平均显著性

bsalc(bsalc

bsalc(bsalc>=th)=1;%前景

% 为每个超像素计算显著性值

fsal = optAff*bsalc;%optAff是所有超像素对所有超像素的关联性,只选取其中的前景部分,即所有前景的显著性值

% 为每个像素分配显著性值

tmapstage2 = zeros(m,n);

for i = 1:spnum

tmapstage2(inds{i}) = fsal(i);

end

tmapstage2 = (tmapstage2-min(tmapstage2(:)))/(max(tmapstage2(:))-min(tmapstage2(:)));

mapstage2 = zeros(w(1),w(2));

mapstage2(w(3):w(4),w(5):w(6)) = tmapstage2;

mapstage2 = uint8(mapstage2*255);

outname = [saldir imnames.name(1:end-4) '_stage2' '.png'];

imwrite(mapstage2,outname);

根据代码内容我有感而发,f∗ =  y/(D − αW)此函数算出所有超像素的关联性后,稍微整理一下就可以当做显著值赋予灰度值,至于论文中提到的两次流形排序,

其实在代码中只有一次用到了此函数计算了所有超像素之间的关联性(127-135)。第一次和第二次都只是分别用了类似于指示向量的向量提取出来而已,本质上没有进行两次流形排序,

而是算了一次总的,而后再分别提取,算是简化了过程吧,至于模型的化简,仍然还是比较复杂的,需要摸索的,本文仅仅对代码详解注释,希望对大家的理解过程有帮助。

参与评论 您还未登录,请先 登录 后发表或查看评论
1. 显著点的检测 Itti的A Model of Saliency-Based Visual Attention for Rapid Scene Analysis TPAMI 1999论文是显著性检测的鼻祖论文,检测出来的是用户关注的点。 2. 显著区域的检测 侯晓迪同学在2007年发表的一篇CVPR的论文,用很简单的方法检测显著性区域,那之后显著性检测主要以区域检测为主:Saliency detection: A spectral residual approach CVPR 2007,虽然之后有人诟病这篇论文有不足之处,但该想法简单,推动了显著性研究的普及。侯同学靠这一篇文章再加上投稿期间的趣事,就封神了。 3. 其他经典的显著性检测方法 在那之后陆续又有一些经典的显著性检测算法被提出:https://blog.csdn.net/touch_dream/article/details/78716507 可以看这个博文。 4. 基于深度学习的显著性检测 再之后,显著性检测领域就进入了Deep Learning时代, Deep Visual Attention Prediction TIP2018 CODE     https://github.com/wenguanwang/deepattention Predicting Human Eye Fixations via an LSTM-based Saliency Attentive Model CODE     https://github.com/marcellacornia/sam CVPR2016 Shallow and Deep Convolutional Networks for Saliency Prediction CODE     https://github.com/imatge-upc/saliency-2016-cvpr Saliency Detection with GAN (2017)     https://github.com/imatge-upc/saliency-salgan-2017  CODE     https://github.com/batsa003/salgan/ PyTorch的版本 5. 非自然图象的显著性检测 例如,海报的显著性检测,图表的显著性检测,地理数据的显著性检测等等。

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

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:数字20 设计师:CSDN官方博客 返回首页

打赏作者

夏欢Vivian

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值