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