8#include "tpcclibConfig.h"
27static char *info[] = {
28 "Testing image segmentation for static PET image.",
29 "This program can be used for method testing purposes only!",
31 "Segmented image will contain the segment numbers as integers 0, 1, 2, 3, ...",
33 "Usage: @P [Options] image segmimage",
38 "See also: imginteg, imgaumc, imgthrs, imgfsegm",
40 "Keywords: image, smoothing, mask, threshold",
61 if(n<1) {printf(
"(empty)\n");
return;}
62 if(n==1) {printf(
"%u\t1\n", list[0]);
return;}
64 unsigned int *sg=malloc(2*n*
sizeof(
unsigned int));
if(sg==NULL)
return;
65 unsigned int *sn=sg+n;
66 sg[0]=list[0]; sn[0]=1;
68 for(
unsigned int i=1; i<n; i++) {
76 sg[s]=list[i]; sn[s]=1; s++;
79 for(
unsigned int j=0; j<s; j++)
80 printf(
"%u\t%u\n", sg[j], sn[j]);
85void psegListContinuous(
89 if(n<1) {printf(
"(empty)\n");
return;}
90 if(n==1) {list[0]=0;
return;}
92 unsigned int *sg=malloc(2*n*
sizeof(
unsigned int));
if(sg==NULL)
return;
93 unsigned int *sn=sg+n;
94 sg[0]=list[0]; sn[0]=1;
96 for(
unsigned int i=1; i<n; i++) {
104 sg[s]=list[i]; sn[s]=1; s++;
112 for(
unsigned int j=0; j<s; j++)
113 for(
unsigned int k=j+1; k<s; k++)
if(sn[k]>sn[j]) {
114 unsigned int t=sg[j]; sg[j]=sg[k]; sg[k]=t;
115 t=sn[j]; sn[j]=sn[k]; sn[k]=t;
121 for(
unsigned int i=0; i<n; i++)
122 for(
unsigned int j=0; j<s; j++)
if(sg[j]==list[i]) {list[i]=j;
break;}
133 if(img==NULL || n<1) {printf(
"(empty)\n");
return;}
134 if((
unsigned int )img->
dimz*img->
dimy*img->
dimx!=n) {printf(
"(error)\n");
return;}
137 unsigned int *sg=malloc(2*n*
sizeof(
unsigned int));
if(sg==NULL) {printf(
"(error)\n");
return;}
138 unsigned int *sn=sg+n;
140 sg[0]=list[0]; sn[0]=1;
142 for(
unsigned int i=1; i<n; i++) {
152 sg[s]=list[i]; sn[s]=1; s++;
155 printf(
"Nr of segments: %u\n", s);
158 double *pmean=malloc(2*s*
sizeof(
double));
if(pmean==NULL) {printf(
"(error)\n"); free(sg);
return;}
160 for(
unsigned int j=0; j<s; j++) {
163 double *p=malloc(sn[j]*
sizeof(
double));
164 if(p==NULL) {printf(
"(error)\n"); free(sg); free(pmean);
return;}
165 for(
unsigned int i=1; i<n && pi<sn[j]; i++)
if(list[i]==sg[j]) p[pi++]=img->
pixel[i];
166 pmean[j]=
dmean(p, pi, psd+j);
170 for(
unsigned int j=0; j<s; j++)
171 printf(
"%u\t%u\t%g\t%g\n", sg[j], sn[j], pmean[j], psd[j]);
173 free(sg); free(pmean);
177void psegListCombineEqual(
182 if(img==NULL || n<1) {printf(
"(empty)\n");
return;}
183 if((
unsigned int )img->
dimz*img->
dimy*img->
dimx!=n) {printf(
"(error)\n");
return;}
186 unsigned int *sg=malloc(2*n*
sizeof(
unsigned int));
if(sg==NULL) {printf(
"(error)\n");
return;}
187 unsigned int *sn=sg+n;
189 sg[0]=list[0]; sn[0]=1;
191 for(
unsigned int i=1; i<n; i++) {
201 sg[s]=list[i]; sn[s]=1; s++;
207 double *pmean=malloc(2*s*
sizeof(
double));
if(pmean==NULL) {printf(
"(error)\n"); free(sg);
return;}
209 for(
unsigned int j=0; j<s; j++) {
212 double *p=malloc(sn[j]*
sizeof(
double));
213 if(p==NULL) {printf(
"(error)\n"); free(sg); free(pmean);
return;}
214 for(
unsigned int i=1; i<n && pi<sn[j]; i++)
if(list[i]==sg[j]) p[pi++]=img->
pixel[i];
215 pmean[j]=
dmean(p, pi, psd+j);
219 for(
unsigned int j=0; j<s; j++) {
220 if(sn[j]==0)
continue;
221 if(fabs(psd[j])>1.0E-08)
continue;
222 for(
unsigned int k=j+1; k<s; k++) {
223 if(sn[k]==0)
continue;
224 if(fabs(psd[k])>1.0E-08)
continue;
225 if(fabs(pmean[j]-pmean[k])>1.0E-08)
continue;
226 printf(
"combining\n");
227 printf(
" %u\t%u\t%g\t%g\n", sg[j], sn[j], pmean[j], psd[j]);
228 printf(
" %u\t%u\t%g\t%g\n", sg[k], sn[k], pmean[k], psd[k]);
230 for(
unsigned int i=0; i<n; i++)
if(list[i]==sg[k]) list[i]=sg[j];
234 free(sg); free(pmean);
241double psegListCombineMostSimilar(
246 if(img==NULL || n<1) {printf(
"(empty)\n");
return(nan(
""));}
247 if((
unsigned int )img->
dimz*img->
dimy*img->
dimx!=n) {printf(
"(error)\n");
return(nan(
""));}
250 unsigned int *sg=malloc(2*n*
sizeof(
unsigned int));
if(sg==NULL) {printf(
"(error)\n");
return(nan(
""));}
251 unsigned int *sn=sg+n;
253 sg[0]=list[0]; sn[0]=1;
255 for(
unsigned int i=1; i<n; i++) {
265 sg[s]=list[i]; sn[s]=1; s++;
271 double *pmean=malloc(2*s*
sizeof(
double));
if(pmean==NULL) {printf(
"(error)\n"); free(sg);
return(nan(
""));}
273 for(
unsigned int j=0; j<s; j++) {
276 double *p=malloc(sn[j]*
sizeof(
double));
277 if(p==NULL) {printf(
"(error)\n"); free(sg); free(pmean);
return(nan(
""));}
278 for(
unsigned int i=1; i<n && pi<sn[j]; i++)
if(list[i]==sg[j]) p[pi++]=img->
pixel[i];
279 pmean[j]=
dmean(p, pi, psd+j);
283 double min_t=1.0E+10;
284 unsigned int min_j=s+1, min_k=s+1;
285 for(
unsigned int j=0; j<s; j++) {
286 if(sn[j]==0)
continue;
287 for(
unsigned int k=j+1; k<s; k++) {
288 if(sn[k]==0)
continue;
289 if(fabs(psd[k])<1.0E-08 && fabs(psd[j])<1.0E-08)
continue;
291 double t=fabs(pmean[j]-pmean[k])/sqrt(psd[j]*psd[j]/(
double)sn[j] + psd[k]*psd[k]/(
double)sn[k]);
298 if(min_j>s || min_k>s) {
299 printf(
"nothing to combine.\n");
300 free(sg); free(pmean);
304 printf(
"smallest t=%g is too large, nothing to combine.\n", min_t);
305 free(sg); free(pmean);
309 printf(
"combining, t=%g\n", min_t);
310 printf(
" %u\t%u\t%g\t%g\n", sg[min_j], sn[min_j], pmean[min_j], psd[min_j]);
311 printf(
" %u\t%u\t%g\t%g\n", sg[min_k], sn[min_k], pmean[min_k], psd[min_k]);
313 for(
unsigned int i=0; i<n; i++)
if(list[i]==sg[min_k]) list[i]=sg[min_j];
315 free(sg); free(pmean);
328 if(img==NULL || n<1) {printf(
"(empty)\n");
return(2);}
329 if((
unsigned int )img->
dimz*img->
dimy*img->
dimx!=n) {printf(
"(error)\n");
return(2);}
331 unsigned int *sg=malloc(2*n*
sizeof(
unsigned int));
if(sg==NULL) {printf(
"(error)\n");
return(2);}
332 unsigned int *sn=sg+n;
334 sg[0]=list[0]; sn[0]=1;
336 for(
unsigned int i=1; i<n; i++) {
346 sg[s]=list[i]; sn[s]=1; s++;
352 double *pmean=malloc(2*s*
sizeof(
double));
if(pmean==NULL) {printf(
"(error)\n"); free(sg);
return(3);}
354 for(
unsigned int j=0; j<s; j++) {
357 double *p=malloc(sn[j]*
sizeof(
double));
358 if(p==NULL) {printf(
"(error)\n"); free(sg); free(pmean);
return(4);}
359 for(
unsigned int i=1; i<n && pi<sn[j]; i++)
if(list[i]==sg[j]) p[pi++]=img->
pixel[i];
360 pmean[j]=
dmean(p, pi, psd+j);
365 unsigned int moved=0;
366 for(
unsigned int j=0; j<s; j++) {
367 if(fabs(psd[j])<1.0E-08)
continue;
368 double max_dif=0.0, pxlv=nan(
"");
369 unsigned int max_i=n+1;
370 for(
unsigned int i=0; i<n; i++)
if(list[i]==sg[j]) {
371 double d=fabs(pmean[j]-img->
pixel[i]);
372 if(d>max_dif) {max_dif=d; max_i=i; pxlv=img->
pixel[i];}
374 if(max_i>n || max_dif<1.0E-06)
continue;
375 printf(
" group %u largest dif is %g\n", sg[j], max_dif);
377 unsigned int better_k=s+1;
378 double min_d=max_dif;
379 for(
unsigned int k=0; k<s; k++)
if(k!=j) {
380 double d=fabs(pmean[k]-pxlv);
381 if(d<min_d) {min_d=d; better_k=k;}
383 if(better_k>s)
continue;
384 printf(
" group %u would be better match with dif %g\n", sg[better_k], min_d);
385 printf(
" pixel value is %g; means of own and better groups are %g and %g\n", pxlv, pmean[j], pmean[better_k]);
386 list[max_i]=sg[better_k];
390 free(sg); free(pmean);
391 if(moved==0)
return(1);
398int imgSegmentStaticTest(
407 if(verbose>0) {printf(
"%s(IMG, IMG, ...)\n", __func__); fflush(stdout);}
412 if(verbose>1) printf(
"pxlNr := %u\n", pxlNr);
414 if(verbose>0) fprintf(stderr,
"Error: too few pixels.\n");
419 unsigned int bdx=1+(img->
dimx-1)/3;
420 unsigned int bdy=1+(img->
dimy-1)/3;
421 unsigned int bdz=1+(img->
dimz-1)/3;
422 if(verbose>2) printf(
"block dimensions x y z := %u %u %u\n", bdx, bdy, bdz);
430 if(verbose>0) fprintf(stderr,
"Error: cannot allocate memory for segmented image.\n");
438 unsigned int *pseg=malloc(
sizeof(
unsigned int)*pxlNr);
440 fprintf(stderr,
"Error: cannot allocate memory.\n");
444 unsigned int s=0, si=0;
445 for(
int zi=0; zi<img->
dimz; zi++)
446 for(
int yi=0; yi<img->
dimy; yi++)
447 for(
int xi=0; xi<img->
dimx; xi++) {
448 s=(zi/3)*bdx*bdy + (yi/3)*bdx + (xi/3);
454 if(verbose>2) psegListImg(pseg, si, img);
456 psegListCombineEqual(pseg, si, img);
457 if(verbose>2) psegListImg(pseg, si, img);
461 if(verbose>2) printf(
"combining most similar\n");
462 t=psegListCombineMostSimilar(pseg, si, img);
464 if(verbose>2) psegListImg(pseg, si, img);
467 if(verbose>2) printf(
"move pixels between segments\n");
468 }
while(psegListPxlMove(pseg, si, img)==0);
469 if(verbose>2) psegListImg(pseg, si, img);
471 psegListCombineEqual(pseg, si, img);
472 if(verbose>2) psegListImg(pseg, si, img);
475 if(verbose>2) printf(
"combining most similar\n");
476 t=psegListCombineMostSimilar(pseg, si, img);
478 if(verbose>2) psegListImg(pseg, si, img);
481 psegListContinuous(pseg, si);
483 if(verbose>2) psegListImg(pseg, si, img);
487 for(
int zi=0; zi<out->
dimz; zi++)
488 for(
int yi=0; yi<out->
dimy; yi++)
489 for(
int xi=0; xi<out->
dimx; xi++) {
490 out->
m[zi][yi][xi][0]=(float)pseg[si];
507int main(
int argc,
char **argv)
509 int ai, help=0, version=0, verbose=1;
510 char petfile[FILENAME_MAX], segfile[FILENAME_MAX];
517 if(argc==1) {
tpcPrintUsage(argv[0], info, stderr);
return(1);}
518 petfile[0]=segfile[0]=(char)0;
520 for(ai=1; ai<argc; ai++)
if(*argv[ai]==
'-') {
522 char *cptr=argv[ai]+1;
if(*cptr==
'-') cptr++;
if(cptr==NULL)
continue;
523 fprintf(stderr,
"Error: invalid option '%s'.\n", argv[ai]);
528 if(help==2) {
tpcHtmlUsage(argv[0], info,
"");
return(0);}
533 if(ai<argc) {
strlcpy(petfile, argv[ai++], FILENAME_MAX);}
534 if(ai<argc) {
strlcpy(segfile, argv[ai++], FILENAME_MAX);}
536 fprintf(stderr,
"Error: invalid argument '%s'.\n", argv[ai]);
542 fprintf(stderr,
"Error: missing command-line argument; use option --help\n");
546 if(strcasecmp(petfile, segfile)==0) {
547 fprintf(stderr,
"Error: same file name for input and output data.\n");
554 printf(
"petfile := %s\n", petfile);
555 printf(
"segfile := %s\n", segfile);
563 if(verbose>0) fprintf(stdout,
"reading image %s\n", petfile);
567 fprintf(stderr,
"Error: %s\n", img.
statmsg);
if(verbose>1)
imgInfo(&img);
571 printf(
"image dimensions: %d %d %d\n", img.
dimz, img.
dimy, img.
dimx);
572 printf(
"image frame nr: %d\n", img.
dimt);
576 fprintf(stderr,
"Error: image must be static (one frame).\n");
580 if(verbose>0) fprintf(stderr,
"Warning: missing pixel values.\n");
586 if(verbose>0) fprintf(stdout,
"segmenting image %s\n", petfile);
588 ret=imgSegmentStaticTest(&img, &seg, verbose-2);
590 fprintf(stderr,
"Error: segmentation not successful.\n");
598 if(verbose>1) printf(
"writing segmented image %s\n", segfile);
600 fprintf(stderr,
"Error: %s\n", seg.
statmsg);
606 if(verbose>0) printf(
"done.\n");
unsigned long long imgNaNs(IMG *img, int fix)
int imgAllocateWithHeader(IMG *image, int planes, int rows, int columns, int frames, IMG *image_from)
void imgEmpty(IMG *image)
int imgRead(const char *fname, IMG *img)
int imgWrite(const char *fname, IMG *img)
Header file for libtpccurveio.
Header file for libtpcimgio.
#define IMG_STATUS_OCCUPIED
Header file for libtpcimgp.
Header file for libtpcmisc.
int tpcProcessStdOptions(const char *s, int *print_usage, int *print_version, int *verbose_level)
size_t strlcpy(char *dst, const char *src, size_t dstsize)
int tpcHtmlUsage(const char *program, char *text[], const char *path)
void tpcPrintBuild(const char *program, FILE *fp)
void tpcPrintUsage(const char *program, char *text[], FILE *fp)
Header file for libtpcmodel.
double dmean(double *data, int n, double *sd)
Header file for libtpcmodext.