29 #define ROUNDCLAMP(x) ((x < 0) ? 0 : \
30 ((x > 1) ? 255 : (uint8_t)floor(255.0*(x) + 0.5)))
34 #define ATTRIBUTE_UNUSED __attribute__((unused))
36 #define ATTRIBUTE_UNUSED
70 static void PrintHelpMessage()
72 puts(
"chanvese, P. Getreuer 2011-2012\n"
73 "Chan-Vese segmentation IPOL demo\n\n"
74 "Usage: chanvese [param:value ...] input animation final \n\n"
75 "where \"input\" and \"final\" are "
77 "and \"animation\" is a GIF file.\n");
79 puts(
" mu:<number> length penalty (default 0.25)");
80 puts(
" nu:<number> area penalty (default 0.0)");
81 puts(
" lambda1:<number> fit weight inside the cuve (default 1.0)");
82 puts(
" lambda2:<number> fit weight outside the curve (default 1.0)");
83 puts(
" phi0:<file> read initial level set from an image or text file");
84 puts(
" tol:<number> convergence tolerance (default 1e-3)");
85 puts(
" maxiter:<number> maximum number of iterations (default 500)");
86 puts(
" dt:<number> time step (default 0.5)\n");
87 puts(
" iterperframe:<number> iterations per frame (default 10)\n");
88 #ifdef LIBJPEG_SUPPORT
89 puts(
" jpegquality:<number> Quality for saving JPEG images (0 to 100)\n");
93 " chanvese tol:1e-5 mu:0.5 input.png animation.gif final.png\n");
95 " chanvese tol:1e-5 mu:0.5 input.bmp animation.gif final.bmp\n");
100 static int PlotFun(
int State,
int Iter, num Delta,
101 const num *c1,
const num *c2,
const num *Phi,
102 int Width,
int Height,
int NumChannels,
void *ParamPtr);
103 static int ParseParam(
programparams *Param,
int argc,
const char *argv[]);
104 static int PhiRescale(
image *Phi);
107 int WriteBinary(
image Phi,
const char *File)
109 unsigned char *Temp = NULL;
113 if(!(Temp = (
unsigned char *)malloc(Phi.
Width*Phi.
Height)))
116 for(i = 0; i < NumPixels; i++)
117 Temp[i] = (Phi.
Data[i] >= 0) ? 255 : 0;
120 IMAGEIO_U8 | IMAGEIO_GRAYSCALE, 0);
127 int WriteAnimation(
plotparam *PlotParam,
int Width,
int Height,
128 const char *OutputFile)
130 const int NumPixels = Width*Height;
131 unsigned char *PlotInd = NULL;
132 unsigned char *Palette = NULL;
133 unsigned char **PlotIndFrames = NULL;
134 int Frame, Success = 0;
136 if(!(PlotInd = (
unsigned char *)malloc(Width*Height*PlotParam->NumFrames))
137 || !(Palette = (
unsigned char *)calloc(3*256, 1))
138 || !(PlotIndFrames = (
unsigned char **)
139 malloc(
sizeof(
unsigned char *)*PlotParam->NumFrames)))
142 for(Frame = 0; Frame < PlotParam->NumFrames; Frame++)
143 PlotIndFrames[Frame] = PlotInd + NumPixels*Frame;
146 if(!
Rgb2Ind(PlotInd, Palette, 255, PlotParam->Plot,
147 Width*Height*PlotParam->NumFrames))
151 FrameDifference(PlotIndFrames, Width, Height, PlotParam->NumFrames, 255);
154 if(!
GifWrite(PlotIndFrames, Width, Height, PlotParam->NumFrames,
155 Palette, 256, 255, PlotParam->Delays, OutputFile))
157 fprintf(stderr,
"Error writing \"%s\".\n", OutputFile);
161 printf(
"Output written to \"%s\".\n", OutputFile);
175 int main(
int argc,
char *argv[])
183 PlotParam.Plot = NULL;
184 PlotParam.Delays = NULL;
186 if(!ParseParam(&Param, argc, (
const char **)argv))
196 fprintf(stderr,
"Size mismatch: "
197 "phi0 (%dx%d) does not match image size (%dx%d).\n",
202 PlotParam.Image = f.
Data;
203 PlotParam.IterPerFrame = Param.IterPerFrame;
204 PlotParam.NumFrames = 0;
208 printf(
"Segmentation parameters\n");
209 printf(
"f : [%d x %d %s]\n",
211 printf(
"phi0 : %s\n", (Param.
Phi.
Data) ?
"custom" :
"default");
212 ChanVesePrintOpt(Param.
Opt);
214 printf(
"datatype : single precision float\n");
216 printf(
"datatype : double precision float\n");
224 fprintf(stderr,
"Out of memory.");
235 fprintf(stderr,
"Error in ChanVese.");
243 printf(
"\nRegion averages\n");
246 printf(
"c1 : %.4f\nc2 : %.4f\n\n", c1[0], c2[0]);
248 printf(
"c1 : (%.4f, %.4f, %.4f)\nc2 : (%.4f, %.4f, %.4f)\n\n",
249 c1[0], c1[1], c1[2], c2[0], c2[1], c2[2]);
260 free(PlotParam.Plot);
262 free(PlotParam.Delays);
263 FreeImageObj(Param.
Phi);
271 static int PlotFun(
int State,
int Iter, ATTRIBUTE_UNUSED num Delta,
272 ATTRIBUTE_UNUSED
const num *c1, ATTRIBUTE_UNUSED
const num *c2,
273 const num *Phi,
int Width,
int Height,
274 ATTRIBUTE_UNUSED
int NumChannels,
void *ParamPtr)
276 const int NumPixels = Width*Height;
278 unsigned char *Plot, *Temp = NULL;
280 num Red, Green, Blue, Alpha;
282 int x, y, Edge, NumFrames = PlotParam->NumFrames, Success = 0;
294 fprintf(stderr,
" Iteration %4d Delta %7.4f c1 = %6.4f c2 = %6.4f\r",
295 Iter, Delta, *c1, *c2);
297 fprintf(stderr,
" Iteration %4d Delta %7.4f\r", Iter, Delta);
300 fprintf(stderr,
"Converged in %d iterations. \n",
304 fprintf(stderr,
"Maximum number of iterations exceeded. \n");
308 if(State == 0 && (Iter % PlotParam->IterPerFrame) > 0)
311 if(!(Plot = (
unsigned char *)realloc(PlotParam->Plot,
312 3*Width*Height*(PlotParam->NumFrames + 1)))
313 || !(Delays = (
int *)realloc(PlotParam->Delays,
314 sizeof(
int)*(PlotParam->NumFrames + 1)))
315 || !(Temp = (
unsigned char *)malloc(Width*Height)))
317 fprintf(stderr,
"Out of memory.\n");
321 PlotParam->Plot = Plot;
322 PlotParam->Delays = Delays;
323 Plot += 3*NumPixels*PlotParam->NumFrames;
325 for(y = 0, i = 0; y < Height; y++)
326 for(x = 0; x < Width; x++, i++)
329 ((x > 0 && Phi[i - 1] < 0)
330 || (x + 1 < Width && Phi[i + 1] < 0)
331 || (y > 0 && Phi[i - Width] < 0)
332 || (y + 1 < Height && Phi[i + Width] < 0)))
340 for(y = 0, i = 0; y < Height; y++)
342 iu = (y == 0) ? 0 : -Width;
343 id = (y == Height - 1) ? 0 : Width;
345 for(x = 0; x < Width; x++, i++)
347 il = (x == 0) ? 0 : -1;
348 ir = (x == Width - 1) ? 0 : 1;
350 Red = PlotParam->Image[i];
351 Green = PlotParam->Image[i + NumPixels];
352 Blue = PlotParam->Image[i + 2*NumPixels];
360 + Temp[i + ir] + Temp[i + il]
361 + Temp[i + id] + Temp[i + iu])/4.0f;
366 Red = (1 - Alpha)*Red;
367 Green = (1 - Alpha)*Green;
368 Blue = (1 - Alpha)*Blue + Alpha;
370 Plot[3*i + 0] = ROUNDCLAMP(Red);
371 Plot[3*i + 1] = ROUNDCLAMP(Green);
372 Plot[3*i + 2] = ROUNDCLAMP(Blue);
376 PlotParam->Delays[NumFrames] = (State == 0) ? 12 : 120;
377 PlotParam->NumFrames++;
387 static int ParseParam(
programparams *Param,
int argc,
const char *argv[])
389 const char *Option, *Value;
399 Param->
Phi = NullImage;
401 Param->IterPerFrame = 10;
405 fprintf(stderr,
"Out of memory.\n");
419 Skip = (argv[k][0] ==
'-') ? 1 : 0;
421 k, &argv[k][Skip], argc, argv,
":");
426 Option = (
char *)
"f";
428 Option = (
char *)
"u";
437 if(!strcmp(Option,
"f") || !strcmp(Option,
"input"))
441 fprintf(stderr,
"Expected a value for option %s.\n", Option);
446 else if(!strcmp(Option,
"u") || !strcmp(Option,
"output"))
450 fprintf(stderr,
"Expected a value for option %s.\n", Option);
455 else if(!strcmp(Option,
"tol"))
462 else if(!strcmp(Option,
"mu"))
469 else if(!strcmp(Option,
"nu"))
476 else if(!strcmp(Option,
"lambda1"))
483 else if(!strcmp(Option,
"lambda2"))
490 else if(!strcmp(Option,
"dt"))
497 else if(!strcmp(Option,
"maxiter"))
504 else if(!strcmp(Option,
"phi0"))
508 fprintf(stderr,
"Expected a value for option %s.\n", Option);
513 FreeImageObj(Param->
Phi);
518 else if(!strcmp(Option,
"jpegquality"))
522 else if(NumValue < 0 || 100 < NumValue)
524 fprintf(stderr,
"JPEG quality must be between 0 and 100.\n");
530 else if(!strcmp(Option,
"iterperframe"))
534 else if(NumValue <= 0)
536 fprintf(stderr,
"Iterations per frame must be postive.\n");
540 Param->IterPerFrame = (int)NumValue;
544 fprintf(stderr,
"Unknown option \"%s\".\n", Option);
574 static int PhiRescale(
image *Phi)
576 const long NumEl = ((long)Phi->
Width) * ((long)Phi->
Height);
577 num *Data = Phi->
Data;
580 for(n = 0; n < NumEl; n++)
581 Data[n] = 4*(2*Data[n] - 1);