10#include "tpcclibConfig.h"
29static char *info[] = {
30 "Reconstruct PET image from attenuation and normalization corrected",
31 "2D PET sinogram using filtered back-projection (FBP).",
32 "This program does not correct image data for decay.",
33 "Image is corrected for the dead-time based on factors in the sinogram.",
34 "Image data is written in units ECAT counts per pixel per second.",
36 "Not for clinical use! Program is not thoroughly tested!",
38 "Usage: @P [Options] scnfile imgfile",
41 " -filter=<None|Ramp|Butter|Hann|Hamm|Parzen|Shepp>",
42 " Set the reconstruction filter; by default Hann.",
44 " Set cut-off value; by default 0.3.",
46 " Set zoom factor; by default 1.0 (no zoom).",
48 " Set image x and y dimensions; by default 128.",
49 " -rot[ation]=<value>",
50 " Set image rotation in degrees, -180 - 180; by default 0 (no rotation).",
52 " Set image shift in x direction (in cm); by default 0.",
54 " Set image shift in y direction (in cm); by default 0.",
56 " Divide image voxel values by voxel volume (mL); by default the voxel",
57 " volume is corrected later during image calibration.",
61 " @P -dim=256 a2345dy1.scn a2345dy1.img",
63 "See also: ecatnorm, edecay, ecalibr, atnmake, eframe, ecatmrp, img2scn",
65 "Keywords: ECAT, sinogram, image, reconstruction, FBP",
84int main(
int argc,
char **argv)
86 int ai, help=0, version=0, verbose=1;
87 char scnfile[FILENAME_MAX], imgfile[FILENAME_MAX];
88 int filter=FBP_FILTER_HANN;
92 float shiftX=0.0, shiftY=0.0;
97 static char *fbpFilterName[]={
98 "None",
"Ramp",
"Butter",
"Hann",
"Hamm",
"Parzen",
"Shepp", 0
105 if(argc==1) {
tpcPrintUsage(argv[0], info, stderr);
return(1);}
106 scnfile[0]=imgfile[0]=(char)0;
108 for(ai=1; ai<argc; ai++)
if(*argv[ai]==
'-') {
109 cptr=argv[ai]+1;
if(*cptr==
'-') cptr++;
if(cptr==NULL)
continue;
111 if(strncasecmp(cptr,
"FILTER=", 7)==0) {
114 while(fbpFilterName[i]!=0) {
115 if(!strcasecmp(cptr, fbpFilterName[i])) {
119 if(filter>=0)
continue;
120 }
else if(strncasecmp(cptr,
"DIM=", 4)==0) {
121 imgDim=atoi(cptr+4);
if(imgDim>1 && imgDim<=2048)
continue;
122 }
else if(strncasecmp(cptr,
"ZOOM=", 5)==0) {
123 zoom=
atof_dpi(cptr+5);
if(zoom>0.1 && zoom<100.0)
continue;
124 }
else if(strncasecmp(cptr,
"CUTOFF=", 7)==0) {
125 cutoff=
atof_dpi(cptr+7);
if(cutoff>0.0 && cutoff<1.0)
continue;
126 }
else if(strncasecmp(cptr,
"ROTATION=", 9)==0) {
129 if(v>=-180.0 && v<=180.0) {rotate=v;
continue;}
130 }
else if(strncasecmp(cptr,
"ROT=", 4)==0) {
133 if(v>-360.0 && v<360.0) {rotate=v;
continue;}
134 }
else if(strncasecmp(cptr,
"X=", 2)==0) {
137 if(v>-50.0 && v<50.0) {shiftX=10.0*v;
continue;}
138 }
else if(strncasecmp(cptr,
"Y=", 2)==0) {
141 if(v>-50.0 && v<50.0) {shiftY=10.0*v;
continue;}
143 fprintf(stderr,
"Error: invalid option '%s'.\n", argv[ai]);
148 if(help==2) {
tpcHtmlUsage(argv[0], info,
"");
return(0);}
153 if(ai<argc) {
strlcpy(scnfile, argv[ai++], FILENAME_MAX);}
154 if(ai<argc) {
strlcpy(imgfile, argv[ai++], FILENAME_MAX);}
156 fprintf(stderr,
"Error: too many arguments.\n");
162 fprintf(stderr,
"Error: missing command-line argument; use --help\n");
168 printf(
"scnfile := %s\n", scnfile);
169 printf(
"imgfile := %s\n", imgfile);
170 printf(
"Filter := %s\n", fbpFilterName[filter]);
171 printf(
"Cut-off := %g\n", cutoff);
172 printf(
"Zoom := %g\n", zoom);
173 printf(
"Dimension := %d\n", imgDim);
174 printf(
"Rotation := %g\n", rotate);
175 printf(
"X_shift_mm := %g\n", shiftX);
176 printf(
"Y_shift_mm := %g\n", shiftY);
177 printf(
"volume_correction := %d\n", pervol);
181 if(strcasecmp(imgfile, scnfile)==0) {
182 fprintf(stderr,
"Error: original sinogram must not be overwritten.\n");
187 fprintf(stderr,
"Error: invalid image dimension.\n");
195 if(verbose>0) printf(
"reading sinogram %s\n", scnfile);
199 fprintf(stderr,
"Error: %s\n", scn.
statmsg);
200 if(verbose>1) printf(
"ret := %d\n", ret);
204 printf(
"dimx := %d\n", scn.
dimx);
205 printf(
"dimy := %d\n", scn.
dimy);
206 printf(
"dimz := %d\n", scn.
dimz);
207 printf(
"dimt := %d\n", scn.
dimt);
211 fprintf(stderr,
"Error: file is not a sinogram.\n");
220 if(verbose>0) printf(
"FBP reconstruction...\n");
221 ret=
imgFBP(&scn, &img, imgDim, zoom, filter, cutoff, shiftX, shiftY, rotate,
224 fprintf(stderr,
"Error in reconstruction.\n");
225 if(verbose>1) printf(
"ret := %d\n", ret);
235 if(verbose>0) printf(
"correcting for voxel volume\n");
239 for(zi=0; zi<img.
dimz; zi++)
240 for(yi=0; yi<img.
dimy; yi++)
241 for(xi=0; xi<img.
dimx; xi++)
242 for(ti=0; ti<img.
dimt; ti++)
243 img.
m[zi][yi][xi][ti]/=vol;
245 fprintf(stderr,
"Warning: cannot correct for pixel volume.\n");
252 if(verbose>0) printf(
"writing image %s\n", imgfile);
254 fprintf(stderr,
"Error: %s\n", img.
statmsg);
260 if(verbose>0) fprintf(stdout,
"done.\n");
int atof_with_check(char *double_as_string, double *result_value)
double atof_dpi(char *str)
int imgFBP(IMG *scn, IMG *img, int imgDim, float zoom, int filter, float cutoff, float shiftX, float shiftY, float rotation, int verbose)
void imgEmpty(IMG *image)
int imgRead(const char *fname, IMG *img)
int imgWrite(const char *fname, IMG *img)
Header file for libtpcimgio.
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 libtpcrec.