www.gusucode.com > MATLAB实现图像的SIFT特征提取,并做在不同光照、不同视角下的特征匹配 > descriptor/do_descriptor.m
function descriptors = do_descriptor(octave, ... % 一组的高斯尺度空间 oframes, ... % frames 包含关键点相关的尺度和主方向 sigma0, ... % 基本 sigma 值 S, ... % 该组的尺度层数 smin, ... varargin) for k=1:2:length(varargin) switch lower(varargin{k}) case 'magnif' magnif = varargin{k+1} ; case 'numspatialbins' NBP = varargin{k+1} ; case 'numorientbins' NBO = varargin{k+1} ; otherwise error(['Unknown parameter ' varargin{k} '.']) ; end end num_spacialBins = NBP; num_orientBins = NBO; key_num = size(oframes, 2); % 计算该图的向量和方向 [M, N, s_num] = size(octave); % M 是图像的高度, N 是图像的宽度; num_level is the number of scale level of the octave descriptors = []; magnitudes = zeros(M, N, s_num); angles = zeros(M, N, s_num); % compute image gradients for si = 1: s_num img = octave(:,:,si); dx_filter = [-0.5 0 0.5]; dy_filter = dx_filter'; gradient_x = imfilter(img, dx_filter); gradient_y = imfilter(img, dy_filter); magnitudes(:,:,si) =sqrt( gradient_x.^2 + gradient_y.^2); % if sum( gradient_x == 0) > 0 % fprintf('00'); % end angles(:,:,si) = mod(atan(gradient_y ./ (eps + gradient_x)) + 2*pi, 2*pi); end x = oframes(1,:); y = oframes(2,:); s = oframes(3,:); % round off x_round = floor(oframes(1,:) + 0.5); y_round = floor(oframes(2,:) + 0.5); scales = floor(oframes(3,:) + 0.5) - smin; for p = 1: key_num %对各个关键点处理 s = scales(p); xp= x_round(p); yp= y_round(p); theta0 = oframes(4,p);%关键点的主方向 sinth0 = sin(theta0) ; costh0 = cos(theta0) ; sigma = sigma0 * 2^(double (s / S)) ; SBP = magnif * sigma; %W = floor( sqrt(2.0) * SBP * (NBP + 1) / 2.0 + 0.5); W = floor( 0.8 * SBP * (NBP + 1) / 2.0 + 0.5); descriptor = zeros(NBP, NBP, NBO); % within the big square, select the pixels with the circle and put into % the histogram. no need to do rotation which is very expensive %在大正方形中用高斯加权圆选择像素点放入方向直方图中,不需要做昂贵的图像旋转 for dxi = max(-W, 1-xp): min(W, N -2 - xp) for dyi = max(-W, 1-yp) : min(+W, M-2-yp) mag = magnitudes(yp + dyi, xp + dxi, s); % 当前点(yp + dyi, xp + dxi)的梯度幅值 angle = angles(yp + dyi, xp + dxi, s) ; % 当前点(yp + dyi, xp + dxi)的梯度幅角 % angle = mod(-angle + theta0, 2*pi); % 用关键点的主方向调整角度 并且 mod it with 2*pi angle = mod(angle - theta0, 2*pi); dx = double(xp + dxi - x(p)); % x(p) 是关键点的精确位置 (浮点数). dx 相对于该关键点当前像素的位置 dy = double(yp + dyi - y(p)); % dy 相对于该关键点当前像素的位置 nx = ( costh0 * dx + sinth0 * dy) / SBP ; % nx 是旋转(dx, dy)后的规格化位置 with the major orientation angle. this tells which x-axis spatial bin the pixel falls in ny = (-sinth0 * dx + costh0 * dy) / SBP ; nt = NBO * angle / (2* pi) ; wsigma = NBP/2 ; wincoef = exp(-(nx*nx + ny*ny)/(2.0 * wsigma * wsigma)) ; binx = floor( nx - 0.5 ) ; biny = floor( ny - 0.5 ) ; bint = floor( nt ); rbinx = nx - (binx+0.5) ; rbiny = ny - (biny+0.5) ; rbint = nt - bint ; for(dbinx = 0:1) for(dbiny = 0:1) for(dbint = 0:1) % if condition limits the samples within the square % width W. binx+dbinx is the rotated x-coordinate. % therefore the sampling square is effectively a % rotated one %如果条件限制在用宽度W设定的方形内的样点,binx+dbinx是旋转后的x坐标 %因此采样方形的旋转是有效的。 if( binx+dbinx >= -(NBP/2) && ... binx+dbinx < (NBP/2) && ... biny+dbiny >= -(NBP/2) && ... biny+dbiny < (NBP/2) && isnan(bint) == 0) weight = wincoef * mag * abs(1 - dbinx - rbinx) ... * abs(1 - dbiny - rbiny) ... * abs(1 - dbint - rbint) ; descriptor(binx+dbinx + NBP/2 + 1, biny+dbiny + NBP/2+ 1, mod((bint+dbint),NBO)+1) = ... descriptor(binx+dbinx + NBP/2+ 1, biny+dbiny + NBP/2+ 1, mod((bint+dbint),NBO)+1 ) + weight ; end end end end end end descriptor = reshape(descriptor, 1, NBP * NBP * NBO);%用一维向量表示各梯度值 descriptor = descriptor ./ norm(descriptor); %归一化处理梯度值 %Truncate at 0.2 indx = find(descriptor > 0.2);%找出幅值大于0.2的梯度值 descriptor(indx) = 0.2; %大于0.2的梯度值直接取0.2 descriptor = descriptor ./ norm(descriptor); %再次归一化梯度值 descriptors = [descriptors, descriptor']; end