Diff of /functions/ac_seg.m [000000] .. [088209]

Switch to unified view

a b/functions/ac_seg.m
1
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2
% I : input image
3
% init_mask: initial mask
4
% max_its : maximum iterations
5
% lengthEweight : weight of the length energy 
6
% shapeEweight  : weight of the shape energy
7
% display : display 
8
9
% This code was edited for LV segmentation in MRI from the original code by Shawn Lankton
10
11
function [seg,phi] = ac_seg(I,init_mask,max_its,lengthEweight,shapeEweight,display)
12
13
  %-- default behavior is to display intermediate outputs
14
  if(~exist('display','var'))
15
    display = true;
16
  end
17
  
18
  %-- ensures image is 2D double matrix
19
  I = im2graydouble(I);    
20
  
21
  %-- Create a signed distance map (SDF) from mask
22
  phi = mask2phi(init_mask);
23
  
24
  phi_prior=phi;
25
  
26
  %--main loop
27
  for its = 1:max_its   % Note: no automatic convergence test
28
29
    idx = find(phi <= 1.2 & phi >= -1.2);  %get the curve's narrow band
30
    
31
    %-- find interior and exterior mean
32
    upts = find(phi<=0);                 % interior points
33
    vpts = find(phi>0);                  % exterior points
34
    u = sum(I(upts))/(length(upts)+eps); % interior mean
35
    v = sum(I(vpts))/(length(vpts)+eps); % exterior mean
36
    
37
    
38
    F = (I(idx)-u).^2-(I(idx)-v).^2; % region-based force from image information
39
    curvature = get_curvature(phi,idx);  % force from curvature penalty
40
    
41
    % derivite of energy function for prior shape
42
    dEdl= -(phi(idx)-phi_prior(idx));
43
    
44
    % note that d phi/dt= - d E/d phi
45
    dphidt = F./max(abs(F)) + lengthEweight*curvature+shapeEweight*dEdl;  % gradient descent to minimize energy
46
    
47
    %-- maintain the CFL condition
48
    dt = .45/(max(dphidt)+eps);
49
    
50
    %-- evolve the curve
51
    phi(idx) = phi(idx) + dt*dphidt;
52
53
    indicator=0;
54
     
55
    %-- Keep SDF smooth
56
    phi = sussman(phi, .5);
57
58
    %-- intermediate output
59
    if((display>0)&&(mod(its,20) == 0)) 
60
      showCurveAndPhi(I,phi,its);  
61
    end
62
    if indicator==1
63
        disp(['stopped at:',num2str(its)])
64
        break
65
    end
66
  end
67
  
68
  %-- final output
69
  if(display)
70
    showCurveAndPhi(I,phi,its);
71
  end
72
  
73
  %-- make mask from SDF
74
  seg = phi<=0; %-- Get mask from levelset
75
76
  
77
%---------------------------------------------------------------------
78
%---------------------------------------------------------------------
79
%-- AUXILIARY FUNCTIONS ----------------------------------------------
80
%---------------------------------------------------------------------
81
%---------------------------------------------------------------------
82
  
83
  
84
%-- Displays the image with curve superimposed
85
function showCurveAndPhi(I, phi, i)
86
   max_range=min(200,max(I(:)));
87
  imshow(I,'initialmagnification',200,'displayrange',[0 max_range]); hold on;
88
  contour(phi, [0 0], 'g','LineWidth',4);
89
  contour(phi, [0 0], 'k','LineWidth',2);
90
  hold off; title([num2str(i) ' Iterations']); drawnow;
91
  
92
%-- converts a mask to a SDF
93
function phi = mask2phi(init_a)
94
  phi=bwdist(init_a)-bwdist(1-init_a)+im2double(init_a)-.5;
95
  
96
%-- compute curvature along SDF
97
function curvature = get_curvature(phi,idx)
98
    [dimy, dimx] = size(phi);        
99
    [y x] = ind2sub([dimy,dimx],idx);  % get subscripts
100
101
    %-- get subscripts of neighbors
102
    ym1 = y-1; xm1 = x-1; yp1 = y+1; xp1 = x+1;
103
104
    %-- bounds checking  
105
    ym1(ym1<1) = 1; xm1(xm1<1) = 1;              
