10#include "tpcclibConfig.h"
26double bcvfunc(
double p,
void*);
30static char *info[] = {
31 "Based on given absolute threshold, calculate between-class variance from",
32 "static PET image file in ECAT, NIfTI, or Analyze format.",
33 "If threshold is not given, threshold that gives the highest between-class",
34 "variance is estimated.",
35 "Between-class variance is calculated using formula by Cao et al. 2018",
36 "doi: 10.1109/ACCESS.2018.2889013",
38 "Usage: @P [Options] imgfile [threshold]",
42 " Save mask file containing pixel values 1 (above threshold) and",
43 " 0 (under the threshold).",
46 "See also: imgthrs, imgmask, imgqntls, imginteg, imgslim, imgcutof",
48 "Keywords: image, threshold",
82 if(verbose>0) {printf(
"%s(IMG, %d, %f, ...)\n", __func__, fi, threshold); fflush(stdout);}
84 if(img==NULL || img->
dimz<1 || img->
dimy<1 || img->
dimx<1 || img->
dimt<1)
return(bcv);
85 if(fi<1 || fi>img->
dimt)
return(bcv);
87 if(verbose>1) fprintf(stdout,
"thresholding\n");
88 unsigned int p0=0, p1=0;
89 double s0=0.0, s1=0.0;
90 for(
int zi=0; zi<img->
dimz; zi++) {
91 for(
int yi=0; yi<img->
dimy; yi++) {
92 for(
int xi=0; xi<img->
dimx; xi++) {
93 if(img->
m[zi][yi][xi][fi-1]<threshold) {
94 p0++; s0+=img->
m[zi][yi][xi][fi-1];
95 }
else if(img->
m[zi][yi][xi][fi-1]>=threshold) {
96 p1++; s1+=img->
m[zi][yi][xi][fi-1];
102 printf(
"p0=%u\n", p0);
103 printf(
"p1=%u\n", p1);
114 mu=(s0+s1)/(
double)(p0+p1);
116 printf(
"mu0=%g\n", mu0);
117 printf(
"mu1=%g\n", mu1);
118 printf(
"mu=%g\n", mu);
122 bcv=(double)p0*(
double)p1*( (mu0-mu1)*(mu0-mu1) + (mu0-mu)*(mu0-mu) + (mu1-mu)*(mu1-mu) );
125 if(verbose>1) {printf(
"BCV := %g\n", bcv); fflush(stdout);}
138int main(
int argc,
char **argv)
140 int ai, help=0, version=0, verbose=1;
141 char petfile[FILENAME_MAX], maskfile[FILENAME_MAX];
142 float threshold=nanf(
"");
148 if(argc==1) {
tpcPrintUsage(argv[0], info, stderr);
return(1);}
149 petfile[0]=maskfile[0]=(char)0;
151 for(ai=1; ai<argc; ai++)
if(*argv[ai]==
'-') {
153 char *cptr=argv[ai]+1;
if(*cptr==
'-') cptr++;
if(cptr==NULL)
continue;
154 if(strncasecmp(cptr,
"MASK=", 5)==0) {
155 strlcpy(maskfile, cptr+5, FILENAME_MAX);
continue;
157 fprintf(stderr,
"Error: invalid option '%s'.\n", argv[ai]);
162 if(help==2) {
tpcHtmlUsage(argv[0], info,
"");
return(0);}
167 if(ai<argc) {
strlcpy(petfile, argv[ai], FILENAME_MAX); ai++;}
171 fprintf(stderr,
"Error: invalid threshold '%s'.\n", argv[ai]);
177 if(ai<argc) {fprintf(stderr,
"Error: too many arguments.\n");
return(1);}
182 fprintf(stderr,
"Error: missing command-line argument; try %s --help\n", argv[0]);
189 printf(
"petfile := %s\n", petfile);
190 if(!isnan(threshold)) printf(
"threshold := %g\n", threshold);
191 if(maskfile[0]) printf(
"maskfile := %s\n", maskfile);
200 if(verbose>1) {printf(
"reading %s\n", petfile); fflush(stdout);}
202 fprintf(stderr,
"Error: %s\n", img.
statmsg);
206 if(verbose>0) fprintf(stderr,
"Warning: missing pixel values.\n");
209 fprintf(stderr,
"Error: do not use for dynamic image.\n");
215 fprintf(stderr,
"Error: invalid image contents.\n");
219 printf(
"image_min := %g\n", imin);
220 printf(
"image_max := %g\n", imax);
225 if(!isnan(threshold)) {
226 if(threshold<=imin || threshold>=imax) {
227 fprintf(stdout,
"Image pixel value range: %g - %g\n", imin, imax); fflush(stdout);
228 fprintf(stderr,
"Error: invalid threshold %g.\n", threshold);
235 if(verbose>1) {printf(
"finding optimal threshold...\n"); fflush(stdout);}
237 int ret=
nlopt1D(bcvfunc, &img, 0.5*(imin+imax), imin, imax, 0.1*(imax-imin),
238 0.000001*(imax-imin), 1000, &p, &fv, verbose-2);
240 fprintf(stderr,
"Error: invalid image contents.\n");
245 printf(
"threshold := %g\n", threshold);
248 printf(
"BCV := %g\n", bcv);
257 fprintf(stderr,
"Error: cannot threshold.\n");
258 if(verbose>1) printf(
"ret=%d\n", ret);
262 if(verbose>1) fprintf(stdout,
"writing %s\n", maskfile);
265 fprintf(stderr,
"Error: %s\n", img.
statmsg);
266 if(verbose>1) printf(
"ret=%d\n", ret);
270 if(verbose>0) printf(
"Written %s\n", maskfile);
285double bcvfunc(
double p,
void *fdata)
int atof_with_check(char *double_as_string, double *result_value)
unsigned long long imgNaNs(IMG *img, int fix)
void imgEmpty(IMG *image)
int imgRead(const char *fname, IMG *img)
int imgWrite(const char *fname, IMG *img)
int imgMinMax(IMG *img, float *minvalue, float *maxvalue)
double imgBetween2ClassesVariance(IMG *img, const int fi, float threshold, int verbose)
int imgThresholdMask(IMG *img, float minValue, float maxValue, IMG *timg)
Header file for libtpcimgio.
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.
int nlopt1D(double(*_fun)(double, void *), void *_fundata, double x, double xl, double xu, double delta, double tol, const int maxeval, double *nx, double *nf, int verbose)
Header file for libtpcmodext.