|
a |
|
b/Thoracic Organs Segmentation code/TwoPhaseLevel Sets/Combination.asv |
|
|
1 |
/*///////////////////////////////////////////////////////////////////////////////////// |
|
|
2 |
2 phase level set method |
|
|
3 |
0-input image |
|
|
4 |
1-initial phi1 |
|
|
5 |
2-dt=>time-step of iteration |
|
|
6 |
3-kappa =>coefficient of the weighted length term L(phi1) |
|
|
7 |
4-lambda1 =>coefficient of insice C term |
|
|
8 |
5-lambda2 =>coefficient of outside C term |
|
|
9 |
6-lambda=>coefficient of the weighted length term L(phi2) |
|
|
10 |
7-mu => coefficient of the internal (penalizing) energy term P(phi1),P(phi2) |
|
|
11 |
8-v=>coefficient of the weighted area term A(phi2) |
|
|
12 |
9-iterations |
|
|
13 |
10-g=>edge indicator |
|
|
14 |
/*///////////////////////////////////////////////////////////////////////////////////// |
|
|
15 |
#include <mex.h> |
|
|
16 |
#include <mat.h> |
|
|
17 |
#include <matrix.h> |
|
|
18 |
|
|
|
19 |
#define cimg_plugin "cimgmatlab.h" |
|
|
20 |
|
|
|
21 |
#include "CImg.h" |
|
|
22 |
#include <iostream> |
|
|
23 |
#include <string> |
|
|
24 |
#include <math.h> |
|
|
25 |
|
|
|
26 |
using namespace cimg_library; |
|
|
27 |
using namespace std; |
|
|
28 |
|
|
|
29 |
//globa values |
|
|
30 |
const double epsilon=0.8; // the papamater smooth Dirac function (default value 1.5); |
|
|
31 |
const float precision=0.009f;//precision of the error estimation |
|
|
32 |
|
|
|
33 |
//functions |
|
|
34 |
CImg<double> DiracU( CImg<double>& u0) ; |
|
|
35 |
CImg<double> Heaviside(CImg<double>& u0); |
|
|
36 |
CImg<double> ExtractContour(CImg<double> LevelSet); |
|
|
37 |
CImg<unsigned char> get_level0(const CImg<>& img); |
|
|
38 |
CImg<unsigned char> InitialLevelSet(CImg<double>&Img); |
|
|
39 |
CImg<double> DiracF(CImg<double>& u1,CImg<double>& u2); |
|
|
40 |
CImg<double>Heaviside1(CImg<double>& u0); |
|
|
41 |
|
|
|
42 |
//----------------- |
|
|
43 |
// Main-MexFunction |
|
|
44 |
//----------------- |
|
|
45 |
|
|
|
46 |
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { |
|
|
47 |
if (nrhs < 13) mexErrMsgTxt("No enough input arguments."); |
|
|
48 |
if (nrhs >13) mexErrMsgTxt("Too many input arguments."); |
|
|
49 |
if (nrhs == 13){ |
|
|
50 |
|
|
|
51 |
//Input Parameters ( inputs) |
|
|
52 |
CImg<double> Img(prhs[0],true); //input image |
|
|
53 |
CImg<double> phi1(prhs[1],true); //Rib cage approximation |
|
|
54 |
CImg<double> phi2(prhs[2],true); |
|
|
55 |
CImg<int>VolumeMask(prhs[3],true); |
|
|
56 |
const double dt= mxGetScalar( prhs[4]); //time-step of iteration |
|
|
57 |
const double kappa = mxGetScalar(prhs[5]); //coefficient of the weighted length term L(phi1) |
|
|
58 |
const double lambda1 = mxGetScalar(prhs[6]);//coefficient of insice C term |
|
|
59 |
const double lambda2 = mxGetScalar(prhs[7]);//coefficient of outside C term |
|
|
60 |
const double lambda = mxGetScalar(prhs[8]); //coefficient of the weighted length term L(phi2) |
|
|
61 |
const double mu = mxGetScalar(prhs[9]); // coefficient of the internal (penalizing) energy term P(u) |
|
|
62 |
const double v = mxGetScalar(prhs[10]); //coefficient of the weighted area term A(u) |
|
|
63 |
const unsigned int nb_iter = mxGetScalar(prhs[11]); |
|
|
64 |
CImg<double> g(prhs[12],true); |
|
|
65 |
////////////////////////////////////////////////////////////////////////////////////////////////// |
|
|
66 |
|
|
|
67 |
unsigned char col1[2]={0,255}, col2[2]={200,255}, col3[2]={255,255};//colors filling |
|
|
68 |
CImg<double>f(phi1.dimx(),phi1.dimy()); |
|
|
69 |
cimg_forXY(phi1,x,y) {if(phi1(x,y)==1) phi1(x,y)=200;} |
|
|
70 |
phi1.draw_fill(0,0,col3); |
|
|
71 |
cimg_forXY(phi2,x,y) {if(phi2(x,y)==1) phi2(x,y)=200;} |
|
|
72 |
phi2.draw_fill(0,0,col3); |
|
|
73 |
|
|
|
74 |
cimg_forXY(phi1,x,y){ |
|
|
75 |
if(phi1(x,y)==200) f(x,y)=0; |
|
|
76 |
if(phi1(x,y)==0) f(x,y)=-5; |
|
|
77 |
if(phi1(x,y)==255) f(x,y)=5; |
|
|
78 |
} |
|
|
79 |
cimg_forXY(phi1,x,y){ |
|
|
80 |
phi1(x,y)=floor(phi1(x,y)-phi2(x,y)); |
|
|
81 |
if(phi1(x,y)<0) phi1(x,y)=-1; |
|
|
82 |
if(phi1(x,y)==0) phi1(x,y)=1; |
|
|
83 |
if(phi1(x,y)==-55 || phi1(x,y)==200) phi1(x,y)=0; |
|
|
84 |
|
|
|
85 |
} |
|
|
86 |
|
|
|
87 |
|
|
|
88 |
|
|
|
89 |
cimg_forXY(phi2,x,y){ |
|
|
90 |
if(phi2(x,y)==200) phi2(x,y)=0; |
|
|
91 |
if(phi2(x,y)==0) phi2(x,y)=-5; |
|
|
92 |
if(phi2(x,y)==255) phi2(x,y)=5; |
|
|
93 |
} |
|
|
94 |
|
|
|
95 |
CImg<double>HeavisideF10= Heaviside1(f); |
|
|
96 |
|
|
|
97 |
|
|
|
98 |
// cimg_forXY(phi1,x,y){ phi1(x,y)=phi1(x,y)*phi2(x,y);} |
|
|
99 |
// if (phi1(x,y)*phi2(x,y)>0) phi1(x,y)=-5; |
|
|
100 |
// if (phi1(x,y)*phi2(x,y)==0)phi1(x,y)=0; |
|
|
101 |
//if (phi1(x,y)*phi2(x,y)<0)phi1(x,y)=5; |
|
|
102 |
//} |
|
|
103 |
|
|
|
104 |
|
|
|
105 |
// phi1.normalize(-1,1); |
|
|
106 |
// CImgDisplay disp2(phi2,"Image",0); |
|
|
107 |
phi1.distance_hamilton(5);//distance function |
|
|
108 |
// phi2.distance_hamilton(30);//distance function |
|
|
109 |
// CImgDisplay disp1(phi1,"Image",0); |
|
|
110 |
|
|
|
111 |
//Initializations |
|
|
112 |
CImg<double> dphi1(Img.dimx(),Img.dimy(),2); //derivatives of phi |
|
|
113 |
CImg<double> veloc1(phi1.dimx(),phi1.dimy()); |
|
|
114 |
CImg<double> N_dphi1(phi1.dimx(),phi1.dimy(),2); //Normalize gradient of level set function phi1 |
|
|
115 |
CImg<double> veloc2(phi2.dimx(),phi2.dimy()); |
|
|
116 |
CImg<double> N_dphi2(phi2.dimx(),phi2.dimy(),2); //Normalize gradient of level set function phi2 |
|
|
117 |
|
|
|
118 |
|
|
|
119 |
// const unsigned int nb_iter = 0;//Number of iterations |
|
|
120 |
double c1=0, c2=0, Averagec1=0, Averagec2=0; |
|
|
121 |
|
|
|
122 |
//Edge indicator |
|
|
123 |
CImg<double>dg(g.dimx(),g.dimy(),1,2); |
|
|
124 |
cimg_for3XY(g,x,y){ |
|
|
125 |
dg(x,y,0)=0.5*(g(_n1x,y)-g(_p1x,y)), |
|
|
126 |
dg(x,y,1)=0.5*(g(x,_n1y)-g(x,_p1y)); |
|
|
127 |
} |
|
|
128 |
|
|
|
129 |
|
|
|
130 |
// CImg<double>HeavisideF10= Heaviside1(phi1); |
|
|
131 |
double E1=1e20f,E2=1e20f;//Initial energy |
|
|
132 |
double Eold1 = 0, Eold2=0; |
|
|
133 |
veloc1.fill(0); |
|
|
134 |
veloc2.fill(0); |
|
|
135 |
|
|
|
136 |
////////////////////////////////////////////////////////////////////////////////////////////// |
|
|
137 |
//Main PDEs |
|
|
138 |
for (unsigned int iter=0; iter<=nb_iter; iter++) { |
|
|
139 |
|
|
|
140 |
|
|
|
141 |
CImg<double> diracF1=DiracU(phi1); |
|
|
142 |
CImg<double>HeavisideF1=Heaviside(phi1); |
|
|
143 |
CImg<double> diracF2=DiracU(phi2); |
|
|
144 |
CImg<double>HeavisideF2=Heaviside1(phi2); |
|
|
145 |
// CImg<double> dirac = DiracF(phi1,phi2); |
|
|
146 |
cimg_for3XY(phi1,x,y)if (VolumeMask(x,y)==0){ |
|
|
147 |
|
|
|
148 |
//PHI1 |
|
|
149 |
const double |
|
|
150 |
phix1=0.5*(phi1(_n1x,y)-phi1(_p1x,y)), |
|
|
151 |
phiy1=0.5*(phi1(x,_n1y)-phi1(x,_p1y)); //derivatives of phi(central) |
|
|
152 |
|
|
|
153 |
const double Mag_dphi1= sqrt(pow(phix1,2)+ pow(phiy1,2)+1e-10); //magnitude of grad(phi) |
|
|
154 |
N_dphi1(x,y,0)=phix1/Mag_dphi1; |
|
|
155 |
N_dphi1(x,y,1)=phiy1/Mag_dphi1; |
|
|
156 |
|
|
|
157 |
c1+=HeavisideF1(x,y)* Img(x,y); |
|
|
158 |
c2+=(1-HeavisideF1(x,y))*Img(x,y); |
|
|
159 |
Averagec1+=HeavisideF1(x,y); |
|
|
160 |
Averagec2+=HeavisideF1(x,y); |
|
|
161 |
///////////////////////////////////////////////////////////////////////////////////// |
|
|
162 |
//PHI2 |
|
|
163 |
const double |
|
|
164 |
phix2=0.5*(phi2(_n1x,y)-phi2(_p1x,y)), |
|
|
165 |
phiy2=0.5*(phi2(x,_n1y)-phi2(x,_p1y)); //derivatives of phi2 |
|
|
166 |
|
|
|
167 |
const double Mag_dphi2= sqrt(pow(phix2,2)+ pow(phiy2,2)+1e-10); //magnitude of grad(phi2) |
|
|
168 |
N_dphi2(x,y,0)=phix2/Mag_dphi2; |
|
|
169 |
N_dphi2(x,y,1)=phiy2/Mag_dphi2; |
|
|
170 |
} |
|
|
171 |
|
|
|
172 |
c1/=(Averagec1+1e-5); |
|
|
173 |
c2/=(Averagec2+1e-5); |
|
|
174 |
|
|
|
175 |
|
|
|
176 |
|
|
|
177 |
cimg_for3XY(Img,x,y)if (VolumeMask(x,y)==0){ |
|
|
178 |
|
|
|
179 |
//Chan-Vese level set function |
|
|
180 |
const double |
|
|
181 |
dN_phix1=0.5*(N_dphi1(_n1x,y,0)-N_dphi1(_p1x,y,0)), |
|
|
182 |
dN_phiy1=0.5*(N_dphi1(x,_n1y,1)-N_dphi1(x,_p1y,1)), |
|
|
183 |
Laplac_phi1=(phi1(_n1x,y) + phi1(_p1x,y) + phi1(x,_n1y) + phi1(x,_p1y))-4*phi1(x,y), |
|
|
184 |
K1=dN_phix1+dN_phiy1; |
|
|
185 |
const double |
|
|
186 |
phixx1=(phi1(_n1x,y)+phi1(_p1x,y)-2*phi1(x,y)), |
|
|
187 |
phiyy1=(phi1(x,_n1y)+phi1(x,_p1y)-2*phi1(x,y)), |
|
|
188 |
phix1 =0.5*(phi1(_n1x,y)-phi1(_p1x,y)), |
|
|
189 |
phiy1 =0.5*(phi1(x,_n1y)-phi1(x,_p1y)), |
|
|
190 |
Mag_dphi1 = sqrt(pow(phix1,2)+ pow(phiy1,2)+1e-10); |
|
|
191 |
|
|
|
192 |
veloc1(x,y)=kappa*diracF1(x,y)*(dg(x,y,0)* N_dphi1(x,y,0) +dg(x,y,1)* N_dphi1(x,y,1)+g(x,y)*K1)+mu*(Laplac_phi1-K1)-lambda1* diracF1(x,y)* pow(Img(x,y)-c1,2)+lambda2*diracF1(x,y)*pow(Img(x,y)-c2,2);//+35*diracF1(x,y);//0.01*diracF1(x,y)*(1-HeavisideF1(x,y))*pow(1-HeavisideF2(x,y),2);//-0.8*diracF2(x,y)*(HeavisideF1(x,y)-1); |
|
|
193 |
// veloc1(x,y)=(1-HeavisideF2(x,y))*veloc1(x,y); |
|
|
194 |
E1+=lambda1*HeavisideF1(x,y)*pow(Img(x,y)-c1,2);//+lambda2*(1-HeavisideF1(x,y))*pow(Img(x,y)-c2,2); |
|
|
195 |
|
|
|
196 |
//front propagation level set function |
|
|
197 |
const double |
|
|
198 |
dN_phix2=0.5*(N_dphi2(_n1x,y,0)-N_dphi2(_p1x,y,0)), |
|
|
199 |
dN_phiy2=0.5*(N_dphi2(x,_n1y,1)-N_dphi2(x,_p1y,1)), |
|
|
200 |
Laplac_phi2=(phi2(_n1x,y) + phi2(_p1x,y) + phi2(x,_n1y) + phi2(x,_p1y))-4*phi2(x,y), |
|
|
201 |
K2=dN_phix2+dN_phiy2; |
|
|
202 |
const double |
|
|
203 |
phixx2=(phi2(_n1x,y)+phi2(_p1x,y)-2*phi2(x,y)), |
|
|
204 |
phiyy2=(phi2(x,_n1y)+phi2(x,_p1y)-2*phi2(x,y)), |
|
|
205 |
phix2 =0.5*(phi2(_n1x,y)-phi2(_p1x,y)), |
|
|
206 |
phiy2 =0.5*(phi2(x,_n1y)-phi2(x,_p1y)),//derivatives of u |
|
|
207 |
Mag_dphi2 = sqrt(pow(phix2,2)+ pow(phiy2,2)+1e-10); //magnitude of grad(u) |
|
|
208 |
//if (HeavisideF10(x,y)-HeavisideF2(x,y)>0 && HeavisideF1(x,y)>0){ |
|
|
209 |
veloc2(x,y)=lambda* diracF2(x,y)*( dg(x,y,0)* N_dphi2(x,y,0) +dg(x,y,1)* N_dphi2(x,y,1) + g(x,y)*K2)+mu*(Laplac_phi2-K2)+v*g(x,y)*diracF2(x,y); |
|
|
210 |
//} |
|
|
211 |
// else veloc2(x,y)=0; |
|
|
212 |
veloc2(x,y)=veloc2(x,y)*HeavisideF10(x,y)*HeavisideF1(x,y); |
|
|
213 |
//Energy estimation(functionals) |
|
|
214 |
E2+=v*HeavisideF2(x,y)*g(x,y); |
|
|
215 |
// E2+=lambda*g(x,y)*diracF2(x,y)* Mag_dphi2+1/2*mu*pow( Mag_dphi2-1,2)+v*HeavisideF2(x,y)*g(x,y); |
|
|
216 |
|
|
|
217 |
|
|
|
218 |
} |
|
|
219 |
|
|
|
220 |
phi1+=dt*veloc1; |
|
|
221 |
|
|
|
222 |
phi2+=dt*veloc2; |
|
|
223 |
|
|
|
224 |
if ((abs(Eold1-E1)<0.001f) && (abs(Eold2-E2)<0.001f)) break; |
|
|
225 |
|
|
|
226 |
/* if (!(iter%8)) { |
|
|
227 |
get_level0(phi1).resize(disp1.dimx(),disp1.dimy()).draw_grid(20,20,0,0,false,false,col3,0.4f,0xCCCCCCCC,0xCCCCCCCC). |
|
|
228 |
draw_text(5,5,"Iteration %d",col3,0,1,11,iter).display(disp1); |
|
|
229 |
get_level0(phi2).resize(disp2.dimx(),disp2.dimy()).draw_grid(20,20,0,0,false,false,col3,0.4f,0xCCCCCCCC,0xCCCCCCCC). |
|
|
230 |
draw_text(5,5,"Iteration %d",col3,0,1,11,iter).display(disp2); |
|
|
231 |
}*/ |
|
|
232 |
//printf ("Energy functional E1: %d \n",E1); |
|
|
233 |
//printf ("Energy functional E2: %d \n",E2); |
|
|
234 |
// printf("E1-Eold1=%d\n",abs(Eold1-E1)); |
|
|
235 |
// printf("E2-Eold2=%d\n",abs(E2-Eold2)); |
|
|
236 |
// if (!(iter%550)) phi2.distance_hamilton(1,3);// phi1.distance_hamilton(1,10);; |
|
|
237 |
c1=0,Averagec1=0; |
|
|
238 |
c2=0,Averagec2=0; |
|
|
239 |
Eold1 = E1, Eold2=E2; |
|
|
240 |
E1=0;E2=0; |
|
|
241 |
|
|
|
242 |
} |
|
|
243 |
// phi2.distance_hamilton(1,10), phi1.distance_hamilton(1,10); |
|
|
244 |
//CImg<double>Contour1 = ExtractContour(phi1); |
|
|
245 |
//CImg<double>Contour2 = ExtractContour(phi2); |
|
|
246 |
// phi2.distance_hamilton(1,3); |
|
|
247 |
// phi1.distance_hamilton(1,3); |
|
|
248 |
|
|
|
249 |
plhs[0]= phi1.toMatlab(); |
|
|
250 |
plhs[1]= phi2.toMatlab(); |
|
|
251 |
|
|
|
252 |
|
|
|
253 |
|
|
|
254 |
} |
|
|
255 |
|
|
|
256 |
return; |
|
|
257 |
|
|
|
258 |
} |
|
|
259 |
|
|
|
260 |
|
|
|
261 |
|
|
|
262 |
|
|
|
263 |
CImg<double> DiracU(CImg<double>& u0) { |
|
|
264 |
|
|
|
265 |
CImg<double> u(u0.dimx(),u0.dimy()); |
|
|
266 |
u.fill(0); |
|
|
267 |
cimg_forXY(u0,x,y) { |
|
|
268 |
|
|
|
269 |
if (u0(x,y)<=epsilon && u0(x,y)>=-epsilon){ |
|
|
270 |
u(x,y)=(double)1/(2*epsilon)*(1+cos(3.14*u0(x,y)/epsilon)); |
|
|
271 |
} |
|
|
272 |
|
|
|
273 |
} |
|
|
274 |
return u; |
|
|
275 |
} |
|
|
276 |
|
|
|
277 |
CImg<double> Heaviside(CImg<double>& u0) { |
|
|
278 |
|
|
|
279 |
CImg<double> u(u0.dimx(),u0.dimy()); |
|
|
280 |
u.fill(0); |
|
|
281 |
/*cimg_forXY(u0,x,y){ |
|
|
282 |
u(x,y)=1/2*(1+2/3.14*atan(u(x,y)/epsilon)); |
|
|
283 |
}*/ |
|
|
284 |
cimg_forXY(u0,x,y) { |
|
|
285 |
|
|
|
286 |
if (u0(x,y)>=-epsilon && u0(x,y)<=epsilon){ |
|
|
287 |
u(x,y)=(double) 1/2+u0(x,y)/(2*epsilon)+1/(2*3.14)*sin(3.14*u0(x,y)/epsilon); |
|
|
288 |
} |
|
|
289 |
if (u0(x,y)>epsilon) u(x,y)=1; |
|
|
290 |
|
|
|
291 |
} |
|
|
292 |
return u; |
|
|
293 |
} |
|
|
294 |
|
|
|
295 |
|
|
|
296 |
/*******************************************************************************/ |
|
|
297 |
CImg<double> ExtractContour(CImg<double> LevelSet) |
|
|
298 |
{ |
|
|
299 |
CImg<double> Contour(LevelSet.dimx(),LevelSet.dimy(),1,1); |
|
|
300 |
Contour.fill(0); |
|
|
301 |
|
|
|
302 |
CImg_3x3(I,double); |
|
|
303 |
cimg_for3x3(LevelSet,x,y,0,0,I) |
|
|
304 |
{ |
|
|
305 |
if(Icc*Icp<=0 || Icc*Icn<=0 || Icc*Ipc<=0 || Icc*Inc<=0) |
|
|
306 |
Contour(x,y) = 1; |
|
|
307 |
} |
|
|
308 |
return Contour; |
|
|
309 |
} |
|
|
310 |
CImg<double> Heaviside1(CImg<double>& u0) { |
|
|
311 |
|
|
|
312 |
CImg<double> u(u0.dimx(),u0.dimy()); |
|
|
313 |
u.fill(0); |
|
|
314 |
cimg_forXY(u0,x,y) { |
|
|
315 |
|
|
|
316 |
if (u0(x,y)<=epsilon && u0(x,y)>=-epsilon){ |
|
|
317 |
u(x,y)=(double) 1/2-u0(x,y)/(2*epsilon)+1/(2*3.14)*sin(-3.14*u0(x,y)/epsilon); |
|
|
318 |
} |
|
|
319 |
if (u0(x,y)<-epsilon) u(x,y)=1; |
|
|
320 |
|
|
|
321 |
} |
|
|
322 |
return u; |
|
|
323 |
} |
|
|
324 |
////////////////////////////////////////////////////////////////////////////////////////////// |
|
|
325 |
// get_level0() : Retrieve the curve corresponding to the zero level set of the distance function |
|
|
326 |
//------------- |
|
|
327 |
CImg<unsigned char> get_level0(const CImg<>& img) { |
|
|
328 |
CImg<unsigned char> dest(img); |
|
|
329 |
CImg_2x2(I,float); Inn = 0; |
|
|
330 |
cimg_for2x2(img,x,y,0,0,I) if (Icc*Inc<0 || Icc*Icn<0) dest(x,y) = 255; else dest(x,y) = Icc<0?100:0; |
|
|
331 |
return dest; |
|
|
332 |
} |
|
|
333 |
|
|
|
334 |
///////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
|
335 |
// // Create a user-defined closed curve (Initial level set fuction) |
|
|
336 |
CImg<unsigned char> InitialLevelSet(CImg<double>&Img){ |
|
|
337 |
CImg<unsigned char> curve(Img.dimx(),Img.dimy(),Img.dimz(),2,0); |
|
|
338 |
unsigned char col1[2]={0,255}, col2[2]={200,255}, col3[2]={255,255};//colors |
|
|
339 |
curve.draw_grid(20,20,0,0,false,false,col1,0.4f,0xCCCCCCCC,0xCCCCCCCC). |
|
|
340 |
draw_text(5,5,"Please draw your curve\nin the middle of this window\n(Use your mouse)\n-heart initial curve",col1); |
|
|
341 |
CImgDisplay disp(curve,"Image",0); |
|
|
342 |
CImg<double> tempImg(Img); |
|
|
343 |
|
|
|
344 |
int xo=-1,yo=-1,x0=-1,y0=-1,x1=-1,y1=-1; |
|
|
345 |
while (!disp.is_closed && (x0<0 || disp.button)) { |
|
|
346 |
if (disp.button && disp.mouse_x>=0 && disp.mouse_y>=0) { |
|
|
347 |
if (x0<0) { xo = x0 = disp.mouse_x; yo = y0 = disp.mouse_y; } else { |
|
|
348 |
x1 = disp.mouse_x; y1 = disp.mouse_y; |
|
|
349 |
curve.draw_line(x0,y0,x1,y1,col2);//.display(disp); |
|
|
350 |
|
|
|
351 |
tempImg.draw_point(x1,y1,col1).display(disp); |
|
|
352 |
x0 = x1; y0 = y1; |
|
|
353 |
} |
|
|
354 |
} |
|
|
355 |
disp.wait(); |
|
|
356 |
if (disp.is_resized) disp.resize(disp); |
|
|
357 |
} |
|
|
358 |
curve.draw_line(x1,y1,xo,yo,col2).channel(0).draw_fill(0,0,col3); |
|
|
359 |
return curve; |
|
|
360 |
} |
|
|
361 |
|
|
|
362 |
|
|
|
363 |
////////////////////////////////////////////////////////////////////////////////////////////// |
|
|
364 |
|
|
|
365 |
|
|
|
366 |
|
|
|
367 |
|
|
|
368 |
|
|
|
369 |
|
|
|
370 |
|
|
|
371 |
|
|
|
372 |
|
|
|
373 |
|
|
|
374 |
|