Traditional Saliency Reloaded: A Good Old Model in New Shape

发在CVPR2015上的一篇文章,读起来并不是很困难,思路也比较纯粹。作者也开源了代码,在这里下载:http://pages.iai.uni-bonn.de/frintrop_simone/vocus2.html问题是,作者的代码依赖于Boost C++ Library,但是我对这个库并不是很熟悉,配置起来可能不是那么方便。所以我根据自己的理解,用Matlab重写了一下,看起来效果还可以,希望能对需要的人有所帮助。需要指出的是,对于一些细节的理解可能不准确,比如说八度的个数,每个八度的层数,生成金字塔特征的过程等。因此,该代码只做测试用,未与原始C++版本代码对照修正,如果需要与论文方法做比较,请依据作者原始代码进行测评。

GetFeatureChannels.m

function [Intensity RG BY] = GetFeatureChannels( Img )

if(length(size(Img))~=3)
    disp('Input image must be a color image with RGB 3 channels!');
    return;
end
R=Img(:,:,1);
G=Img(:,:,2);
B=Img(:,:,3);
Intensity=(R+G+B)/3;
RG=R-G;
BY=B-(R+G)/2;
end
 BuildMultiScaleTwinPyr.m

function [center_pyramid surround_pyramid] = BuildMultiScaleTwinPyr( input_image_channel,octave_num,layer_num,sig_center,sig_surround )
% 第几个八度(o)和八度中的第几层(s)两个变量构成了高斯金字塔的尺度空间。
% 一个八度中图像的长和宽是相等的,即变量o控制的是塔中尺寸这个尺度;
% s控制的是一个八度中不同的模糊程度。

center_pyramid=cell(octave_num,layer_num);
surround_pyramid=cell(octave_num,layer_num);
tmpimg=input_image_channel;
for o=0:octave_num-1
    for s=0:layer_num-1
        sig_total=power(2.0,double(o)+double(s)/double(layer_num-1))*sig_center;
        gaussFilter=fspecial('gaussian',[5 5],sig_total);
        center_pyramid{o+1,s+1}=double(imfilter(tmpimg,gaussFilter,'replicate'));
        sig_ratio=sqrt(sig_surround*sig_surround-sig_center*sig_center);
        ratioFilter=fspecial('gaussian',[5 5],sig_ratio);
        surround_pyramid{o+1,s+1}=double(imfilter(center_pyramid{o+1,s+1},ratioFilter,'replicate'));
    end
    tmpimg=imresize(tmpimg,[size(tmpimg,1)/2 size(tmpimg,2)/2]);
end
end
FeatureFusion.m

function FeatureMap = FeatureFusion( ContrastPyr )
%ContrastPyr should be in CELL format. Each row represents an OCTAVE with
%multiple layers (in our setup, we set 3 layers in one octave). FeatureMap
%should be the same size as elements in first row of ContrastPyr, that is,
%FeatureMap is the same size as original input image. Consequently, before
%fusing ContrastPyr, we should unify(enlarge) contrast maps to the same
%size, i.e., size of original input image.

[height width]=size(ContrastPyr{1,1}); %standard size
FeatureMap=zeros(height,width);
[m n]=size(ContrastPyr);
SameSizeMap=cell(m,n);

for i=1:m % Remain first row of ContrastPyr unchanged
    for j=1:n
        if(i==1)
            SameSizeMap{i,j}=ContrastPyr{i,j};
        else
            SameSizeMap{i,j}=imresize(ContrastPyr{i,j},[height width],'bicubic');
        end
    end
end

for i=1:m
    for j=1:n
        FeatureMap=FeatureMap+SameSizeMap{i,j};
    end
end

end

Normalize.m

function OutImg = Normalize(InImg)  
ymax=255;ymin=0;  
xmax = max(max(InImg)); %求得InImg中的最大值  
xmin = min(min(InImg)); %求得InImg中的最小值  
OutImg = round((ymax-ymin)*(InImg-xmin)/(xmax-xmin) + ymin); %归一化并取整  
end  

Main.m

clc;
clear;
% Path setting
inputImgPath = 'Imgs';                 % input image path
resSalPath = 'SAL_MAP';                     % result path
if ~exist(resSalPath, 'file')
    mkdir(resSalPath);
