function [VO,M] = pm_segment(VF,PG,flags) % Segment an MR image into Gray, White & CSF. % % FORMAT VO = pm_segment(PF,PG,flags) % PF - name(s) of image(s) to segment (must have same dimensions). % PG - name(s) of template image(s) for realignment. % - or a 4x4 transformation matrix which maps from the image to % the set of templates. % flags - a structure normally based on defaults.segment % VO - optional output volume % M - affine transformation between template and image to segment % % The algorithm is four step: % % 1) Determine the affine transform which best matches the image with a % template image. If the name of more than one image is passed, then % the first image is used in this step. This step is not performed if % no template images are specified. % % 2) Perform Cluster Analysis with a modified Mixture Model and a-priori % information about the likelihoods of each voxel being one of a % number of different tissue types. If more than one image is passed, % then they they are all assumed to be in register, and the voxel % values are fitted to multi-normal distributions. % % 3) Perform morphometric operations on the grey and white partitions % in order to more accurately identify brain tissue. This is then used % to clean up the grey and white matter segments. % % 4) If no or 2 output arguments is/are specified, then the segmented % images are written to disk. The names of these images have "c1", % "c2" & "c3" appended to the name of the first image passed. The % 'brainmask' is also created with "BrMsk_" as an appendix. % %_______________________________________________________________________ % Refs: % % Ashburner J & Friston KJ (1997) Multimodal Image Coregistration and % Partitioning - a Unified Framework. NeuroImage 6:209-217 % %_______________________________________________________________________ % % The template image, and a-priori likelihood images are modified % versions of those kindly supplied by Alan Evans, MNI, Canada % (ICBM, NIH P-20 project, Principal Investigator John Mazziotta). %_______________________________________________________________________ % % This is a renamed version of the original spm_segment which has been % removed from the main spm distribution, but copied into the FieldMap % toolbox where it is still used. %_______________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % John Ashburner % $Id: pm_segment.m 4873 2012-08-30 19:06:26Z john $ % Create some suitable default values %----------------------------------------------------------------------- dr = fileparts(mfilename('fullpath')); def_flags.estimate.priors = char(... fullfile(dr,'grey.nii'),... fullfile(dr,'white.nii'),... fullfile(dr,'csf.nii')); def_flags.estimate.reg = 0.01; def_flags.estimate.cutoff = 30; def_flags.estimate.samp = 3; def_flags.estimate.bb = [[-88 88]' [-122 86]' [-60 95]']; def_flags.estimate.affreg.smosrc = 8; def_flags.estimate.affreg.regtype = 'mni'; def_flags.estimate.affreg.weight = ''; def_flags.write.cleanup = 1; def_flags.write.wrt_cor = 1; def_flags.write.wrt_brV = 0; def_flags.graphics = 1; if nargin<3, flags = def_flags; end; if ~isfield(flags,'estimate'), flags.estimate = def_flags.estimate; end; if ~isfield(flags.estimate,'priors'), flags.estimate.priors = def_flags.estimate.priors; end; if ~isfield(flags.estimate,'reg'), flags.estimate.reg = def_flags.estimate.reg; end; if ~isfield(flags.estimate,'cutoff'), flags.estimate.cutoff = def_flags.estimate.cutoff; end; if ~isfield(flags.estimate,'samp'), flags.estimate.samp = def_flags.estimate.samp; end; if ~isfield(flags.estimate,'bb'), flags.estimate.bb = def_flags.estimate.bb; end; if ~isfield(flags.estimate,'affreg'), flags.estimate.affreg = def_flags.estimate.affreg; end; if ~isfield(flags.estimate.affreg,'smosrc'), flags.estimate.affreg.smosrc = def_flags.estimate.affreg.smosrc; end; if ~isfield(flags.estimate.affreg,'regtype'), flags.estimate.affreg.regtype = def_flags.estimate.affreg.regtype; end; if ~isfield(flags.estimate.affreg,'weight'), flags.estimate.affreg.weight = def_flags.estimate.affreg.weight; end; if ~isfield(flags,'write'), flags.write = def_flags.write; end; if ~isfield(flags.write,'cleanup'), flags.write.cleanup = def_flags.write.cleanup; end; if ~isfield(flags.write,'wrt_cor'), flags.write.wrt_cor = def_flags.write.wrt_cor; end; if ~isfield(flags.write,'wrt_brV'), flags.write.wrt_brV = def_flags.write.wrt_brV; end; if ~isfield(flags,'graphics'), flags.graphics = def_flags.graphics; end; %----------------------------------------------------------------------- if ischar(VF), VF= spm_vol(VF); end; SP = init_sp(flags.estimate,VF,PG); [x1,x2,x3] = get_sampling(SP.MM,VF,flags.estimate.samp,flags.estimate.bb); BP = init_bp(VF, flags.estimate.cutoff, flags.estimate.reg); CP = init_cp(VF,x3); sums = zeros(8,1); for pp=1:length(x3), [raw,msk] = get_raw(VF,x1,x2,x3(pp)); s = get_sp(SP,x1,x2,x3(pp)); CP = update_cp_est(CP,s,raw,msk,pp); sums = sums + reshape(sum(sum(s,1),2),8,1); end; sums = sums/sum(sums); CP = shake_cp(CP); [CP,BP,SP] = run_segment(CP,BP,SP,VF,sums,x1,x2,x3); %save segmentation_results.mat CP BP SP VF sums [g,w,c] = get_gwc(VF,BP,SP,CP,sums,flags.write.wrt_cor); if flags.write.cleanup, [g,w,c,b] = clean_gwc(g,w,c); end; % Create the segmented images + the brain mask. %----------------------------------------------------------------------- %offs = cumsum(repmat(prod(VF(1).dim(1:2)),1,VF(1).dim(3)))-prod(VF(1).dim(1:2)); %pinfo = [repmat([1/255 0]',1,VF(1).dim(3)) ; offs]; [pth,nm,xt] = fileparts(deblank(VF(1).fname)); if flags.write.wrt_brV Nwrt = 4; else Nwrt = 3; end for j=1:Nwrt, tmp = fullfile(pth,['c', num2str(j), nm, xt]); if j==4, tmp = fullfile(pth,['BrMsk_', nm xt]); end VO(j) = struct(... 'fname',tmp,... 'dim', VF(1).dim(1:3),... 'dt', [spm_type('uint8'), spm_platform('bigend')],... 'mat', VF(1).mat,... 'pinfo', [1/255 0 0]',... 'descrip','Segmented image'); end; if nargout==0 || nargout==2, VO = spm_create_vol(VO); spm_progress_bar('Init',VF(1).dim(3),'Writing Segmented','planes completed'); for pp=1:VF(1).dim(3), VO(1) = spm_write_plane(VO(1),double(g(:,:,pp))/255,pp); VO(2) = spm_write_plane(VO(2),double(w(:,:,pp))/255,pp); VO(3) = spm_write_plane(VO(3),double(c(:,:,pp))/255,pp); if flags.write.wrt_brV VO(4) = spm_write_plane(VO(4),double(b(:,:,pp))/255,pp); end spm_progress_bar('Set',pp); end; spm_progress_bar('Clear'); end; VO(1).dat = g; VO(1).pinfo = VO(1).pinfo(1:2,:); VO(2).dat = w; VO(2).pinfo = VO(2).pinfo(1:2,:); VO(3).dat = c; VO(3).pinfo = VO(3).pinfo(1:2,:); if flags.write.wrt_brV VO(4).dat = b; VO(4).pinfo = VO(4).pinfo(1:2,:); end if nargout==2 M = SP.MM/VF(1).mat; end if flags.graphics, display_graphics(VF,VO,CP.mn,CP.cv,CP.mg); end; return; %======================================================================= %======================================================================= function [y1,y2,y3] = affine_transform(x1,x2,x3,M) y1 = M(1,1)*x1 + M(1,2)*x2 + M(1,3)*x3 + M(1,4); y2 = M(2,1)*x1 + M(2,2)*x2 + M(2,3)*x3 + M(2,4); y3 = M(3,1)*x1 + M(3,2)*x2 + M(3,3)*x3 + M(3,4); return; %======================================================================= %======================================================================= function display_graphics(VF,VS,mn,cv,mg) % Do the graphics nb = 3; spm_figure('Clear','Graphics'); fg = spm_figure('FindWin','Graphics'); if ~isempty(fg), % Show some text %----------------------------------------------------------------------- ax = axes('Position',[0.05 0.8 0.9 0.2],'Visible','off','Parent',fg); text(0.5,0.80, 'Segmentation','FontSize',16,'FontWeight','Bold',... 'HorizontalAlignment','center','Parent',ax); text(0,0.65, ['Image: ' spm_file(VF(1).fname,'short50')],... 'FontSize',14,'FontWeight','Bold','Parent',ax); text(0,0.40, 'Means:','FontSize',12,'FontWeight','Bold','Parent',ax); text(0,0.30, 'Std devs:' ,'FontSize',12,'FontWeight','Bold','Parent',ax); text(0,0.20, 'N vox:','FontSize',12,'FontWeight','Bold','Parent',ax); for j=1:nb, text((j+0.5)/(nb+1),0.40, num2str(mn(1,j)),... 'FontSize',12,'FontWeight','Bold',... 'HorizontalAlignment','center','Parent',ax); text((j+0.5)/(nb+1),0.30, num2str(sqrt(cv(1,1,j))),... 'FontSize',12,'FontWeight','Bold',... 'HorizontalAlignment','center','Parent',ax); text((j+0.5)/(nb+1),0.20, num2str(mg(1,j)/sum(mg(1,:))),... 'FontSize',12,'FontWeight','Bold',... 'HorizontalAlignment','center','Parent',ax); end; if length(VF) > 1, text(0,0.10,... 'Note: only means and variances for the first image are shown',... 'Parent',ax,'FontSize',12); end; M1 = VS(1).mat; M2 = VF(1).mat; for i=1:5, M = spm_matrix([0 0 i*VF(1).dim(3)/6]); img = spm_slice_vol(VF(1),M,VF(1).dim(1:2),1); img(1,1) = eps; ax = axes('Position',... [0.05 0.75*(1-i/5)+0.05 0.9/(nb+1) 0.75/5],... 'Visible','off','Parent',fg); imagesc(rot90(img), 'Parent', ax); set(ax,'Visible','off','DataAspectRatio',[1 1 1]); for j=1:3, img = spm_slice_vol(VS(j),M2\M1*M,VF(1).dim(1:2),1); ax = axes('Position',... [0.05+j*0.9/(nb+1) 0.75*(1-i/5)+0.05 0.9/(nb+1) 0.75/5],... 'Visible','off','Parent',fg); image(rot90(img*64), 'Parent', ax); set(ax,'Visible','off','DataAspectRatio',[1 1 1]); end; end; spm_print; drawnow; end; return; %======================================================================= %======================================================================= function M = get_affine_mapping(VF,VG,aflags) if ~isempty(VG) && ischar(VG), VG = spm_vol(VG); end; if ~isempty(VG) && isstruct(VG), % Affine registration so that a priori images match the image to % be segmented. %----------------------------------------------------------------------- VFS = spm_smoothto8bit(VF(1),aflags.smosrc); % Scale all images approximately equally % --------------------------------------------------------------- for i=1:length(VG), VG(i).pinfo(1:2,:) = VG(i).pinfo(1:2,:)/spm_global(VG(i)); end; VFS(1).pinfo(1:2,:) = VFS(1).pinfo(1:2,:)/spm_global(VFS(1)); spm_plot_convergence('Init','Affine Registration','Mean squared difference','Iteration'); flags = struct('sep',aflags.smosrc, 'regtype',aflags.regtype,'WG',[],'globnorm',0,'debug',0); M = eye(4); [M,scal] = spm_affreg(VG, VFS, flags, M); if ~isempty(aflags.weight), flags.WG = spm_vol(aflags.weight); end; flags.sep = aflags.smosrc/2; M = spm_affreg(VG, VFS, flags, M,scal); spm_plot_convergence('Clear'); elseif all(size(VG) == [4 4]) % Assume that second argument is a matrix that will do the job %----------------------------------------------------------------------- M = VG; else % Assume that image is normalized %----------------------------------------------------------------------- M = eye(4); end return; %======================================================================= %======================================================================= function [x1,x2,x3] = get_sampling(MM,VF,samp,bb1) % Voxels to sample during the cluster analysis %----------------------------------------------------------------------- % A bounding box for the brain in Talairach space. %bb = [ [-88 88]' [-122 86]' [-60 95]']; %c = [bb(1,1) bb(1,2) bb(1,3) 1 % bb(1,1) bb(1,2) bb(2,3) 1 % bb(1,1) bb(2,2) bb(1,3) 1 % bb(1,1) bb(2,2) bb(2,3) 1 % bb(2,1) bb(1,2) bb(1,3) 1 % bb(2,1) bb(1,2) bb(2,3) 1 % bb(2,1) bb(2,2) bb(1,3) 1 % bb(2,1) bb(2,2) bb(2,3) 1]'; %tc = MM\c; %tc = tc(1:3,:)'; %mx = max(tc); %mn = min(tc); %bb = [mn ; mx]; %vx = sqrt(sum(VF(1).mat(1:3,1:3).^2)); %samp = round(max(abs([4 4 4]./vx), [1 1 1])); %x1 = bb(1,1):samp(1):bb(2,1); %x2 = bb(1,2):samp(2):bb(2,2); %x3 = bb(1,3):samp(3):bb(2,3); %return; % A bounding box for the brain in Talairach space. if nargin<4, bb1 = [ [-88 88]' [-122 86]' [-60 95]']; end; % A mapping from a unit radius sphere to a hyper-ellipse % that is just enclosed by the bounding box in Talairach % space. M0 = [diag(diff(bb1)/2) mean(bb1)';[0 0 0 1]]; % The mapping from voxels to Talairach space is MM, % so the ellipse in the space of the image becomes: M0 = MM\M0; % So to work out the bounding box in the space of the % image that just encloses the hyper-ellipse. tmp = M0(1:3,1:3); tmp = diag(tmp*tmp'/diag(sqrt(diag(tmp*tmp')))); bb = round([M0(1:3,4)-tmp M0(1:3,4)+tmp])'; bb = min(max(bb,[1 1 1 ; 1 1 1]),[VF(1).dim(1:3) ; VF(1).dim(1:3)]); % Want to sample about every 3mm tmp = sqrt(sum(VF(1).mat(1:3,1:3).^2))'; samp = round(max(abs(tmp.^(-1)*samp), [1 1 1]')); x1 = bb(1,1):samp(1):bb(2,1); x2 = bb(1,2):samp(2):bb(2,2); x3 = bb(1,3):samp(3):bb(2,3); return; %======================================================================= %======================================================================= function [CP,BP,SP] = run_segment(CP,BP,SP,VF,sums,x1,x2,x3) oll = -Inf; spm_plot_convergence('Init','Segmenting','Log-likelihood','Iteration #'); for iter = 1:64, ll= 0; for pp = 1:length(x3), % Loop over planes bf = get_bp(BP,x1,x2,x3(pp)); [raw,msk] = get_raw(VF,x1,x2,x3(pp)); s = get_sp(SP,x1,x2,x3(pp)); cor = bf.*raw; [P,ll0] = get_p(cor,msk,s,sums,CP,bf); ll = ll + ll0; CP = update_cp_est(CP,P,cor,msk,pp); BP = update_bp_est(BP,P,cor,CP,msk,x1,x2,x3(pp)); end; BP = update_bp(BP); if iter>1, spm_plot_convergence('Set',ll); end; %fprintf('\t%g\n', ll); % Stopping criterion %----------------------------------------------------------------------- if iter == 2, ll2 = ll; elseif iter > 2 && abs((ll-oll)/(ll-ll2)) < 0.0001 break; end; oll = ll; end; spm_plot_convergence('Clear'); return; %======================================================================= %======================================================================= function BP = init_bp(VF,co,reg) m = length(VF); tmp = sqrt(sum(VF(1).mat(1:3,1:3).^2)); BP.nbas = max(round((VF(1).dim(1:3).*tmp)/co),[1 1 1]); BP.B1 = spm_dctmtx(VF(1).dim(1),BP.nbas(1)); BP.B2 = spm_dctmtx(VF(1).dim(2),BP.nbas(2)); BP.B3 = spm_dctmtx(VF(1).dim(3),BP.nbas(3)); nbas = BP.nbas; if prod(BP.nbas)>1, % Set up a priori covariance matrix vx = sqrt(sum(VF(1).mat(1:3,1:3).^2)); kx=(pi*((1:nbas(1))'-1)*pi/vx(1)/VF(1).dim(1)*10).^2; ky=(pi*((1:nbas(2))'-1)*pi/vx(2)/VF(1).dim(2)*10).^2; kz=(pi*((1:nbas(3))'-1)*pi/vx(3)/VF(1).dim(3)*10).^2; % Cost function based on sum of squares of 4th derivatives IC0 = (1*kron(kz.^4,kron(ky.^0,kx.^0)) +... 1*kron(kz.^0,kron(ky.^4,kx.^0)) +... 1*kron(kz.^0,kron(ky.^0,kx.^4)) +... 4*kron(kz.^3,kron(ky.^1,kx.^0)) +... 4*kron(kz.^3,kron(ky.^0,kx.^1)) +... 4*kron(kz.^1,kron(ky.^3,kx.^0)) +... 4*kron(kz.^0,kron(ky.^3,kx.^1)) +... 4*kron(kz.^1,kron(ky.^0,kx.^3)) +... 4*kron(kz.^0,kron(ky.^1,kx.^3)) +... 6*kron(kz.^2,kron(ky.^2,kx.^0)) +... 6*kron(kz.^2,kron(ky.^0,kx.^2)) +... 6*kron(kz.^0,kron(ky.^2,kx.^2)) +... 12*kron(kz.^2,kron(ky.^1,kx.^1)) +... 12*kron(kz.^1,kron(ky.^2,kx.^1)) +... 12*kron(kz.^1,kron(ky.^1,kx.^2)) )*reg; %IC0(1) = max(IC0); BP.IC0 = diag(IC0(2:end)); % Initial estimate for intensity modulation field BP.T = zeros(nbas(1),nbas(2),nbas(3),length(VF)); %----------------------------------------------------------------------- else BP.T = zeros([1 1 1 length(VF)]); BP.IC0 = []; end; BP.Alpha = zeros(prod(BP.nbas(1:3)),prod(BP.nbas(1:3)),m); BP.Beta = zeros(prod(BP.nbas(1:3)),m); return; %======================================================================= %======================================================================= function BP = update_bp_est(BP,p,cor,CP,msk,x1,x2,x3) if prod(BP.nbas)<=1, return; end; B1 = BP.B1(x1,:); B2 = BP.B2(x2,:); B3 = BP.B3(x3,:); for j=1:size(BP.Alpha,3), cr = cor(:,:,j); w1 = zeros(size(cr)); w2 = zeros(size(cr)); for i=[1 2 3 4 5 6 7 8], tmp = p(:,:,i)*CP.cv(j,j,i)^(-1); w1 = w1 + tmp.*(CP.mn(j,i) - cr); w2 = w2 + tmp; end; wt1 = 1 + cr.*w1; wt2 = cr.*(cr.*w2 - w1); wt1(~msk) = 0; wt2(~msk) = 0; BP.Beta(:,j) = BP.Beta(:,j) + kron(B3',spm_krutil(wt1,B1,B2,0)); BP.Alpha(:,:,j) = BP.Alpha(:,:,j) + kron(B3'*B3,spm_krutil(wt2,B1,B2,1)); end; return; %======================================================================= %======================================================================= function BP = update_bp(BP) if prod(BP.nbas)<=1, return; end; for j=1:size(BP.Alpha,3), x = BP.T(:,:,:,j); x = x(:); x = x(2:end); Alpha = BP.Alpha(2:end,2:end,j); Beta = BP.Beta(2:end,j); x = (Alpha + BP.IC0)\(Alpha*x + Beta); BP.T(:,:,:,j) = reshape([0 ; x],BP.nbas(1:3)); BP.Alpha = zeros(size(BP.Alpha)); BP.Beta = zeros(size(BP.Beta)); end; return; %======================================================================= %======================================================================= function bf = get_bp(BP,x1,x2,x3) bf = ones(length(x1),length(x2),size(BP.Alpha,3)); if prod(BP.nbas)<=1, return; end; B1 = BP.B1(x1,:); B2 = BP.B2(x2,:); B3 = BP.B3(x3,:); for i=1:size(BP.Alpha,3), t = reshape(reshape(BP.T(:,:,:,i),... BP.nbas(1)*BP.nbas(2),BP.nbas(3))*B3', BP.nbas(1), BP.nbas(2)); bf(:,:,i) = exp(B1*t*B2'); end; return; %======================================================================= %======================================================================= function [dat,msk] = get_raw(VF,x1,x2,x3) [X1,X2,X3] = ndgrid(x1,x2,x3); for i=1:length(VF), [Y1,Y2,Y3] = affine_transform(X1,X2,X3,VF(i).mat\VF(1).mat); dat(:,:,i) = spm_sample_vol(VF(i),Y1,Y2,Y3,1); end; msk = all(dat,3) & all(isfinite(double(dat)),3); return; %======================================================================= %======================================================================= function CP = init_cp(VF,x3) n = 8; m = length(VF); p = length(x3); CP.mom0 = zeros(1,n,p)+eps; CP.mom1 = zeros(m,n,p); CP.mom2 = zeros(m,m,n,p)+eps; % Occasionally the dynamic range of the images is such that many voxels % all have the same intensity. Adding cv0 is an attempt to improve the % stability of the algorithm if this occurs. The value 0.083 was obtained % from var(rand(1000000,1)). It prbably isn't the best way of doing % things, but it appears to work. CP.cv0 = zeros(m,m); for i=1:m, if spm_type(VF(i).dt(1),'intt'), CP.cv0(i,i)=0.083*mean(VF(i).pinfo(1,:)); end; end; return; %======================================================================= %======================================================================= function CP = shake_cp(CP) CP.mom0(:,5,:) = CP.mom0(:,1,:); CP.mom0(:,6,:) = CP.mom0(:,2,:); CP.mom0(:,7,:) = CP.mom0(:,3,:); CP.mom1(:,5,:) = CP.mom1(:,1,:); CP.mom1(:,6,:) = CP.mom1(:,2,:); CP.mom1(:,7,:) = CP.mom1(:,3,:); CP.mom1(:,8,:) = 0; CP.mom2(:,:,5,:) = CP.mom2(:,:,1,:); CP.mom2(:,:,6,:) = CP.mom2(:,:,2,:); CP.mom2(:,:,7,:) = CP.mom2(:,:,3,:); return; %======================================================================= %======================================================================= function CP = update_cp_est(CP,P,dat,msk,p) m = size(dat,3); d = size(P); P = reshape(P,[d(1)*d(2),d(3)]); dat = reshape(dat,[d(1)*d(2),m]); P(~msk(:),:) = []; dat(~msk(:),:) = []; for i=1:size(CP.mom0,2), CP.mom0(1,i,p) = sum(P(:,i)); CP.mom1(:,i,p) = sum((P(:,i)*ones(1,m)).*dat)'; CP.mom2(:,:,i,p) = ((P(:,i)*ones(1,m)).*dat)'*dat; end; for i=1:size(CP.mom0,2), CP.mg(1,i) = sum(CP.mom0(1,i,:),3); CP.mn(:,i) = sum(CP.mom1(:,i,:),3)/CP.mg(1,i); tmp = (CP.mg(1,i).*CP.mn(:,i))*CP.mn(:,i)'; tmp = tmp-eye(size(tmp))*eps*1e6; CP.cv(:,:,i) = (sum(CP.mom2(:,:,i,:),4) - tmp)/CP.mg(1,i) + CP.cv0; end; CP.mg = CP.mg/sum(CP.mg); return; %======================================================================= %======================================================================= function [p,ll] = get_p(cor,msk,s,sums,CP,bf) d = [size(cor) 1 1]; n = size(CP.mg,2); cor = reshape(cor,d(1)*d(2),d(3)); cor = cor(msk,:); p = zeros(d(1)*d(2),n); if ~any(msk), p = reshape(p,d(1),d(2),n); ll=0; return; end; for i=1:n, amp = 1/sqrt((2*pi)^d(3) * det(CP.cv(:,:,i))); dst = (cor-ones(size(cor,1),1)*CP.mn(:,i)')/sqrtm(CP.cv(:,:,i)); dst = sum(dst.*dst,2); tmp = s(:,:,i); p(msk,i) = (amp*CP.mg(1,i)/sums(i))*exp(-0.5*dst).*tmp(msk) +eps; end; sp = sum(p,2); ll = sum(log(sp(msk).*bf(msk)+eps)); sp(~msk) = Inf; for i=1:n, p(:,i) = p(:,i)./sp; end; p = reshape(p,d(1),d(2),n); return; %======================================================================= %======================================================================= function SP = init_sp(flags,VF,PG) SP.VB = spm_vol(flags.priors); MM = get_affine_mapping(VF,PG,flags.affreg); %VF = spm_vol(PF); SP.MM = MM*VF(1).mat; SP.w = 0.98; return; %======================================================================= %======================================================================= function s = get_sp(SP,x1,x2,x3) [X1,X2,X3] = ndgrid(x1,x2,x3); [Y1,Y2,Y3] = affine_transform(X1,X2,X3,SP.VB(1).mat\SP.MM); w1 = SP.w; w2 = (1-w1)/2; s = zeros([size(Y1),4]); for i=1:3, s(:,:,i) = spm_sample_vol(SP.VB(i),Y1,Y2,Y3,1)*w1+w2; end; s(:,:,4:8) = repmat(abs(1-sum(s(:,:,1:3),3))/5,[1 1 5]); return; %======================================================================= %======================================================================= function [g,w,c] = get_gwc(VF,BP,SP,CP,sums,wc) if wc, VC = VF; for j=1:length(VF), [pth,nm,xt,vr] = spm_fileparts(deblank(VF(j).fname)); VC(j).fname = fullfile(pth,['m' nm xt vr]); VC(j).descrip = 'Bias corrected image'; end; VC = spm_create_vol(VC); end; spm_progress_bar('Init',VF(1).dim(3),'Creating Segmented','planes completed'); x1 = 1:VF(1).dim(1); x2 = 1:VF(1).dim(2); x3 = 1:VF(1).dim(3); g = uint8(0); g(VF(1).dim(1),VF(1).dim(2),VF(1).dim(3)) = 0; w = uint8(0); w(VF(1).dim(1),VF(1).dim(2),VF(1).dim(3)) = 0; c = uint8(0); c(VF(1).dim(1),VF(1).dim(2),VF(1).dim(3)) = 0; for pp=1:length(x3), bf = get_bp(BP,x1,x2,x3(pp)); [raw,msk] = get_raw(VF,x1,x2,x3(pp)); cor = raw.*bf; if wc, for j=1:length(VC), VC(j) = spm_write_plane(VC(j),cor(:,:,j),pp); end; end; s = get_sp(SP,x1,x2,x3(pp)); p = get_p(cor,msk,s,sums,CP,bf); g(:,:,pp) = uint8(round(p(:,:,1)*255)); w(:,:,pp) = uint8(round(p(:,:,2)*255)); c(:,:,pp) = uint8(round(p(:,:,3)*255)); spm_progress_bar('Set',pp); end; spm_progress_bar('Clear'); return; %======================================================================= %======================================================================= function [g,w,c,b] = clean_gwc(g,w,c) b = w; b(1) = w(1); % Build a 3x3x3 seperable smoothing kernel %----------------------------------------------------------------------- kx=[0.75 1 0.75]; ky=[0.75 1 0.75]; kz=[0.75 1 0.75]; sm=sum(kron(kron(kz,ky),kx))^(1/3); kx=kx/sm; ky=ky/sm; kz=kz/sm; % Erosions and conditional dilations %----------------------------------------------------------------------- niter = 32; spm_progress_bar('Init',niter,'Extracting Brain','Iterations completed'); for j=1:niter, if j>2, th=0.15; else th=0.6; end; % Dilate after two its of erosion. for i=1:size(b,3), gp = double(g(:,:,i)); wp = double(w(:,:,i)); bp = double(b(:,:,i))/255; bp = (bp>th).*(wp+gp); b(:,:,i) = uint8(round(bp)); end; spm_conv_vol(b,b,kx,ky,kz,-[1 1 1]); spm_progress_bar('Set',j); end; th = 0.05; for i=1:size(b,3), gp = double(g(:,:,i))/255; wp = double(w(:,:,i))/255; cp = double(c(:,:,i))/255; bp = double(b(:,:,i))/255; bp = ((bp>th).*(wp+gp))>th; g(:,:,i) = uint8(round(255*gp.*bp./(gp+wp+cp+eps))); w(:,:,i) = uint8(round(255*wp.*bp./(gp+wp+cp+eps))); c(:,:,i) = uint8(round(255*(cp.*bp./(gp+wp+cp+eps)+cp.*(1-bp)))); b(:,:,i) = uint8(round(255*bp)); end; spm_progress_bar('Clear'); return;