TPCCLIB
Loading...
Searching...
No Matches
imgaabtac.c
1
8/*****************************************************************************/
9#include "tpcclibConfig.h"
10/*****************************************************************************/
11#include <stdio.h>
12#include <stdlib.h>
13#include <math.h>
14#include <string.h>
15#include <unistd.h>
16#include <time.h>
17/*****************************************************************************/
18#include "libtpcmisc.h"
19#include "libtpcimgio.h"
20#include "libtpcimgp.h"
21/*****************************************************************************/
22
23/*****************************************************************************/
24static char *info[] = {
25 "Trial program to find the location of abdominal aorta in dynamic PET image.",
26 " ",
27 "Usage: @P [Options] imgfile maskfile",
28 " ",
29 "Options:",
30 " -peak=<filename>",
31 " Image containing possible peak pixels.",
32 " -stdoptions", // List standard options like --help, -v, etc
33 " ",
34 "See also: eabaort, imgprofi, imgthrs, imgfsegm, imgzavg, imgmax, img2tif",
35 " ",
36 "Keywords: image, input, blood, aorta, mask",
37 0};
38/*****************************************************************************/
39
40/*****************************************************************************/
41/* Turn on the globbing of the command line, since it is disabled by default in
42 mingw-w64 (_dowildcard=0); in MinGW32 define _CRT_glob instead, if necessary;
43 In Unix&Linux wildcard command line processing is enabled by default. */
44/*
45#undef _CRT_glob
46#define _CRT_glob -1
47*/
48int _dowildcard = -1;
49/*****************************************************************************/
50
51/*****************************************************************************/
55int main(int argc, char **argv)
56{
57 int ai, help=0, version=0, verbose=1;
58 int ret;
59 char *cptr, imgfile[FILENAME_MAX], maskfile[FILENAME_MAX];
60 char peakfile[FILENAME_MAX];
61
62
63 /*
64 * Get arguments
65 */
66 if(argc==1) {tpcPrintUsage(argv[0], info, stderr); return(1);}
67 imgfile[0]=maskfile[0]=(char)0;
68 peakfile[0]=(char)0;
69 /* Options */
70 for(ai=1; ai<argc; ai++) if(*argv[ai]=='-') { /* options */
71 cptr=argv[ai]+1; if(*cptr=='-') cptr++; if(cptr==NULL) continue;
72 if(tpcProcessStdOptions(argv[ai], &help, &version, &verbose)==0) continue;
73 if(strncasecmp(cptr, "PEAK=", 5)==0) {
74 strlcpy(peakfile, cptr+5, FILENAME_MAX); continue;
75 }
76 fprintf(stderr, "Error: invalid option '%s'\n", argv[ai]);
77 return(1);
78 } else break;
79
80 /* Print help or version? */
81 if(help==2) {tpcHtmlUsage(argv[0], info, ""); return(0);}
82 if(help) {tpcPrintUsage(argv[0], info, stdout); return(0);}
83 if(version) {tpcPrintBuild(argv[0], stdout); return(0);}
84
85 /* Process other arguments, starting from the first non-option */
86 if(ai<argc) {strlcpy(imgfile, argv[ai], FILENAME_MAX); ai++;}
87 if(ai<argc) {strlcpy(maskfile, argv[ai], FILENAME_MAX); ai++;}
88 if(ai<argc) {fprintf(stderr, "Error: too many arguments.\n"); return(1);}
89
90 /* Is something missing or wrong? */
91 if(!maskfile[0]) {
92 fprintf(stderr, "Error: missing command-line argument; use option --help\n");
93 return(1);
94 }
95
96 /* In verbose mode print arguments and options */
97 if(verbose>1) {
98 printf("imgfile := %s\n", imgfile);
99 printf("maskfile := %s\n", maskfile);
100 if(peakfile[0]) printf("peakfile := %s\n", peakfile);
101 }
102
103
104 /*
105 * Read dynamic image
106 */
107 if(verbose>0) fprintf(stdout, "reading dynamic image %s\n", imgfile);
108 IMG img; imgInit(&img);
109 ret=imgRead(imgfile, &img);
110 if(ret) {
111 fprintf(stderr, "Error: %s\n", img.statmsg);
112 if(verbose>1) printf("ret := %d\n", ret);
113 return(2);
114 }
115 if(imgNaNs(&img, 1)>0)
116 if(verbose>0) fprintf(stderr, "Warning: missing pixel values.\n");
117 /* Check if PET data is raw or image */
118 if(img.type!=IMG_TYPE_IMAGE) {
119 fprintf(stderr, "Error: %s is not an image.\n", imgfile);
120 imgEmpty(&img); return(2);
121 }
122 int dimt, dimz, dimy, dimx;
123 dimt=img.dimt; dimz=img.dimz; dimy=img.dimy; dimx=img.dimx;
124 if(verbose>0) fprintf(stdout, " dim[x,y,z,t] := %d, %d, %d, %d\n", dimx, dimy, dimz, dimt);
125
126
127 /*
128 * Filter in x,y dimension and in z dimension
129 */
130 IMG xyfilt; imgInit(&xyfilt);
131 IMG zfilt; imgInit(&zfilt);
132 ret=imgDup(&img, &xyfilt);
133 if(ret==0) ret=imgDup(&img, &zfilt);
134 if(ret) {
135 fprintf(stderr, "Error: cannot setup IMG data.\n");
136 if(verbose>1) fprintf(stderr, "ret := %d\n", ret);
137 imgEmpty(&img); imgEmpty(&xyfilt); imgEmpty(&zfilt); return(3);
138 }
139 ret=imgMeanFilter(&xyfilt, 5, 5, 0, 0, verbose-4);
140 if(ret==0) ret=imgMeanFilter(&zfilt, 0, 0, 5, 0, verbose-4);
141 if(ret!=0) {
142 fprintf(stderr, "Error: cannot filter the image.\n");
143 if(verbose>1) fprintf(stderr, "ret := %d\n", ret);
144 imgEmpty(&img); imgEmpty(&xyfilt); imgEmpty(&zfilt); return(4);
145 }
146
147
148 /*
149 * Subtract filtered images at peak time
150 */
151 IMG peak; imgInit(&peak);
152 ret=imgAllocateWithHeader(&peak, dimz, dimy, dimx, 1, &img);
153 if(ret) {
154 fprintf(stderr, "Error: out of memory.\n");
155 imgEmpty(&img); imgEmpty(&xyfilt); imgEmpty(&zfilt); imgEmpty(&peak);
156 return(5);
157 }
158 for(int z=0; z<dimz; z++)
159 for(int y=0; y<dimy; y++)
160 for(int x=0; x<dimx; x++) {
161 /* Find highest pixel value in t dimension */
162 float maxv=0.0;
163 int maxt=0;
164 for(int t=0; t<dimt; t++) {
165 if(xyfilt.m[z][y][x][t]>maxv) {maxt=t; maxv=xyfilt.m[z][y][x][t];}
166 }
167 peak.m[z][y][x][0]=zfilt.m[z][y][x][maxt]-xyfilt.m[z][y][x][maxt];
168 if(peak.m[z][y][x][0]<0.0) peak.m[z][y][x][0]=0.0;
169 /* divide by peak 'time' */
170 if(maxt>0) peak.m[z][y][x][0]/=(float)maxt;
171 }
172
173 /* Divide by distance from the image centre */
174 for(int y=0; y<dimy; y++) {
175 for(int x=0; x<dimx; x++) {
176 float d=1.0+hypotf((float)x-dimx/2, (float)y-dimy/2); // always >= 1
177 for(int z=0; z<dimz; z++)
178 peak.m[z][y][x][0]/=d;
179 }
180 }
181
182 /* Write peak file */
183 if(peakfile[0]) {
184 if(verbose>1) printf("writing peak image...\n");
185 ret=imgWrite(peakfile, &peak);
186 if(ret) {
187 fprintf(stderr, "Error: %s\n", peak.statmsg);
188 imgEmpty(&img); imgEmpty(&xyfilt); imgEmpty(&zfilt); imgEmpty(&peak);
189 return(11);
190 }
191 if(verbose>0) fprintf(stdout, "Peak image %s saved.\n", peakfile);
192 }
193
194 /* Free filter images */
195 imgEmpty(&xyfilt); imgEmpty(&zfilt);
196
197
198 /*
199 * Make mask
200 */
201 IMG mask; imgInit(&mask);
202 ret=imgAllocateWithHeader(&mask, dimz, dimy, dimx, 1, &img);
203 if(ret) {
204 fprintf(stderr, "Error: out of memory.\n");
205 imgEmpty(&img); imgEmpty(&peak);
206 return(6);
207 }
208
209 {
210 /* Mean over image planes */
211 IMG zimg; imgInit(&zimg);
212 if(imgMeanZ(&peak, &zimg)) {
213 fprintf(stderr, "Error: cannot calculate mean over z dimension.\n");
214 imgEmpty(&img); imgEmpty(&peak); imgEmpty(&mask); imgEmpty(&zimg);
215 return(6);
216 }
217
218 /* Get peak position from that (omitting image border) */
219 int px=1, py=1;
220 float pmax=zimg.m[0][1][1][0];
221 for(int y=1; y<dimy-1; y++) for(int x=1; x<dimx-1; x++) if(zimg.m[0][y][x][0]>pmax) {
222 pmax=zimg.m[0][y][x][0]; px=x; py=y;
223 }
224 if(verbose>1) printf("estimated x,y position is %d,%d\n", 1+px, 1+py);
225
226 /* Grow it */
227 IMG zmask; imgInit(&zmask);
228 imgAllocateWithHeader(&zmask, 1, dimy, dimx, 1, &zimg);
229 imgRegionGrowingByThreshold(&zimg, 0, py, px, 0.5*pmax, 10.*pmax, &zmask, verbose-3);
230
231 /* Inside that mask find max pixel in each image plane */
232 float zmax[dimz];
233 int xpos[dimz], ypos[dimz];
234 for(int z=0; z<dimz; z++) {
235 zmax[z]=0.0;
236 int py=0, px=0;
237 for(int y=0; y<dimy; y++) for(int x=0; x<dimx; x++)
238 if(zmask.m[0][y][x][0]>0.5 && peak.m[z][y][x][0]>zmax[z]) {
239 py=y; px=x; zmax[z]=peak.m[z][y][x][0];
240 }
241 //mask.m[z][py][px][0]=1.0;
242 xpos[z]=px; ypos[z]=py;
243 }
244
245 /* Median of plane max values */
246 float m=fmedian(zmax, dimz);
247 /* Grow regions starting from the max of each plane */
248 if(verbose>1) printf("growing from max of each plane\n");
249 for(int z=0; z<dimz; z++) {
250 imgRegionGrowingByThreshold(&peak, z, ypos[z], xpos[z], 0.99*m, 100.*m, &mask, verbose-3);
251 }
252
253 imgEmpty(&zimg); imgEmpty(&zmask);
254 }
255
256 /* Write file */
257 if(maskfile[0]) {
258 if(verbose>1) printf("writing mask image...\n");
259 ret=imgWrite(maskfile, &mask);
260 if(ret) {
261 fprintf(stderr, "Error: %s\n", mask.statmsg);
262 imgEmpty(&img); imgEmpty(&peak); imgEmpty(&mask);
263 return(12);
264 }
265 if(verbose>0) fprintf(stdout, "Mask image %s saved.\n", maskfile);
266 }
267
268 imgEmpty(&img); imgEmpty(&peak); imgEmpty(&mask);
269 if(verbose>0) printf("done.\n");
270 return(0);
271}
272/*****************************************************************************/
273
274/*****************************************************************************/
unsigned long long imgNaNs(IMG *img, int fix)
Definition img.c:658
int imgAllocateWithHeader(IMG *image, int planes, int rows, int columns, int frames, IMG *image_from)
Definition img.c:279
int imgDup(IMG *img1, IMG *img2)
Definition img.c:304
void imgEmpty(IMG *image)
Definition img.c:121
void imgInit(IMG *image)
Definition img.c:60
int imgRead(const char *fname, IMG *img)
Definition imgfile.c:26
int imgWrite(const char *fname, IMG *img)
Definition imgfile.c:136
int imgMeanFilter(IMG *img, int xn, int yn, int zn, int tn, int verbose)
Definition imgfilter.c:624
int imgMeanZ(IMG *img1, IMG *img2)
Definition imgflips.c:157
float fmedian(float *data, long long int n)
Definition imgminmax.c:593
int imgRegionGrowingByThreshold(IMG *img, const int sz, const int sy, const int sx, float lthr, float uthr, IMG *mask, int verbose)
Header file for libtpcimgio.
#define IMG_TYPE_IMAGE
Header file for libtpcimgp.
Header file for libtpcmisc.
int tpcProcessStdOptions(const char *s, int *print_usage, int *print_version, int *verbose_level)
Definition proginfo.c:40
size_t strlcpy(char *dst, const char *src, size_t dstsize)
Definition strext.c:245
int tpcHtmlUsage(const char *program, char *text[], const char *path)
Definition proginfo.c:213
void tpcPrintBuild(const char *program, FILE *fp)
Definition proginfo.c:383
void tpcPrintUsage(const char *program, char *text[], FILE *fp)
Definition proginfo.c:158
unsigned short int dimx
char type
float **** m
unsigned short int dimt
unsigned short int dimz
unsigned short int dimy
const char * statmsg