root / src / lsm_lib.h @ 9
Historique | Voir | Annoter | Télécharger (17,91 ko)
1 |
/*
|
---|---|
2 |
Copyright 2016 ENS de Lyon
|
3 |
|
4 |
File author(s):
|
5 |
Typhaine Moreau, Annamaria Kiss <annamaria.kiss@ens-lyon.fr.fr>
|
6 |
|
7 |
See accompanying file LICENSE.txt
|
8 |
*/
|
9 |
|
10 |
#include <iostream> |
11 |
#include <math.h> |
12 |
#include <sstream> |
13 |
#include <vector> |
14 |
#include <fstream> |
15 |
#include <algorithm> |
16 |
|
17 |
#include "CImg.h" |
18 |
|
19 |
using namespace cimg_library; |
20 |
using namespace std; |
21 |
|
22 |
|
23 |
//**************************************** GLOBAL IMAGE *************************************************************************
|
24 |
|
25 |
//Write an image image
|
26 |
//----------------------------------------------------------------------------
|
27 |
int imsave(string filename, float tailleVoxel[3], CImg<unsigned char> const & img) |
28 |
{ |
29 |
img.save_inr(filename.c_str(),tailleVoxel); |
30 |
string zip="gzip -f "+filename;
|
31 |
if(system(zip.c_str()));
|
32 |
cout<<"Image saved in file :"<<filename<<".gz"<<endl; |
33 |
cout<<" - Voxel size : ("<<tailleVoxel[0]<<","<<tailleVoxel[1]<<","<<tailleVoxel[2]<<")"<<endl; |
34 |
cout<<" - Image size : ("<<img.width()<<","<<img.height()<<","<<img.depth()<<")"<<endl; |
35 |
return 1; |
36 |
} |
37 |
|
38 |
//Read an image image
|
39 |
//----------------------------------------------------------------------------
|
40 |
CImg<unsigned char> imread(string &filename, float (&tailleVoxel)[3]) |
41 |
{ |
42 |
CImg<unsigned char> img_prev; |
43 |
cout<<"Image read : "<<filename<<endl;
|
44 |
if(filename.compare(filename.size()-4,4,".inr")==0) |
45 |
{ |
46 |
img_prev.get_load_inr(filename.c_str(),tailleVoxel); // reads resolution
|
47 |
} |
48 |
else if(filename.compare(filename.size()-7,7,".inr.gz")==0) |
49 |
{ |
50 |
string oldname = filename; |
51 |
filename.erase(filename.size()-3);
|
52 |
string zip="gunzip -c "+oldname+" > "+filename; |
53 |
if(system(zip.c_str())); // decompress image file |
54 |
img_prev.load(filename.c_str()); //read image
|
55 |
img_prev.get_load_inr(filename.c_str(),tailleVoxel); // read resolution
|
56 |
zip="rm "+filename;
|
57 |
if(system(zip.c_str())); //removes decompressed image |
58 |
} |
59 |
else
|
60 |
{cout<<"!! wrong file extension : "<<filename<<endl;
|
61 |
} |
62 |
cout<<" - Voxel size : ("<<tailleVoxel[0]<<","<<tailleVoxel[1]<<","<<tailleVoxel[2]<<")"<<endl; |
63 |
cout<<" - Image size : ("<<img_prev.width()<<","<<img_prev.height()<<","<<img_prev.depth()<<")"<<endl; |
64 |
return img_prev;
|
65 |
} |
66 |
|
67 |
//Invert the image
|
68 |
//----------------------------------------------------------------------------
|
69 |
CImg<unsigned char> invert_image(CImg<unsigned char> const & img) |
70 |
{ |
71 |
CImg<unsigned char> unity(img._width,img._height,img._depth,1,1); |
72 |
CImg<unsigned char> inverted = unity - img; |
73 |
return inverted;
|
74 |
} |
75 |
|
76 |
//Add black slices on each side of the image
|
77 |
//----------------------------------------------------------------------------
|
78 |
CImg<float> add_side_slices(CImg<float> const & img, int side) |
79 |
{ |
80 |
int s=side*2; |
81 |
CImg<float> newImg(img._width+s,img._height+s,img._depth+s,1,1); |
82 |
|
83 |
cimg_forXYZ(img,x,y,z) |
84 |
{ |
85 |
newImg(x+side,y+side,z+side)=img(x,y,z); |
86 |
} |
87 |
return newImg;
|
88 |
} |
89 |
|
90 |
//Remove slices
|
91 |
//----------------------------------------------------------------------------
|
92 |
CImg<float> remove_side_slices(CImg<float> const & img, int side) |
93 |
{ |
94 |
int s=side*2; |
95 |
CImg<float> newImg(img._width-s,img._height-s,img._depth-s,1,0); |
96 |
|
97 |
cimg_forXYZ(newImg,x,y,z) |
98 |
{ |
99 |
newImg(x,y,z)=img(x+side,y+side,z+side); |
100 |
} |
101 |
return newImg;
|
102 |
} |
103 |
|
104 |
//Threshold linear along Z 1:background 0:cells
|
105 |
//----------------------------------------------------------------------------
|
106 |
CImg<unsigned char> threshold_linear_alongZ(CImg<float> const & img, int t1, int t2) |
107 |
{ |
108 |
CImg<unsigned char> outside(img._width,img._height,img._depth,1,0); |
109 |
for(int z=0; z<img._depth ; z++) |
110 |
{ |
111 |
cimg_forXY(outside,x,y) |
112 |
{ |
113 |
float thresh = t1 + (t2-t1)*(z*1.0/img._depth); |
114 |
if(img(x,y,z)<thresh)
|
115 |
{outside(x,y,z)=1;}
|
116 |
} |
117 |
} |
118 |
outside.label(); |
119 |
cimg_forXYZ(outside,x,y,z) |
120 |
{ |
121 |
if(outside(x,y,z)>0) {outside(x,y,z)=0;} |
122 |
else {outside(x,y,z)=1;} |
123 |
} |
124 |
return outside;
|
125 |
} |
126 |
|
127 |
//LSM contour init +c0 background, -c0 cells
|
128 |
//--------------------------------------------------------------------------
|
129 |
CImg<float> lsm_contour_init(CImg<unsigned char> const & region,int c0) |
130 |
{ |
131 |
CImg<float> initLSM(region._width,region._height,region._depth,1,c0); |
132 |
initLSM=initLSM-2*c0*region;
|
133 |
return initLSM;
|
134 |
} |
135 |
|
136 |
//Gradient 3D with central finite differences
|
137 |
//----------------------------------------------------------------------------
|
138 |
CImgList<float> gradient(CImg<float> const & img) |
139 |
{ |
140 |
//List of 3 images the same size as img
|
141 |
CImgList<float> grad(3,img._width,img._height,img._depth,1,0); |
142 |
|
143 |
//Image loop with a 3*3*3 neighborhood
|
144 |
CImg_3x3x3(I,float);
|
145 |
cimg_for3x3x3(img,x,y,z,0,I,float) |
146 |
{ |
147 |
grad(0,x,y,z) = (Incc - Ipcc)/2; //grad x = (img(x+1,y,z)-img(x-1,y,z))/2 |
148 |
grad(1,x,y,z) = (Icnc - Icpc)/2; //grad y |
149 |
grad(2,x,y,z) = (Iccn - Iccp)/2; //grad z |
150 |
} |
151 |
return grad;
|
152 |
} |
153 |
|
154 |
//Norm of the gradient
|
155 |
//---------------------------------------------------------------------------
|
156 |
CImg<float> gradient_norm(CImg<float> const & img) |
157 |
{ |
158 |
CImgList<float> grad = gradient(img);
|
159 |
CImg<float> res(grad[0]._width,grad[0]._height,grad[0]._depth,1,0); |
160 |
float f=0; |
161 |
cimg_forXYZ(res,x,y,z) |
162 |
{ |
163 |
f=grad(0,x,y,z)*grad(0,x,y,z) + grad(1,x,y,z)*grad(1,x,y,z) + grad(2,x,y,z)*grad(2,x,y,z); |
164 |
res(x,y,z)=sqrt(f); |
165 |
} |
166 |
return res;
|
167 |
} |
168 |
|
169 |
|
170 |
//Edge indicator
|
171 |
//---------------------------------------------------------------------------
|
172 |
CImg<float> edge_indicator(CImgList<float> const & grad) |
173 |
{ |
174 |
CImg<float> res(grad[0]._width,grad[0]._height,grad[0]._depth,1,0); |
175 |
float f=0; |
176 |
cimg_forXYZ(res,x,y,z) |
177 |
{ |
178 |
f=grad(0,x,y,z)*grad(0,x,y,z) + grad(1,x,y,z)*grad(1,x,y,z) + grad(2,x,y,z)*grad(2,x,y,z); |
179 |
res(x,y,z)=1.0/(1.0+f); |
180 |
//res(x,y,z)=exp(-f);
|
181 |
} |
182 |
return res;
|
183 |
} |
184 |
|
185 |
//Edge indicator 1 (gradient)
|
186 |
//---------------------------------------------------------------------------
|
187 |
CImg<float> edge_indicator1(CImg<float> const & img) |
188 |
{ |
189 |
CImgList<float> grad;
|
190 |
grad = gradient(img); |
191 |
CImg<float> res(img._width,img._height,img._depth,1,0); |
192 |
float f=0; |
193 |
cimg_forXYZ(res,x,y,z) |
194 |
{ |
195 |
f=grad(0,x,y,z)*grad(0,x,y,z) + grad(1,x,y,z)*grad(1,x,y,z) + grad(2,x,y,z)*grad(2,x,y,z); |
196 |
res(x,y,z)=1.0/(1.0+f); |
197 |
} |
198 |
return res;
|
199 |
} |
200 |
|
201 |
CImg<float> edge_indicator1(CImg<float> const & img, float gamma) |
202 |
{ |
203 |
CImgList<float> grad;
|
204 |
grad = gradient(img); |
205 |
CImg<float> res(img._width,img._height,img._depth,1,0); |
206 |
float f=0; |
207 |
cimg_forXYZ(res,x,y,z) |
208 |
{ |
209 |
f=grad(0,x,y,z)*grad(0,x,y,z) + grad(1,x,y,z)*grad(1,x,y,z) + grad(2,x,y,z)*grad(2,x,y,z); |
210 |
res(x,y,z)=1.0/(1.0+f/gamma/gamma); |
211 |
} |
212 |
return res;
|
213 |
} |
214 |
|
215 |
//Edge indicator 2 (hessienne, computed without smoothing)
|
216 |
//---------------------------------------------------------------------------
|
217 |
CImg<float> edge_indicator2(CImg<float> const & img) |
218 |
{ |
219 |
CImg<float> res(img._width,img._height,img._depth,1,0); |
220 |
float f=0; |
221 |
cimg_forXYZ(res,x,y,z) |
222 |
{ |
223 |
int xp=x-1; |
224 |
if (x==0){xp=x;} |
225 |
int xn=x+1; |
226 |
if (x==img._width-1){xn=x;} |
227 |
int yp=y-1; |
228 |
if (y==0){yp=y;} |
229 |
int yn=y+1; |
230 |
if (y==img._height-1){yn=y;} |
231 |
int zp=z-1; |
232 |
if (z==0){zp=z;} |
233 |
int zn=z+1; |
234 |
if (z==img._depth-1){zn=z;} |
235 |
|
236 |
CImg<float> hess(3,3,1,1,0); |
237 |
hess(0,0) = img(xp,y,z) + img(xn,y,z) - 2*img(x,y,z); // Hxx |
238 |
hess(1,1) = img(x,yp,z) + img(x,yn,z) - 2*img(x,y,z); // Hyy |
239 |
hess(2,2) = img(x,y,zp) + img(x,y,zn) - 2*img(x,y,z); // Hzz |
240 |
hess(1,0) = hess(0,1) = (img(xp,yp,z) + img(xn,yn,z) - img(xp,yn,z) - img(xn,yp,z))/4; // Hxy = Hyx |
241 |
hess(2,0) = hess(0,2) = (img(xp,y,zp) + img(xn,y,zn) - img(xp,y,zn) - img(xn,y,zp))/4; // Hxz = Hzx |
242 |
hess(2,1) = hess(1,2) = (img(x,yp,zp) + img(x,yn,zn) - img(x,yp,zn) - img(x,yn,zp))/4; // Hyz = Hzy |
243 |
|
244 |
//val : 3 eigen values as an array, decreasing order
|
245 |
//vec : 3 eigen vectors as a 3*3 image
|
246 |
//have to be double or create NaN
|
247 |
CImg<double> val,vec;
|
248 |
hess.symmetric_eigen(val,vec); |
249 |
if (val[2]>0) val[2]=0; |
250 |
val[2]=-val[2]; |
251 |
//res(x,y,z)=1.0/(1.0 +val[2]*(50/3.)); //h=g test4
|
252 |
//res(x,y,z)=1.0/(1.0 +val[2]*val[2]*(50/3.)*(50/3.) );
|
253 |
//res(x,y,z)=1.0/(1.0 +exp(-val[2]));
|
254 |
//res(x,y,z)=exp(-val[2]);
|
255 |
//res(x,y,z)=exp(-val[2]*val[2]);
|
256 |
res(x,y,z)=1.0/(1.0 +val[2]*val[2]); |
257 |
} |
258 |
return res;
|
259 |
} |
260 |
|
261 |
//Edge indicator 2 (hessienne, computed with smoothing)
|
262 |
//---------------------------------------------------------------------------
|
263 |
CImg<float> edge_indicator2s(CImg<float> const & img, float gamma) |
264 |
{ |
265 |
CImg<float> res(img._width,img._height,img._depth,1,0); |
266 |
|
267 |
// make a minimal blur before taking derivatives
|
268 |
CImg<float> imgBlur=img.get_blur(2); |
269 |
|
270 |
float f=0; |
271 |
cimg_forXYZ(res,x,y,z) |
272 |
{ |
273 |
int xp=x-1; |
274 |
if (x==0){xp=x;} |
275 |
int xn=x+1; |
276 |
if (x==img._width-1){xn=x;} |
277 |
int yp=y-1; |
278 |
if (y==0){yp=y;} |
279 |
int yn=y+1; |
280 |
if (y==img._height-1){yn=y;} |
281 |
int zp=z-1; |
282 |
if (z==0){zp=z;} |
283 |
int zn=z+1; |
284 |
if (z==img._depth-1){zn=z;} |
285 |
|
286 |
CImg<float> hess(3,3,1,1,0); |
287 |
hess(0,0) = imgBlur(xp,y,z) + imgBlur(xn,y,z) - 2*imgBlur(x,y,z); // Hxx |
288 |
hess(1,1) = imgBlur(x,yp,z) + imgBlur(x,yn,z) - 2*imgBlur(x,y,z); // Hyy |
289 |
hess(2,2) = imgBlur(x,y,zp) + imgBlur(x,y,zn) - 2*imgBlur(x,y,z); // Hzz |
290 |
hess(1,0) = hess(0,1) = (imgBlur(xp,yp,z) + imgBlur(xn,yn,z) - imgBlur(xp,yn,z) - imgBlur(xn,yp,z))/4; // Hxy = Hyx |
291 |
hess(2,0) = hess(0,2) = (imgBlur(xp,y,zp) + imgBlur(xn,y,zn) - imgBlur(xp,y,zn) - imgBlur(xn,y,zp))/4; // Hxz = Hzx |
292 |
hess(2,1) = hess(1,2) = (imgBlur(x,yp,zp) + imgBlur(x,yn,zn) - imgBlur(x,yp,zn) - imgBlur(x,yn,zp))/4; // Hyz = Hzy |
293 |
|
294 |
//val : 3 eigen values as an array, decreasing order
|
295 |
//vec : 3 eigen vectors as a 3*3 image
|
296 |
//have to be double or create NaN
|
297 |
CImg<double> val,vec;
|
298 |
hess.symmetric_eigen(val,vec); |
299 |
if (val[2]>0) val[2]=0; |
300 |
val[2]=-val[2]; |
301 |
res(x,y,z)=1.0/(1.0 +val[2]*val[2]/gamma/gamma); |
302 |
} |
303 |
return res;
|
304 |
} |
305 |
|
306 |
|
307 |
CImg<float> edge_indicator2(CImg<float> const & img, float gamma) |
308 |
{ |
309 |
CImg<float> res(img._width,img._height,img._depth,1,0); |
310 |
float f=0; |
311 |
cimg_forXYZ(res,x,y,z) |
312 |
{ |
313 |
int xp=x-1; |
314 |
if (x==0){xp=x;} |
315 |
int xn=x+1; |
316 |
if (x==img._width-1){xn=x;} |
317 |
int yp=y-1; |
318 |
if (y==0){yp=y;} |
319 |
int yn=y+1; |
320 |
if (y==img._height-1){yn=y;} |
321 |
int zp=z-1; |
322 |
if (z==0){zp=z;} |
323 |
int zn=z+1; |
324 |
if (z==img._depth-1){zn=z;} |
325 |
|
326 |
CImg<float> hess(3,3,1,1,0); |
327 |
hess(0,0) = img(xp,y,z) + img(xn,y,z) - 2*img(x,y,z); // Hxx |
328 |
hess(1,1) = img(x,yp,z) + img(x,yn,z) - 2*img(x,y,z); // Hyy |
329 |
hess(2,2) = img(x,y,zp) + img(x,y,zn) - 2*img(x,y,z); // Hzz |
330 |
hess(1,0) = hess(0,1) = (img(xp,yp,z) + img(xn,yn,z) - img(xp,yn,z) - img(xn,yp,z))/4; // Hxy = Hyx |
331 |
hess(2,0) = hess(0,2) = (img(xp,y,zp) + img(xn,y,zn) - img(xp,y,zn) - img(xn,y,zp))/4; // Hxz = Hzx |
332 |
hess(2,1) = hess(1,2) = (img(x,yp,zp) + img(x,yn,zn) - img(x,yp,zn) - img(x,yn,zp))/4; // Hyz = Hzy |
333 |
|
334 |
//val : 3 eigen values as an array, decreasing order
|
335 |
//vec : 3 eigen vectors as a 3*3 image
|
336 |
//have to be double or create NaN
|
337 |
CImg<double> val,vec;
|
338 |
hess.symmetric_eigen(val,vec); |
339 |
if (val[2]>0) val[2]=0; |
340 |
//val[2]=-val[2];
|
341 |
res(x,y,z)=1.0/(1.0 +val[2]*val[2]/gamma/gamma); |
342 |
} |
343 |
return res;
|
344 |
} |
345 |
|
346 |
//Edge indicator 3 (image based)
|
347 |
//---------------------------------------------------------------------------
|
348 |
CImg<float> edge_indicator3(CImg<float> const & img) |
349 |
{ |
350 |
CImg<float> res(img._width,img._height,img._depth,1,0); |
351 |
cimg_forXYZ(res,x,y,z) |
352 |
{ |
353 |
res(x,y,z)=1.0/(1.0+img(x,y,z)*img(x,y,z)); |
354 |
} |
355 |
return res;
|
356 |
} |
357 |
|
358 |
CImg<float> edge_indicator3(CImg<float> const & img, float gamma) |
359 |
{ |
360 |
CImg<float> res(img._width,img._height,img._depth,1,0); |
361 |
cimg_forXYZ(res,x,y,z) |
362 |
{ |
363 |
res(x,y,z)=1.0/(1.0+(img(x,y,z)/gamma)*(img(x,y,z)/gamma)); |
364 |
} |
365 |
return res;
|
366 |
} |
367 |
|
368 |
|
369 |
CImg<float> edge_indicator3exp(CImg<float> const & img, float gamma) |
370 |
{ |
371 |
CImg<float> res(img._width,img._height,img._depth,1,0); |
372 |
cimg_forXYZ(res,x,y,z) |
373 |
{ |
374 |
res(x,y,z)=exp(-(img(x,y,z)/gamma)*(img(x,y,z)/gamma)); |
375 |
} |
376 |
return res;
|
377 |
} |
378 |
|
379 |
//Edge image (based on lambda3 of the hessien)
|
380 |
//---------------------------------------------------------------------------
|
381 |
CImg<float> edge_lambda3(CImg<float> const & img) |
382 |
{ |
383 |
CImg<float> res(img._width,img._height,img._depth,1,0); |
384 |
float f=0; |
385 |
cimg_forXYZ(res,x,y,z) |
386 |
{ |
387 |
int xp=x-1; |
388 |
if (x==0){xp=x;} |
389 |
int xn=x+1; |
390 |
if (x==img._width-1){xn=x;} |
391 |
int yp=y-1; |
392 |
if (y==0){yp=y;} |
393 |
int yn=y+1; |
394 |
if (y==img._height-1){yn=y;} |
395 |
int zp=z-1; |
396 |
if (z==0){zp=z;} |
397 |
int zn=z+1; |
398 |
if (z==img._depth-1){zn=z;} |
399 |
|
400 |
CImg<float> hess(3,3,1,1,0); |
401 |
hess(0,0) = img(xp,y,z) + img(xn,y,z) - 2*img(x,y,z); // Hxx |
402 |
hess(1,1) = img(x,yp,z) + img(x,yn,z) - 2*img(x,y,z); // Hyy |
403 |
hess(2,2) = img(x,y,zp) + img(x,y,zn) - 2*img(x,y,z); // Hzz |
404 |
hess(1,0) = hess(0,1) = (img(xp,yp,z) + img(xn,yn,z) - img(xp,yn,z) - img(xn,yp,z))/4; // Hxy = Hyx |
405 |
hess(2,0) = hess(0,2) = (img(xp,y,zp) + img(xn,y,zn) - img(xp,y,zn) - img(xn,y,zp))/4; // Hxz = Hzx |
406 |
hess(2,1) = hess(1,2) = (img(x,yp,zp) + img(x,yn,zn) - img(x,yp,zn) - img(x,yn,zp))/4; // Hyz = Hzy |
407 |
|
408 |
//val : 3 eigen values as an array, decreasing order
|
409 |
//vec : 3 eigen vectors as a 3*3 image
|
410 |
//have to be double or create NaN
|
411 |
CImg<double> val,vec;
|
412 |
hess.symmetric_eigen(val,vec); |
413 |
if (val[2]>0) val[2]=0; |
414 |
res(x,y,z)=-val[2];
|
415 |
} |
416 |
return res;
|
417 |
} |
418 |
|
419 |
|
420 |
//Wall indicator
|
421 |
//---------------------------------------------------------------------------
|
422 |
CImg<float> wall_indicator(CImg<float> const & img) |
423 |
{ |
424 |
CImg<float> res(img._width,img._height,img._depth,1,0); |
425 |
cimg_forXYZ(res,x,y,z) |
426 |
{ |
427 |
res(x,y,z)=1.0/(1.0+(img(x,y,z)*img(x,y,z))); |
428 |
} |
429 |
return res;
|
430 |
} |
431 |
|
432 |
//Dirac function
|
433 |
//-------------------------------------------------------------------------
|
434 |
CImg<float> Dirac(CImg<float> const & img, float sigma) |
435 |
{ |
436 |
CImg<float> fImg(img._width,img._height,img._depth,1,0); |
437 |
float f=0; |
438 |
cimg_forXYZ(img,x,y,z) |
439 |
{ |
440 |
if(abs(img(x,y,z))<=sigma)
|
441 |
{ |
442 |
f=(1.0/(2*sigma))*(1+cos(M_PI*img(x,y,z)/sigma)); |
443 |
} |
444 |
else {f=0;} |
445 |
fImg(x,y,z)=f; |
446 |
} |
447 |
return fImg;
|
448 |
} |
449 |
|
450 |
//Normal vector
|
451 |
//------------------------------------------------------------------------
|
452 |
CImgList<float> normal_vector(CImg<float> const & img) |
453 |
{ |
454 |
CImgList<float> normal_vector(3,img._width,img._height,img._depth,1,0); |
455 |
|
456 |
CImg_3x3x3(I,float);
|
457 |
cimg_for3x3x3(img,x,y,z,0,I,float) |
458 |
{ |
459 |
float nx = (Incc-Ipcc)/2.0; |
460 |
float ny = (Icnc-Icpc)/2.0; |
461 |
float nz = (Iccn-Iccp)/2.0; |
462 |
//border
|
463 |
if((x==0)or(y==0)or(z==0)) |
464 |
{nx=ny=nz=0;}
|
465 |
if((x==img.width()-1)or(y==img.height()-1)or(z==img.depth()-1)) |
466 |
{nx=ny=nz=0;}
|
467 |
|
468 |
float norm=1; |
469 |
if((nx!=0)or(ny!=0)or(nz!=0)) |
470 |
{norm = sqrt(nx*nx+ny*ny+nz*nz);} |
471 |
|
472 |
normal_vector(0,x,y,z)=nx/norm;
|
473 |
normal_vector(1,x,y,z)=ny/norm;
|
474 |
normal_vector(2,x,y,z)=nz/norm;
|
475 |
} |
476 |
return normal_vector;
|
477 |
} |
478 |
|
479 |
|
480 |
//Curvature
|
481 |
//------------------------------------------------------------------------
|
482 |
CImg<float> curvature2(CImgList<float> const & N) |
483 |
{ |
484 |
CImg<float> K(N[0]._width,N[0]._height,N[0]._depth,1,0); |
485 |
cimg_forXYZ(N[0],x,y,z)
|
486 |
{ |
487 |
float kx=0; |
488 |
float ky=0; |
489 |
float kz=0; |
490 |
if(x==0) |
491 |
{kx=N[0](x+1,y,z)-N[0](x,y,z);} |
492 |
else if(x==N[0]._width-1) |
493 |
{kx=N[0](x,y,z)-N[0](x-1,y,z);} |
494 |
else
|
495 |
{kx=(N[0](x+1,y,z)-N[0](x-1,y,z))/2.0;} |
496 |
|
497 |
if(y==0) |
498 |
{ky=N[1](x,y+1,z)-N[1](x,y,z);} |
499 |
else if(y==N[1]._height-1) |
500 |
{ky=N[1](x,y,z)-N[1](x,y-1,z);} |
501 |
else
|
502 |
{ky=(N[1](x,y+1,z)-N[1](x,y-1,z))/2.0;} |
503 |
|
504 |
if(z==0) |
505 |
{kz=N[2](x,y,z+1)-N[2](x,y,z);} |
506 |
else if(z==N[2]._depth-1) |
507 |
{kz=N[2](x,y,z)-N[2](x,y,z-1);} |
508 |
else
|
509 |
{kz=(N[2](x,y,z+1)-N[2](x,y,z-1))/2.0;} |
510 |
|
511 |
K(x,y,z)=kx+ky+kz; |
512 |
} |
513 |
return K;
|
514 |
} |
515 |
|
516 |
// Compute image laplacian
|
517 |
//--------------------------------------------------------------------
|
518 |
CImg<float> laplacian(CImg<float> const & img) |
519 |
{ |
520 |
CImg<float> laplacian(img._width,img._height,img._depth,1,0); |
521 |
CImg_3x3x3(I,float);
|
522 |
cimg_for3x3x3(img,x,y,z,0,I,float) |
523 |
{ |
524 |
laplacian(x,y,z) =Incc+Ipcc+Icnc+Icpc+Iccn+Iccp - 6*Iccc;
|
525 |
} |
526 |
return laplacian;
|
527 |
} |
528 |
|
529 |
//Evolution AK2 contour
|
530 |
//-------------------------------------------------------------------------
|
531 |
CImg<float> evolution_AK2_contour(CImg<float> u, CImg<float> const & g, CImgList<float> const & gg, CImg<float> const & h, int lam, float mu, float alf, float beta, float epsilon, int dt) |
532 |
{ |
533 |
CImg<float> diracU=Dirac(u,epsilon);
|
534 |
CImgList<float> N=normal_vector(u);
|
535 |
CImg<float> K=curvature2(N);
|
536 |
CImg<float> L=laplacian(u);
|
537 |
float term=0; |
538 |
|
539 |
cimg_forXYZ(u,x,y,z) |
540 |
{ |
541 |
term=0;
|
542 |
if (diracU(x,y,z)!=0) |
543 |
{ |
544 |
//weighted length term
|
545 |
if(lam!=0) |
546 |
{term=( gg(0,x,y,z)*N(0,x,y,z) + gg(1,x,y,z)*N(1,x,y,z) + gg(2,x,y,z)*N(2,x,y,z) + (g(x,y,z)*K(x,y,z))) *lam;} |
547 |
//length term
|
548 |
if(beta!=0) |
549 |
{term=term + K(x,y,z)*beta;} |
550 |
//weighted area term
|
551 |
if(alf!=0) |
552 |
{term=term + h(x,y,z)*alf;} |
553 |
//regularization
|
554 |
term=term*diracU(x,y,z); |
555 |
//penalizing term
|
556 |
term=term + (L(x,y,z)-K(x,y,z))*mu; |
557 |
} |
558 |
else
|
559 |
{ |
560 |
//penalizing term
|
561 |
term=(L(x,y,z)-K(x,y,z))*mu; |
562 |
} |
563 |
|
564 |
u(x,y,z)=u(x,y,z) + term*dt; |
565 |
} |
566 |
return u;
|
567 |
} |
568 |
|
569 |
//Evolution AK2 contour cells
|
570 |
//-------------------------------------------------------------------------
|
571 |
CImg<float> evolution_AK2_contour_cells(CImg<float> u, CImg<float> const & g, CImgList<float> const & gg, CImg<float> const & h, int lam, float mu, float alf, int beta, float epsilon, int dt, vector<int> min_list) |
572 |
{ |
573 |
CImg<float> diracU=Dirac(u,epsilon);
|
574 |
CImgList<float> N=normal_vector(u);
|
575 |
CImg<float> K=curvature2(N);
|
576 |
CImg<float> L=laplacian(u);
|
577 |
float term=0; |
578 |
int xmax=u._width;
|
579 |
int ymax=u._height;
|
580 |
int zmax=u._depth;
|
581 |
int c0=-4; |
582 |
|
583 |
cimg_forXYZ(u,x,y,z) |
584 |
{ |
585 |
int xb=x+min_list[0]; |
586 |
int yb=y+min_list[1]; |
587 |
int zb=z+min_list[2]; |
588 |
term=0;
|
589 |
if (diracU(x,y,z)!=0) |
590 |
{ |
591 |
//weighted length term
|
592 |
if(lam!=0) |
593 |
{term=( gg(0,xb,yb,zb)*N(0,x,y,z) + gg(1,xb,yb,zb)*N(1,x,y,z) + gg(2,xb,yb,zb)*N(2,x,y,z) + (g(xb,yb,zb)*K(x,y,z))) *lam;} |
594 |
//length term
|
595 |
if(beta!=0) |
596 |
{term=term + K(x,y,z)*beta;} |
597 |
//weighted area term
|
598 |
if(alf!=0) |
599 |
{term=term + h(xb,yb,zb)*alf;} |
600 |
//regularization
|
601 |
term=term*diracU(x,y,z); |
602 |
//penalizing term
|
603 |
term=term + (L(x,y,z)-K(x,y,z))*mu; |
604 |
} |
605 |
else
|
606 |
{ |
607 |
//penalizing term
|
608 |
term=(L(x,y,z)-K(x,y,z))*mu; |
609 |
} |
610 |
// computing the evolution
|
611 |
u(x,y,z)=u(x,y,z) + term*dt; |
612 |
// box boundary regularisation
|
613 |
if ((x==0) or (x==xmax) or (x==1) or (x==xmax-1) or(y==0) or (y==ymax)or(y==1) or (y==ymax-1) or (z==0) or (z==zmax)or (z==1) or (z==zmax-1)) |
614 |
{u(x,y,z)=c0;} |
615 |
} |
616 |
return u;
|
617 |
} |