106
    yp1(yp1>dimy)=dimy; xp1(xp1>dimx) = dimx;    
107
108
    %-- get indexes for 8 neighbors
109
    idup = sub2ind(size(phi),yp1,x);    
110
    iddn = sub2ind(size(phi),ym1,x);
111
    idlt = sub2ind(size(phi),y,xm1);
112
    idrt = sub2ind(size(phi),y,xp1);
113
    idul = sub2ind(size(phi),yp1,xm1);
114
    idur = sub2ind(size(phi),yp1,xp1);
115
    iddl = sub2ind(size(phi),ym1,xm1);
116
    iddr = sub2ind(size(phi),ym1,xp1);
117
    
118
    %-- get central derivatives of SDF at x,y
119
    phi_x  = -phi(idlt)+phi(idrt);
120
    phi_y  = -phi(iddn)+phi(idup);
121
    phi_xx = phi(idlt)-2*phi(idx)+phi(idrt);
122
    phi_yy = phi(iddn)-2*phi(idx)+phi(idup);
123
    phi_xy = -0.25*phi(iddl)-0.25*phi(idur)...
124
             +0.25*phi(iddr)+0.25*phi(idul);
125
    phi_x2 = phi_x.^2;
126
    phi_y2 = phi_y.^2;
127
    
128
    %-- compute curvature (Kappa)
129
    curvature = ((phi_x2.*phi_yy + phi_y2.*phi_xx - 2*phi_x.*phi_y.*phi_xy)./...
130
              (phi_x2 + phi_y2 +eps).^(3/2)).*(phi_x2 + phi_y2).^(1/2);        
131
  
132
%-- Converts image to one channel (grayscale) double
133
function img = im2graydouble(img)    
134
  [dimy, dimx, c] = size(img);
135
  if(isfloat(img)) % image is a double
136
    if(c==3) 
137
      img = rgb2gray(uint8(img)); 
138
    end
139
  else           % image is a int
140
    if(c==3) 
141
      img = rgb2gray(img); 
142
    end
143
    img = double(img);
144
  end
145
146
%-- level set re-initialization by the sussman method
147
function D = sussman(D, dt)
148
  % forward/backward differences
149
  a = D - shiftR(D); % backward
150
  b = shiftL(D) - D; % forward
151
  c = D - shiftD(D); % backward
152
  d = shiftU(D) - D; % forward
153
  
154
  a_p = a;  a_n = a; % a+ and a-
155
  b_p = b;  b_n = b;
156
  c_p = c;  c_n = c;
157
  d_p = d;  d_n = d;
158
  
159
  a_p(a < 0) = 0;
160
  a_n(a > 0) = 0;
161
  b_p(b < 0) = 0;
162
  b_n(b > 0) = 0;
163
  c_p(c < 0) = 0;
164
  c_n(c > 0) = 0;
165
  d_p(d < 0) = 0;
166
  d_n(d > 0) = 0;
167
  
168
  dD = zeros(size(D));
169
  D_neg_ind = find(D < 0);
170
  D_pos_ind = find(D > 0);
171
  dD(D_pos_ind) = sqrt(max(a_p(D_pos_ind).^2, b_n(D_pos_ind).^2) ...
172
                       + max(c_p(D_pos_ind).^2, d_n(D_pos_ind).^2)) - 1;
173
  dD(D_neg_ind) = sqrt(max(a_n(D_neg_ind).^2, b_p(D_neg_ind).^2) ...
174
                       + max(c_n(D_neg_ind).^2, d_p(D_neg_ind).^2)) - 1;
175
  
176
  D = D - dt .* sussman_sign(D) .* dD;
177
  
178
%-- whole matrix derivatives
179
function shift = shiftD(M)
180
  shift = shiftR(M')';
181
182
function shift = shiftL(M)
183
  shift = [ M(:,2:size(M,2)) M(:,size(M,2)) ];
184
185
function shift = shiftR(M)
186
  shift = [ M(:,1) M(:,1:size(M,2)-1) ];
187
188
function shift = shiftU(M)
189
  shift = shiftL(M')';
190
  
191
function S = sussman_sign(D)
192
  S = D ./ sqrt(D.^2 + 1);    
193
194
  
195
196
197
198