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