0001 function [ FV ] = avw_bet(avw,bt)
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018 if ~exist('bt','var'), bt = 0.5; end
0019 if isempty(bt), bt = 0.5; end
0020
0021 fprintf('...estimating brain surface...'); tic;
0022
0023 [FV,t,t02,t98,tm,COG] = avw_bet_init(avw);
0024
0025 Hf = figure;
0026 Hp = patch('vertices',FV.vertices,...
0027 'faces',FV.faces,...
0028 'facecolor',[.8 .75 .75],...
0029 'edgecolor',[.6 .6 .6]);
0030 light
0031 drawnow
0032
0033 for i = 1:1000,
0034
0035 updateStr = sprintf('update iteration: %04d\n',i);
0036 set(Hf,'Name',['avw_bet, ',updateStr]);
0037 drawnow
0038
0039
0040 [FV.normals,FV.unit_normals] = mesh_vertex_normals(FV);
0041
0042
0043 [S,Sn,St,Sn_unit] = avw_bet_update1(FV);
0044
0045
0046 [f2,L] = avw_bet_update2(FV,COG.voxels,Sn);
0047
0048
0049 [ f3, t1, Imin, Imax] = avw_bet_update3(FV,avw,bt,Sn,t,t02,tm);
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062 f2 = repmat(f2,1,3);
0063 f3 = repmat(f3,1,3);
0064 L = repmat(L ,1,3);
0065
0066 u1 = 0.5 * St;
0067 u2 = f2 .* Sn;
0068 u3 = 0.05 .* f3 .* L .* Sn_unit;
0069
0070 u = u1 + u2 + u3;
0071
0072
0073 FV.vertices = FV.vertices + u;
0074
0075 set(Hp,'vertices',FV.vertices);
0076 drawnow
0077
0078 end
0079
0080
0081
0082
0083
0084
0085
0086
0087 time = toc; fprintf('done (%5.2f sec)\n',time);
0088 return
0089
0090
0091
0092
0093
0094
0095
0096 function [FV,t,t02,t98,tm,COG] = avw_bet_init(avw)
0097
0098
0099
0100 [bins,freq,freq_nozero] = avw_histogram(avw,2,[],0);
0101
0102
0103
0104
0105 binbyfreq = bins .* freq;
0106
0107 t02_tmp = 0.02 * sum(binbyfreq);
0108 t98_tmp = 0.98 * sum(binbyfreq);
0109
0110 i = 1;
0111 while sum(binbyfreq(1:i)) < t02_tmp, i = i + 1; end
0112 t02 = bins(i-1);
0113
0114 i = 1; while sum(binbyfreq(1:i)) < t98_tmp, i = i + 1; end
0115 t98 = bins(i);
0116
0117
0118
0119
0120
0121
0122 t = (0.1 * (t98 - t02)) + t02;
0123
0124
0125
0126 bin = avw;
0127
0128 voxels_lt_t = find(avw.img < t);
0129 bin.img(voxels_lt_t) = 0;
0130
0131 voxels_gt_t98 = find(avw.img > t98);
0132 bin.img(voxels_gt_t98) = 0;
0133
0134 nonzero = find(bin.img);
0135 bin.img(nonzero) = 1;
0136
0137
0138 [i,j,k] = ind2sub(size(avw.img),nonzero);
0139
0140
0141
0142 COG = avw_center_mass(bin);
0143 xCOG = COG.voxels(1);
0144 yCOG = COG.voxels(2);
0145 zCOG = COG.voxels(3);
0146
0147 radius_voxel = sqrt( (i-xCOG).^2 + (j-yCOG).^2 + (k-zCOG).^2 );
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159 radius_mean = mean(radius_voxel) / 2;
0160
0161
0162
0163
0164
0165 tm = median(avw.img(nonzero));
0166
0167
0168
0169
0170 FV = sphere_tri('ico',4,radius_mean);
0171 FV.edge = mesh_edges(FV);
0172
0173 Nvert = size(FV.vertices,1);
0174 A = repmat([xCOG,yCOG,zCOG],Nvert,1);
0175 FV.vertices = FV.vertices + A;
0176
0177 return
0178
0179
0180
0181
0182
0183
0184
0185 function [S,Sn,St,Sn_unit] = avw_bet_update1(FV),
0186
0187
0188
0189
0190
0191 Nvert = size(FV.vertices,1);
0192
0193 for index = 1:Nvert,
0194
0195 v = FV.vertices(index,:);
0196 x = v(1);
0197 y = v(2);
0198 z = v(3);
0199
0200 unit_normal = FV.unit_normals(index,:);
0201
0202
0203 vi = find(FV.edge(index,:));
0204 neighbour_vertices = FV.vertices(vi,:);
0205 X = neighbour_vertices(:,1);
0206 Y = neighbour_vertices(:,2);
0207 Z = neighbour_vertices(:,3);
0208
0209
0210
0211 Xmean = mean(X);
0212 Ymean = mean(Y);
0213 Zmean = mean(Z);
0214
0215
0216
0217
0218 s = [ Xmean - x, Ymean - y, Zmean - z];
0219
0220
0221 sn = dot( s, unit_normal ) * unit_normal;
0222
0223
0224 st = s - sn;
0225
0226 S(index,:) = s;
0227 Sn(index,:) = sn;
0228 St(index,:) = st;
0229
0230 Sn_unit(index,:) = sn ./ sqrt( (sn(1) - v(1)).^2 + (sn(2) - v(2)).^2 + (sn(3) - v(3)).^2 );
0231
0232 end
0233
0234 return
0235
0236
0237
0238
0239
0240
0241
0242 function [f2,L] = avw_bet_update2(FV,origin,Sn),
0243
0244
0245
0246
0247
0248 xo = origin(1); yo = origin(2); zo = origin(3);
0249
0250
0251
0252 radius_min = 3.33;
0253 radius_max = 10.00;
0254
0255
0256 E = mean([(1 / radius_min), (1 / radius_max)]);
0257 F = 6 * ( (1 / radius_min) - (1 / radius_max) );
0258
0259 Nvert = size(FV.vertices,1);
0260
0261 f2 = zeros(Nvert,1);
0262 L = zeros(Nvert,1);
0263
0264 for index = 1:Nvert,
0265
0266
0267 vi = find(FV.edge(index,:));
0268
0269
0270
0271 edge_distance = FV.edge(index,vi);
0272 L(index) = mean(edge_distance);
0273
0274
0275 sn = Sn(index,:);
0276 sn_mag = vector_magnitude(sn);
0277
0278
0279 radius_of_curvature = (L(index) ^ 2) / (2 * sn_mag);
0280
0281 f2(index) = (1 + tanh( F * (1 / radius_of_curvature - E))) / 2;
0282
0283 end
0284
0285 return
0286
0287
0288
0289
0290
0291
0292
0293
0294 function [ f3, t1, Imin, Imax] = avw_bet_update3(FV,avw,bt,sn,t,t02,tm)
0295
0296
0297
0298
0299
0300
0301
0302 d1 = 20;
0303 d2 = d1/2;
0304
0305 Nvert = size(FV.vertices,1);
0306
0307 t1 = zeros(Nvert,1);
0308 f3 = zeros(Nvert,1);
0309 Imin = zeros(Nvert,1);
0310 Imax = zeros(Nvert,1);
0311
0312 for index = 1:Nvert,
0313
0314 x = FV.vertices(index,1);
0315 y = FV.vertices(index,2);
0316 z = FV.vertices(index,3);
0317
0318 unit_normal = FV.unit_normals(index,:);
0319
0320
0321
0322
0323
0324
0325
0326 d1_distances = [-d1:0.5:0 ]';
0327 d2_distances = [ 0:0.5:d2]';
0328
0329 XYZ = repmat([x y z],length(d1_distances),1);
0330 S1 = XYZ + (d1_distances * unit_normal);
0331 XYZ = repmat([x y z],length(d2_distances),1);
0332 S2 = XYZ + (d2_distances * unit_normal);
0333
0334 X1 = S1(:,1);
0335 Y1 = S1(:,2);
0336 Z1 = S1(:,3);
0337
0338 X2 = S2(:,1);
0339 Y2 = S2(:,2);
0340 Z2 = S2(:,3);
0341
0342
0343
0344 d1_intensity = interp3(avw.img,Y1,X1,Z1,'*nearest');
0345 d2_intensity = interp3(avw.img,Y2,X2,Z2,'*nearest');
0346
0347 Imin(index) = max( [ t02; min([tm; d1_intensity]) ] );
0348 Imax(index) = min( [ tm; max([ t; d2_intensity]) ] );
0349
0350
0351
0352
0353 t1(index) = (Imax(index) - t02) * bt + t02;
0354
0355 f3(index) = ( 2 * (Imin(index) - t1(index)) ) / ( Imax(index) - t02 );
0356
0357 end
0358
0359 return
0360
0361
0362
0363
0364
0365
0366
0367
0368
0369
0370
0371
0372
0373
0374 function [FV,f2,sn,sn_unit,L] = avw_bet_update2_radial(FV,origin),
0375
0376
0377
0378
0379
0380 xo = origin(1); yo = origin(2); zo = origin(3);
0381
0382 Nvert = size(FV.vertices,1);
0383
0384 f2 = zeros(Nvert,1);
0385 sn = zeros(Nvert,3);
0386
0387 for index = 1:Nvert,
0388
0389 v = FV.vertices(index,:);
0390 x = FV.vertices(index,1);
0391 y = FV.vertices(index,2);
0392 z = FV.vertices(index,3);
0393
0394
0395 r = sqrt( (x-xo)2 + (y-yo)2 + (z-zo)2 );
0396
0397
0398 v_unit_vector = ( v - origin ) / r;
0399
0400
0401 l = (x-xo)/r;
0402 m = (y-yo)/r;
0403 n = (z-zo)/r;
0404
0405
0406 vi = find(FV.edge(index,:));
0407 neighbour_vertices = FV.vertices(vi,:);
0408 X = neighbour_vertices(:,1);
0409 Y = neighbour_vertices(:,2);
0410 Z = neighbour_vertices(:,3);
0411
0412
0413 r_neighbours = sqrt( (X-xo).^2 + (Y-yo).^2 + (Z-zo).^2 );
0414 r_neighbours_mean = mean(r_neighbours);
0415 L(index) = r_neighbours_mean;
0416
0417
0418
0419
0420 r_diff = r - r_neighbours_mean;
0421
0422
0423
0424
0425 sn(index,:) = r_diff * v_unit_vector;
0426
0427 snx = sn(index,1);
0428 sny = sn(index,2);
0429 snz = sn(index,3);
0430
0431 sn_unit(index,:) = sn(index,:) ./ sqrt( (snx - v(1)).^2 + (sny - v(2)).^2 + (snz - v(3)).^2 );
0432
0433
0434
0435 edge_distance = FV.edge(index,vi);
0436 edge_distance_mean = mean(edge_distance);
0437
0438
0439 if r_diff,
0440 radius_of_curvature = (edge_distance_mean ^ 2) / (2 * r_diff);
0441 else
0442 radius_of_curvature = 10000;
0443 end
0444
0445
0446 radius_min = 3.33;
0447 radius_max = 10.00;
0448
0449
0450
0451 E = mean([(1 / radius_min), (1 / radius_max)]);
0452 F = 6 * ( (1 / radius_min) - (1 / radius_max) );
0453
0454 f2(index) = (1 + tanh( F * (1 / radius_of_curvature - E))) / 2;
0455
0456 end
0457
0458 return