环境: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
[frames1,descr1,gss1,dogss1] = do_sift( I1, 'Verbosity', 1, 'NumOctaves', 4, 'Threshold', 0.1/3/2 ) ; %0.04/3/2
第一步:首先初始化一些变量:
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) ;