perform_active_contour.m.svn-base
来自「fast marching method」· SVN-BASE 代码 · 共 203 行
SVN-BASE
203 行
function D = perform_active_contour(D0, motion, options)% perform_active_contour - perform active contour resolution%% D = perform_active_contour(D0, motion, options);%% Level set implementation of various active contour, all related to% motion by mean curvature.%% The resolution is done by an explicit euler, the time sep is options.dt% and should be quite small for stability. The maximum time is% options.Tmax.%% In the following, one denotes the curvature of the level sets of D as% Curv(D) = div(grad(D)/|grad(D)|)% and D' = d(D)/dt the time derivative.%% motion can be:% 'mean': D' = |grad(D)| * Curv(D)% 'affine': D' = |grad(D)| * Curv(D)^(1/3)% 'errosion': D' = |grad(D)| * max(Curv(D),0)^(1/3)% 'snakes': D' = E * |grad(D)| * Curv(D) + <grad(E),grad(D)>% 'chan-vese': D' = |grad(D)| * ( Curv(D) - lambda*(D-c1)^2 + lambda*(D-c2)^2 )%% You can provide the parameters in options.E, options.c1, options.c2,% options.lambda. You can turn on the automatic update of c1/c2 using% options.update_c.%% The distance function D is redistanced every options.redistance_freq% iterations.%% To turn off the display, options.do_display=0. You can provide a% background image in options.M.%% See also: display_segmentation.%% Copyright (c) 2007 Gabriel eyredt = getoptions(options, 'dt', 1000);Tmax = getoptions(options, 'Tmax', 1000);do_display = getoptions(options, 'display', 1);display_freq = getoptions(options, 'display_freq', 20);redistance_freq = getoptions(options, 'redistance_freq', 30);lambda = getoptions(options, 'lambda', 0.8);update_c = getoptions(options, 'update_c', 1);c1 = getoptions(options, 'c1', 0.1);c2 = getoptions(options, 'c2', 0.8);nb_svg = getoptions(options, 'nb_svg', 0);solver = getoptions(options, 'solver', 'cg');svg_path = getoptions(options, 'svg_path', ''); % ['results/active-contour/' motion '/']);if strcmp(motion,'chan-vese') || strcmp(motion, 'snake') || strcmp(motion, 'chan-vese-user') E = getoptions(options, 'E', 0, 1);else E = [];endM = getoptions(options, 'M', E(:,:,1));options.bound = 'per';if not(isempty(svg_path)) && not(exist(svg_path)) mkdir(svg_path);endnb_phase = 1;if not(isempty(E)) nb_phase = 2 - (size(E,3)==1);end if strcmp(motion, 'snake') % pre compute gradient of the energy dE = divgrad(E,options);endD = D0;n = size(D0,1);epsilon = 1e-3;niter = round(Tmax/dt);if nb_svg>0 % distribute more svg at the begining of the iterations svg_list = round( 1 + linspace(0,1,nb_svg+2).^3*niter ); svg_list(1) = []; % delta_svg = niter/nb_svg; if not(exist(svg_path)) mkdir(svg_path); endelse delta_svg = Inf;endnext_svg = 0;nb = 0;for i=1:niter progressbar(i,niter); for k=1:nb_phase g0(:,:,:,k) = divgrad(D(:,:,k),options); d(:,:,k) = max(epsilon, sqrt(sum(g0(:,:,:,k).^2,3)) ); g(:,:,:,k) = g0(:,:,:,k) ./ repmat( d(:,:,k), [1 1 2] ); end if strcmp(solver, 'grad') %%%% gradient %%%% switch lower(motion) case 'mean' dD = d .* divgrad( g,options ); case 'affine' gg = divgrad(g,options); dD = d .* sign(gg) .* abs(gg).^(1/3); case 'errosion' dD = d .* max(divgrad(g,options),0).^(1/3); case 'snake' dD = E .* d .* divgrad( g,options ) + sum(dE.*g0, 3); case 'chan-vese' % compute the inner / outer constant if update_c c1 = mean( E(D>=0) ); c2 = mean( E(D<0) ); end dD = d .* ( divgrad( g,options ) - lambda*(E-c1).^2 + lambda*(E-c2).^2 ); case 'chan-vese-user' if nb_phase==1 % single phase dD = d .* ( divgrad( g,options ) + E ); else for k=1:nb_phase dG = divgrad( g(:,:,:,k),options ); dD(:,:,k) = d(:,:,k) .* ( dG - E(:,:,2*k-1).*(D(:,:,3-k)>0) - E(:,:,2*k).*(D(:,:,3-k)<=0) ); end end otherwise error('Unknown motion'); end D = D + dt*dD; else options.E = []; switch lower(motion) case 'mean' C = zeros(n); case 'snake' options.E = E; C = sum(dE.*g0, 3); case 'chan-vese' % compute the inner / outer constant if update_c c1 = mean( E(D>=0) ); c2 = mean( E(D<0) ); end C = - lambda*(E-c1).^2 + lambda*(E-c2).^2; case 'chan-vese-user' C = E; otherwise error('Unknown motion'); end %%%% conjugate gradient %%%% % right hand side y = D + dt*C; options.d = d; options.dt = dt; options.n = n; options.ncols = n^2; options.niter_max = 20; ptions.epsilon = 1e-8; options.x = D(:); [D,err,k] = perform_conjugate_gradient(@callback_active_contour,y(:),options); D = reshape(D,n,n); end if mod(i,redistance_freq)==0 for k=1:nb_phase D(:,:,k) = perform_redistancing(D(:,:,k), options); end end if do_display && ( mod(i,display_freq)==1 || i>=next_svg ) A = prod(D,3); if strcmp(motion, 'snake') || strcmp(motion, 'chan-vese') || strcmp(motion, 'chan-vese-user') A = M; end clf; display_segmentation(D,A); drawnow; if 0 clf; hold on; if strcmp(motion, 'snake') || strcmp(motion, 'chan-vese') || strcmp(motion, 'chan-vese-user') imagesc(M); axis image; axis off; axis([1 n 1 n]); else imagesc(D); axis image; axis off; axis([1 n 1 n]); end% h = plot(c(1,:), c(2,:), 'r'); [c,h] = contour(D,[0 0], 'r'); set(h, 'LineWidth', 2); drawnow; hold off; colormap gray(256); end if i>=next_svg nb = nb+1; % save image saveas(gcf, [svg_path motion '-' num2string_fixeddigit(nb, 2) '.png'], 'png'); next_svg = svg_list(nb); % next_svg+delta_svg; end endend
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?