环境:matlab2012a
源码作者如下:
% This m-file demoes the usage of SIFT functions. It generates SIFT keypionts and descriptors for one input image.
% Author: Yantao Zheng. Nov 2006. For Project of CS5240
%% file: do_gaussian.m
% author: Noemie Phulpin
% description: gaussian scale space of image I
SIFT变换函数流程如下:
[frames1,descr1,gss1,dogss1] = do_sift( I1, 'Verbosity', 1, 'NumOctaves', 4, 'Threshold', 0.1/3/2 ) ; %0.04/3/2
接下来看do_sift函数:
第一步:首先初始化一些变量:
warning off all;
[M,N,C] = size(I) ;
% Lowe's choices
S=3 ;
omin= 0 ;
%O=floor(log2(min(M,N)))-omin-4 ; % Up to 16x16 images
O = 4;
sigma0=1.6*2^(1/S) ;
sigman=0.5 ;
thresh = 0.2 / S / 2 ; % 0.04 / S / 2 ;
r = 18 ;
NBP = 4 ;
NBO = 8 ;
magnif = 3.0 ;
% Parese input
compute_descriptor = 0 ;
discard_boundary_points = 1 ;
verb = 0 ;
% Arguments sanity check
if C > 1
error('I should be a grayscale image') ;
end
frames = [] ;
descriptors = [] ;
第二步:开始构建尺度空间
fprintf('CS5240 -- SIFT: constructing scale space with DoG ...\n') ; tic ;
scalespace = do_gaussian(I,sigman,O,S,omin,-1,S+1,sigma0) ;
进入do_gaussian 函数:
开始 Gaussian scale space construction:
function L = do_gaussian(I,sigman,O,S,omin,smin,smax,sigma0)
%% file: do_gaussian.m
% author: Noemie Phulpin
% description: gaussian scale space of image I
%%
if(nargin<7)
sigma0=1.6*k;
end
if omin<0
for o=1:-omin
I=doubleSize(I);
end
elseif omin>0
for o=1:-omin
I=halveSize(I);
end
end
[M,N] = size(I); %size of image
k = 2^(1/S); %scale space multiplicative step k
sigma0=1.6*k; %definition by Lowe
dsigma0 = sigma0*sqrt(1-1/k^2); %scale step factor
sigmaN=0.5; %nominal smoothing of the image
so=-smin+1; %index offset
%scale space structure
L.O = O;
L.S = S;
L.sigma0 = sigma0;
L.omin = omin;
L.smin = smin;
L.smax = smax;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%First Octave
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%initilize the octave with S sub-levels
L.octave{1} = zeros(M,N,smax-smin+1);
%initilize the first sub-level
sig=sqrt( (sigma0*k^smin)^2 - (sigmaN/2^omin)^2 );
%b=smooth2(I,sig) ;
%[N1,M1]=size(b)
%b(1:4,1:4)
%c=imsmooth(I,sig) ;
%[N2,M2]=size(c)
%c(1:4,1:4)
L.octave{1}(:,:,1) = smooth(I,sig);
%other sub-levels
for s=smin+1:smax
dsigma = k^s * dsigma0;
L.octave{1}(:,:,s+so) = smooth( squeeze(L.octave{1}(:,:,s-1+so)) ,dsigma);
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Folowing Octaves
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%convert all octaves
for o=2:O
sbest = min(smin+S,smax);
TMP = halvesize( squeeze(L.octave{o-1}(:,:,sbest+so)) );
sigma_next = sigma0*k^smin;
sigma_prev = sigma0*k^(sbest-S);
if (sigma_next>sigma_prev)
sig=sqrt(sigma_next^2-sigma_prev^2);
TMP= smooth( TMP,sig);
end
[M,N] = size(TMP);
L.octave{o} = zeros(M,N,smax-smin+1);
L.octave{o}(:,:,1) = TMP;
%other sub-levels
for s=smin+1:smax
dsigma = k^s * dsigma0;
L.octave{o}(:,:,s+so) = smooth( squeeze(L.octave{o}(:,:,s-1+so)) ,dsigma);
end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Auxiliary functions
function J = halvesize(I)
J=I(1:2:end,1:2:end);
function J = doubleSize(I)
[M,N]=size(I) ;
J = zeros(2*M,2*N) ;
J(1:2:end,1:2:end) = I ;
J(2:2:end-1,2:2:end-1) = ...
0.25*I(1:end-1,1:end-1) + ...
0.25*I(2:end,1:end-1) + ...
0.25*I(1:end-1,2:end) + ...
0.25*I(2:end,2:end) ;
J(2:2:end-1,1:2:end) = ...
0.5*I(1:end-1,:) + ...
0.5*I(2:end,:) ;
J(1:2:end,2:2:end-1) = ...
0.5*I(:,1:end-1) + ...
0.5*I(:,2:end) ;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
接下来开始 Differential scale space construction
function D = do_diffofg(L)
%% file: do_diffofg.m
% author: Noemie Phulpin
% description: substraction of consecutive levels of the scale space SS.
%%
D.smin = L.smin;
D.smax = L.smax-1;
D.omin =L.omin;
D.O = L.O;
D.S = L.S;
D.sigma0 = L.sigma0;
for o=1:D.O
[M,N,S] = size(L.octave{o});
D.octave{o} = zeros(M,N,S-1);
for s=1:S-1
D.octave{o}(:,:,s) = L.octave{o}(:,:,s+1) - L.octave{o}(:,:,s);
end;
end;
第三步:开始多组(octave)尺度空间的特征点检测计算
fprintf('CS5240 -- SIFT: computing octave %d\n', o-1+omin) ;
tic ;
% Local maxima of the DOG octave
oframes1 = do_localmax( difofg.octave{o}, 0.8*thresh, difofg.smin ) ;
oframes = [oframes1 , do_localmax( - difofg.octave{o}, 0.8*thresh, difofg.smin)] ;
fprintf('CS5240 -- SIFT: initial keypoints # %d. \n', ...
size(oframes, 2)) ;
fprintf(' Time (%.3f s)\n', ...
toc) ;
tic ;
if size(oframes, 2) == 0
continue;
end
% Remove points too close to the boundary
rad = magnif * scalespace.sigma0 * 2.^(oframes(3,:)/scalespace.S) * NBP / 2 ;
sel=find(...
oframes(1,:)-rad >= 1 & ...
oframes(1,:)+rad <= size(scalespace.octave{o},2) & ...
oframes(2,:)-rad >= 1 & ...
oframes(2,:)+rad <= size(scalespace.octave{o},1) ) ;
oframes=oframes(:,sel) ;
fprintf('CS5240 -- SIFT: keypoints # %d after discarding from boundary\n', size(oframes,2)) ;
% Refine the location, threshold strength and remove points on edges
oframes = do_extrefine(...
oframes, ...
difofg.octave{o}, ...
difofg.smin, ...
thresh, ...
r) ;
fprintf('CS5240 -- SIFT: keypoints # %d after discarding from low constrast and edges\n',size(oframes,2)) ;
fprintf(' Time (%.3f s)\n', toc) ;
tic ;
fprintf('CS5240 -- SIFT: compute orientations of keypoints\n');
% Compute the orientations
oframes = do_orientation(...
oframes, ...
scalespace.octave{o}, ...
scalespace.S, ...
scalespace.smin, ...
scalespace.sigma0 ) ;
fprintf(' time: (%.3f s)\n', toc);tic;
% Store frames
x = 2^(o-1+scalespace.omin) * oframes(1,:) ;
y = 2^(o-1+scalespace.omin) * oframes(2,:) ;
sigma = 2^(o-1+scalespace.omin) * scalespace.sigma0 * 2.^(oframes(3,:)/scalespace.S) ;
frames = [frames, [x(:)' ; y(:)' ; sigma(:)' ; oframes(4,:)] ] ;
fprintf('CS5240 -- SIFT: keypoints # %d after orientation computation \n', size(frames,2)) ;
% Descriptors
fprintf('CS5240 -- SIFT: compute descriptors...\n') ;
tic ;
sh = do_descriptor(scalespace.octave{o}, ...
oframes, ...
scalespace.sigma0, ...
scalespace.S, ...
scalespace.smin, ...
'Magnif', magnif, ...
'NumSpatialBins', NBP, ...
'NumOrientBins', NBO) ;
descriptors = [descriptors, sh] ;
fprintf(' time: (%.3f s)\n\n\n',toc) ;