function [snake_pnts,e] = snake(pnts, alpha, beta, max_delta_x, resol_x, ... max_delta_y, resol_y, feat_img) % SNAKES % By Chris Bregler and Malcolm Slaney, Interval Technical Report IRC 1995-017 % Copyright (c) 1995 Interval Research Corporation. % % Usage % % [snake_pnts,e] = snake(pnts, alpha, beta, ... % max_delta_y, resol_y, max_delta_x, resol_x, feat_img) % % This function computes one iteration of the energy-minimization of % active contour models described in the paper "Using Dynamic Programming % for Solving Variational Problems in Vision" by Amir A. Amini, Terry E. % Weymouth, and Ramesh C. Jain, IEEE Transactions on Pattern Analysis and % Machine Intelligence, Vol. 12, No. 9, September 1990, pp 855-867. % % Snakes align a contour to some feature maxima in an image (for example) % image boundaries) using dynamic programming. The quality of the % alignment is measured by an energy function consisting of an internal % "contour-smoothness-term" and an external feature term (equation 50 in the % paper). Minimizing this energy term leads to a contour that trade offs % these two criterias (smoothness + maximal feature responses) in some desired % way. % % Inputs: % pnts Starting contour. Each row is a [x,y] coordinate. % alpha Energy contributed by the distance between control points. % Set to zero if length of slope doesn't matter. % beta Energy contributed by the curvature of the snake. Larger % values of beta cause bends in the snake to have a high cost % and lead to smoother snakes. % max_delta_y Max number of pixels to move each contour point vertically % resol_y Contour points will be moved by multiples of resol_y % max_delta_x Analog to max_delta_y % resol_x Analog to resol_y % feat_img 2D-Array of the feature responses in the image. For example % it can contain the magnitude of the image gradients % % Outputs: % snake_pnts New contour points. % e Energy value of these new contour points % % SNAKES - A MatLab MEX file to demonstrate snake contour-following. % This Software was developed by Chris Bregler and Malcolm Slaney of % Interval Research Corporation. % Copyright (c) 1995 Interval Research Corporation. % % This is experimental software and is being provided to Licensee % 'AS IS.' Although the software has been tested on a PowerMac % 8100 running version 4.2c of MatLab with MEX support and on an % SGI running version 4.2c, Interval makes no warranties relating % to the software's performance on these or any other platforms. % % Disclaimer % THIS SOFTWARE IS BEING PROVIDED TO YOU 'AS IS.' INTERVAL MAKES % NO EXPRESS, IMPLIED OR STATUTORY WARRANTY OF ANY KIND FOR THE % SOFTWARE INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY OF % PERFORMANCE, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. % IN NO EVENT WILL INTERVAL BE LIABLE TO LICENSEE OR ANY THIRD % PARTY FOR ANY DAMAGES, INCLUDING LOST PROFITS OR OTHER INCIDENTAL % OR CONSEQUENTIAL DAMAGES, EVEN IF INTERVAL HAS BEEN ADVISED OF % THE POSSIBLITY THEREOF. % % This software program is owned by Interval Research % Corporation, but may be used, reproduced, modified and % distributed by Licensee. Licensee agrees that any copies of the % software program will contain the same proprietary notices and % warranty disclaimers which appear in this software program. if resol_y < 1; resol_y = 1; end; if resol_x < 1; resol_x = 1; end; n = size(pnts,1); [row,col] = size(feat_img); target = reshape(feat_img,row*col,1); scan_y = -max_delta_y:resol_y:max_delta_y; scan_x = -max_delta_x:resol_x:max_delta_x; num_scan_y = size(scan_y,2); num_scan_x = size(scan_x,2); num_states = num_scan_y * num_scan_x; fprintf('n = %d; num_states = %d; ',n,num_states); delta_x = ones(num_scan_y,1)*scan_x; delta_y = scan_y'*ones(1,num_scan_x); delta_x = reshape(delta_x,1,num_states); delta_y = reshape(delta_y,1,num_states); states_x = round(pnts(:,1))*ones(1,num_states) + ones(n,1)*delta_x; states_y = round(pnts(:,2))*ones(1,num_states) + ones(n,1)*delta_y; % take care of boundary cases states_x = min(max(states_x,1),col); states_y = min(max(states_y,1),row); states_i = (states_x-1)*row + states_y; Smat = zeros(n,num_states^2); Imat = zeros(n,num_states^2); % forward pass for v2 = 1:num_states, Smat(1,(v2-1)*num_states+1:v2*num_states) = ... -target(states_i(1,:))'; end; for k = 2:n-1, fprintf('.'); % debug for v2 = 1:num_states, for v1 = 1:num_states, v0_domain = 1:num_states; [y,i] = min( Smat(k-1,(v1-1)*num_states+v0_domain) ... + alpha(k)*( (states_x(k,v1)-states_x(k-1,v0_domain)).^2 ... + (states_y(k,v1)-states_y(k-1,v0_domain)).^2) ... + beta(k)*( (states_x(k+1,v2)-2*states_x(k,v1) ... + states_x(k-1,v0_domain)).^2 ... + (states_y(k+1,v2)-2*states_y(k,v1) ... + states_y(k-1,v0_domain)).^2) ); Smat(k,(v2-1)*num_states+v1) = ... y-target(states_i(k,v1)); Imat(k,(v2-1)*num_states+v1) = i; end; end; end; for v1 = 1:num_states, v0_domain = 1:num_states; [y,i] = min( Smat(n-1,(v1-1)*num_states+v0_domain) ... + alpha(n)*( (states_x(n,v1)-states_x(n-1,v0_domain)).^2 ... + (states_y(n,v1)-states_y(n-1,v0_domain)).^2)); Smat(n,v1) = y-target(states_i(n,v1)); Imat(n,v1) = i; end; [e,final_i] = min(Smat(n,1:num_states)); % backward pass snake_pnts = zeros(n,2); snake_pnts(n,:) = [states_x(n,final_i),states_y(n,final_i)]; v1 = final_i; v2 = 1; for k=n-1:-1:1, v = Imat(k+1,(v2-1)*num_states+v1); v2 = v1; v1 = v; snake_pnts(k,:) = [states_x(k,v1),states_y(k,v1)]; end; fprintf('\n');