end
addpath(genpath(inputImgPath));
% Parameter setting
octave_num=5; %5个八度
layer_num=3; %每个八度下3层
sig_center=3;
sig_surround=13;
%% Create twin pyramids
imgFiles = dir(inputImgPath);
for indImg = 1:2:length(imgFiles)-2    
    % read image
    imgPath = fullfile(inputImgPath, imgFiles(indImg+2).name);
    img= imread(imgPath); 
    [Intensity RG BY]=GetFeatureChannels(img);
    % Build twin pyramids for Internsity
    [InCenterPyr InSurroundPyr] = BuildMultiScaleTwinPyr(Intensity,octave_num,layer_num,sig_center,sig_surround);
    % Build twin pyramids for RG
    [RGCenterPyr RGSurroundPyr] = BuildMultiScaleTwinPyr(RG,octave_num,layer_num,sig_center,sig_surround);
    % Build twin pyramids for BY
    [BYCenterPyr BYSurroundPyr] = BuildMultiScaleTwinPyr(BY,octave_num,layer_num,sig_center,sig_surround);
    
    %% Create contrast pyramids
    [m n]=size(InCenterPyr);
    InOnOff=cell(m,n);
    InOffOn=cell(m,n);
    RGOnOff=cell(m,n);
    RGOffOn=cell(m,n);
    BYOnOff=cell(m,n);
    BYOffOn=cell(m,n);
    for i=1:m
        for j=1:n
            InOnOff{i,j}=InCenterPyr{i,j}-InSurroundPyr{i,j};
            tmp=InOnOff{i,j};
            InOnOff{i,j}(find(tmp(:)<0))=0;
            InOffOn{i,j}=InSurroundPyr{i,j}-InCenterPyr{i,j};
            tmp=InOffOn{i,j};
            InOffOn{i,j}(find(tmp(:)<0))=0;
            RGOnOff{i,j}=RGCenterPyr{i,j}-RGSurroundPyr{i,j};
            tmp=RGOnOff{i,j};
            RGOnOff{i,j}(find(tmp(:)<0))=0;
            RGOffOn{i,j}=RGSurroundPyr{i,j}-RGCenterPyr{i,j};
            tmp=RGOffOn{i,j};
            RGOffOn{i,j}(find(tmp(:)<0))=0;
            BYOnOff{i,j}=BYCenterPyr{i,j}-BYSurroundPyr{i,j};
            tmp=BYOnOff{i,j};
            BYOnOff{i,j}(find(tmp(:)<0))=0;
            BYOffOn{i,j}=BYSurroundPyr{i,j}-BYCenterPyr{i,j};
            tmp=BYOffOn{i,j};
            BYOffOn{i,j}(find(tmp(:)<0))=0;
        end
    end    
    %% FeatureMaps
    InOnOffFusion=FeatureFusion(InOnOff);
    InOffOnFusion=FeatureFusion(InOffOn);
    RGOnOffFusion=FeatureFusion(RGOnOff);
    RGOffOnFusion=FeatureFusion(RGOffOn);
    BYOnOffFusion=FeatureFusion(BYOnOff);
    BYOffOnFusion=FeatureFusion(BYOffOn);
    %% FeatureMaps Fusion
    IntensityFeature=Normalize((InOnOffFusion+InOffOnFusion)/2);
    RGFeature=Normalize((RGOnOffFusion+RGOffOnFusion)/2);
    BYFeature=Normalize((BYOnOffFusion+BYOffOnFusion)/2);
    %% Generate Saliency Map
    FeatureMap=Normalize((IntensityFeature+RGFeature+BYFeature)/3);
    figure(indImg);
    subplot(121);
    imshow(img,[]);
    title('Original Image');
    subplot(122);
    imshow(FeatureMap,[]);
    title('Saliency Map');   
    pause(2);
    close(figure(indImg));
end 
    

再次提醒,该代码可能不能准确反映论文原始意图,仅做测试使用,顺便可能对需要的人有所启发。贴几张效果图



有问题可联系 jzwangATbjtuDOTeduDOTcn讨论交流。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值