(Saliency Detection: A Spectral Residual Approach)
给定一幅图像,I(x)首先计算其2维离散傅里叶变换,将其从空间域转换到频域,对幅值取对数后得到log谱L(f):
式中F代表2维离散傅里叶变换,I·I代表其幅值,φ代表其相位。
由于log曲线满足局部线性条件,所以用局部平均滤波器hn(f)对其进行平滑,获得log谱的大致形状:
hn(f)是一个nxn矩阵定义为:
因此谱残差就是log谱和其进行均值滤波后的差,可按下面的式子计算:
谱残差能够描述一幅图像中的异常区域,因此可以用来进行显著目标检测。将谱残差和相位P(f)进行2维离散傅里叶反变换
由此可以重构出一幅图像,用来表示原图像各像素的显著性,称为显著图(saliencymap)。
下面为基于谱残差法显著性检测的matlab代码
function [srmap] = sr(rgb, sigma)
%计算利用最基本普残差得到显著图,即不包含颜色亮度分量等特征
F = fft2(rgb2gray(rgb));%将彩色图像转为灰度图像(即亮度)后进行二维离散傅立叶变换
Af = abs(F);%对傅立叶变换结果取绝对值(即求变换后图像的幅度图像)
Pf = angle(F);%求变换后图像的相位谱图像
Lf = log(Af);%得到幅度值的Log谱
filt = fspecial('average', 3);%创建局部平均滤波算子[3,3]为默认尺寸
%circular'图像大小通过将图像看成是一个二维周期函数的一个周期来扩展
Rf = Lf - imfilter(Lf, filt, 'circular');% 幅度值的Log谱-局部平均滤波器进行平滑处理后的Log谱得到普残差
srmap = ifft2((exp(Rf+i*Pf)));%将相位谱和谱残差进行二维傅立叶反变换得到显著图
srmap = abs(srmap);%取上面计算图像的幅值部分即位显著图(saliency map)
srmap = srmap .^ 2;%将显著图矩阵中各个元素平方,即为进行二维卷积运算,利用了“复数和它的共轭复数的乘积是复数模的平方”这一结论
srmap = mat2gray(imfilter(srmap, fspecial('gaussian',[3 3], sigma)));%对处理后的显著图进行滤波(高斯低通滤波尺寸为[3,3],Sigma为滤波器的标准差),然后归一化
end
以下为谱残差法显著性检测的C++实现
// opencvtest1.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include
#include
#include
using namespace cv;
using namespace std;
int _tmain(int argc,char** argv)
{
//读取图片
const char *filename = (argc >=2 ? argv[1]:"1.jpg" );
Mat I = imread(filename);
if (I.empty())
{
return -1;
}
//彩色图转成灰色图
if (I.channels()==3)
{
cvtColor(I,I,CV_RGB2GRAY);
}
Mat planes[] = { Mat_(I), Mat::zeros(I.size(), CV_32F) };
Mat complexI;
//构造复数双通道矩阵
merge(planes,2,complexI);
//快速傅里叶变换
dft(complexI,complexI);
Mat mag, pha, mag_mean;
Mat Re, Im;
//分离复数到实部和虚部
Re = planes[0]; //实部
split(complexI, planes);
Re = planes[0]; //实部
Im = planes[1]; //虚部
//计算幅值
magnitude(Re, Im, mag);
//计算相角
phase(Re, Im, pha);
float *pre, *pim, *pm, *pp;
//对幅值进行对数化
for (int i = 0; i(i);
for (int j = 0; j(i);
pim = Im.ptr(i);
pm = mag.ptr(i);
pp = pha.ptr(i);
for (int j = 0; j(Re), Mat_(Im) };
//重新整合实部和虚部组成双通道形式的复数矩阵
merge(planes1, 2, complexI);
// 傅立叶反变换
idft(complexI, complexI, DFT_SCALE);
//分离复数到实部和虚部
split(complexI, planes);
Re = planes[0];
Im = planes[1];
//计算幅值和相角
magnitude(Re, Im, mag);
for (int i = 0; i(i);
for (int j = 0; j
function [pftmap] = pft(rgb)
% [row,col,page] =size(rgb);
gimg = rgb2gray(rgb);%将彩色图像转为灰度图像
F = fft2(gimg);%对灰度图像进行二维离散傅里叶变换
amp = abs(F);%得到幅值图像
ph = angle(F);%得到相位图
s = ifft2(1 * exp(1i*ph));%不加入幅值图像部分,只对相位谱进行二维离散傅里叶反变换
filt = fspecial('gaussian', [3 3]);%标准差为sigma的二维高斯滤波算子
Pftmap = mat2gray(imfilter(abs(s).*abs(s), filt, 'circular'));
pftmap = mat2gray(Pftmap);%归一化
end
(Spatio-temporal Saliency Detection Using Phase Spectrum of Quaternion Fourier Transform)
function [qpftmap, RG, BY,I1] = qpft(rgb, sigma )%-1
%四元傅里叶相位谱显著性检测
[row ,col, page] = size(rgb);
%计算四元数
r = double(rgb(:,:,1)); g = double(rgb(:,:,2)); b = double(rgb(:,:,3));%r红通道g绿通道b蓝通道
R = r - (g + b)/2; %调整后的红色通道
G = g - (r + b)/2; %调整后的绿色通道
B = b - (r + g)/2; %调整后的蓝色通道
Y = (r + g)/2 - (abs(r - g))/2 - b;%黄色通道
u1=1;%I
u2=1;%RG
RG = R - G;%红/绿对立神经元
BY =B - Y;%蓝/黄对立神经元
I1 = ((r+g+b)./3).*u1;%-0 计算亮度特征
%I0=rgb2gray(rgb);
%I1=grayslice(I0,64);
%I1=double(I1);
%level = graythresh(I0); %OTSU阈值确定-1
%I1=im2bw(I0,level); %转为二值图像-1
M = zeros(row, col); %创建一个全0数组(运动特征)
%定义加权四元数表示如下
f1 = M + RG * 1i;
f2 = BY + I1* 1i;
%进行傅里叶变换
F1 = fft2(f1);
F2 = fft2(f2);
phaseQ1 = angle(F1);%得到相位谱
phaseQ2 = angle(F2);%得到相位谱
ifftq1 = ifft2(exp(phaseQ1 * 1i));%对相位谱进行傅里叶反变换
ifftq2 = ifft2(exp(phaseQ2 * 1i));%对相位谱进行傅里叶反变换
absq1 = abs(ifftq1);%得到幅值图像
absq2 = abs(ifftq2);%得到幅值图像
squareq=(absq1+absq2).*(absq1+absq2);
L = fspecial('gaussian', [5 5], sigma);%标准差为sigma的二维高斯滤波算子
Squareq = mat2gray(imfilter(squareq, L, 'circular'));%L表示标准差为sigma的二维高斯滤波器
qpftmap = mat2gray(Squareq);%最终显著图为归一化后的二维矩阵
end