TPCCLIB
Loading...
Searching...
No Matches
reprojection.c
Go to the documentation of this file.
1
7/*****************************************************************************/
8#include "libtpcrec.h"
9/*****************************************************************************/
10
11/*****************************************************************************/
21 IMG *img,
23 IMG *scn,
25 int verbose
26) {
27 if(verbose>0) printf("imgReprojection()\n");
28
29 int i, j, ret;
30 int plane, frame, binNr, viewNr;
31 float *scnData, *imgData, *fptr, f;
32 float *sinB, bpZoom, bpZoomInv;
33
34
35 /* Check the arguments */
36 if(img==NULL || scn==NULL || img->status!=IMG_STATUS_OCCUPIED) return(1);
37 /* Clear any previous contents in sinogram data structure */
38 imgEmpty(scn);
39
40 /* Determine the sinogram dimensions */
41 if(img->sizez<3.0) { /* HR+ */
42 scn->dimx=binNr=288; scn->dimy=viewNr=144;
43 scn->sampleDistance=2.25; /* bin size (mm) */
44 scn->axialFOV=155.2; scn->transaxialFOV=583.;
45 } else if(img->sizez<5.0) { /* GE Advance */
46 scn->dimx=binNr=281; scn->dimy=viewNr=336;
47 scn->sampleDistance=1.95730; /* bin size (mm) */
48 scn->axialFOV=150.; scn->transaxialFOV=550.;
49 } else { /* 931 */
50 scn->dimx=binNr=192; scn->dimy=viewNr=256;
51 scn->sampleDistance=3.12932; /* bin size (mm) */
52 scn->axialFOV=108.; scn->transaxialFOV=600.829;
53 }
54
55 /*
56 * Allocate output sinogram
57 */
58 if(verbose>1) printf("allocating memory for sinogram\n");
59 ret=imgAllocate(scn, img->dimz, scn->dimy, scn->dimx, img->dimt);
60 if(ret) return(3);
61
62 /* Set sinogram "header" information */
63 scn->type=IMG_TYPE_RAW;
64 scn->_fileFormat=img->_fileFormat;
65 scn->unit=CUNIT_COUNTS;
66 scn->scanStart=img->scanStart;
67 scn->sizez=img->sizez;
68 strcpy(scn->studyNr, img->studyNr);
69 for(plane=0; plane<img->dimz; plane++)
70 scn->planeNumber[plane]=img->planeNumber[plane];
74 for(frame=0; frame<img->dimt; frame++) {
75 scn->start[frame]=img->start[frame]; scn->end[frame]=img->end[frame];
76 scn->mid[frame]=0.5*(scn->start[frame]+scn->end[frame]);
77 }
78 scn->isWeight=0;
79
80 /*
81 * Preparations for reprojection
82 */
83 /* Allocate memory for scan and image data arrays */
84 if(verbose>1) printf("allocating memory for matrix data\n");
85 scnData=(float*)calloc(scn->dimx*scn->dimy, sizeof(float));
86 imgData=(float*)calloc(img->dimx*img->dimy, sizeof(float));
87 if(scnData==NULL || imgData==NULL) return(4);
88 /* Pre-compute the sine tables for back-projection */
89 sinB=(float*)calloc((3*viewNr/2), sizeof(float));
90 if(sinB==NULL) {free((char*)scnData); free((char*)imgData); return(4);}
91 recSinTables(viewNr, sinB, NULL, 0.0);
92 /* Set the backprojection zoom and its inverse */
93 bpZoom=img->zoom*(float)img->dimx/(float)binNr; bpZoomInv=1.0/bpZoom;
94 if(verbose>1) printf("bpZoom=%g bpZoomInv=%g\n", bpZoom, bpZoomInv);
95 /* Initialize variables used by back-projection */
96 for(i=0; i<3*viewNr/2; i++) sinB[i]*=bpZoomInv;
97
98
99 /*
100 * Reprojection of one matrix at a time
101 */
102 if(verbose>1) {printf("reprojection of matrices\n"); fflush(stdout);}
103 for(plane=0; plane<img->dimz; plane++) for(frame=0; frame<img->dimt; frame++) {
104 if(verbose>2) {
105 printf(" plane %d frame %d\n", img->planeNumber[plane], frame+1);
106 fflush(stdout);
107 }
108
109 /* Copy image data into the array */
110 /* At the same time, correct for the frame length */
111 f=img->end[frame]-img->start[frame]; if(f<1.0) f=1.0;
112 /* if GE Advance, then multiply by voxel volume, */
113 /* because it is corrected again in image calibration */
114 if(binNr==281 && img->sizex>0 && img->sizey>0 && img->sizez>0)
115 f*=0.001*img->sizex*img->sizey*img->sizez;
116 for(i=0, fptr=imgData; i<img->dimy; i++) for(j=0; j<img->dimx; j++)
117 *fptr++ = f*img->m[plane][i][j][frame];
118
119 /* Initiate sinogram buffer to zero */
120 memset(scnData, 0, scn->dimx*scn->dimy*sizeof(float));
121
122 /* Reproject on one angle (view) at a time */
123 for(i=0; i<viewNr; i++) {
124 viewReprojection(imgData, scnData+(i*binNr), i,
125 img->dimx, viewNr, binNr, sinB, sinB, 0.0, 0.0, bpZoom);
126 /* smoothing by mean */
127 if(scn->dimx>=img->dimx)
128 reprojectionAvg5(scnData+(i*binNr), binNr);
129 else
130 reprojectionAvg3(scnData+(i*binNr), binNr);
131 }
132
133 /* Copy the sinogram data to sinogram matrix */
134 /* Correct for zoom */
135 f=bpZoomInv*bpZoomInv;
136 for(i=0, fptr=scnData; i<viewNr; i++) for(j=0; j<binNr; j++)
137 scn->m[plane][i][j][frame] = *fptr++ * f;
138
139 }
140 if(verbose>1) {printf(" reprojection done.\n"); fflush(stdout);}
141 free(imgData); free(scnData); free(sinB);
142
143 return(0);
144}
145/*****************************************************************************/
146
147/*****************************************************************************/
156 float *image,
158 int dim,
160 int rays,
163 int views,
165 float bpzoom,
167 float *sinogram,
169 int verbose
170) {
171 if(verbose>0) {
172 printf("reprojection(%d, %d, %d, %g)\n", dim, rays, views, bpzoom);
173 fflush(stdout);
174 }
175 if(image==NULL || rays<2 || views<2 || dim<2 || sinogram==NULL) return(1);
176 if(dim%2) return(2);
177 if(bpzoom<0.1) return(3);
178
179 int i;
180
181 /* Initiate sinogram data to zero */
182 for(i=0; i<rays*views; i++) sinogram[i]=0.0;
183
184 /* Set the backprojection zoom inverse */
185 float bpzoomInv;
186 bpzoomInv=1.0/bpzoom;
187
188 /* Pre-compute the sine tables for back-projection */
189 float sinB[3*views/2];
190 recSinTables(views, sinB, NULL, 0.0);
191 for(i=0; i<3*views/2; i++) sinB[i]*=bpzoomInv;
192
193 /* Reproject on one angle (view) at a time */
194 for(i=0; i<views; i++) {
195 if(verbose>1) {printf(" reprojecting angle %d\n", 1+i); fflush(stdout);}
196 viewReprojection(image, sinogram+(i*rays), i,
197 dim, views, rays, sinB, sinB, 0.0, 0.0, bpzoom);
198
199 if(dim>=rays)
200 reprojectionAvg5(sinogram+(i*rays), rays);
201 else
202 reprojectionAvg3(sinogram+(i*rays), rays);
203
204/*
205 if(i==0 || i==views/4 || i==views/2 || i==3*views/4)
206 reprojectionAvg5(sinogram+(i*rays), rays);
207*/
208 }
209
210 return(0);
211}
212/*****************************************************************************/
213
214/*****************************************************************************/
218 float *idata,
220 float *sdata,
222 int view,
224 int dim,
227 int viewNr,
229 int rayNr,
231 float *sinB,
233 float *sinBrot,
235 float offsX,
237 float offsY,
239 float bpZoom
240) {
241 float *iOrigin, sir, cor, si, co, tpow2, t, *imgp, fract, rayCenter, toffs;
242 int x, y, yBottom, xRight, halfdim, ti;
243
244 if(view>=viewNr) {
245 fprintf(stderr, "Error in viewReprojection(): view=%d >= %d\n", view, viewNr);
246 fflush(stderr);
247 exit(1);
248 }
249
250 /* Set pointer to image origin (middle of the image data) */
251 halfdim=dim/2;
252 iOrigin= idata + dim*(halfdim-1) + halfdim;
253 /* Set sine and cosine for x,y-shift */
254 si=sinB[view]*offsY;
255 co=sinB[viewNr/2+view]*offsX;
256 /* Set sin and cos for reprojection */
257 sir=sinBrot[view];
258 cor=sinBrot[viewNr/2+view];
259 /* Set rotation point */
260 y=halfdim-2;
261 rayCenter=(float)rayNr/2.0;
262 if((float)y>rayCenter*bpZoom) {
263 y=(int)(rayCenter*bpZoom);
264 yBottom=-y;
265 } else {
266 yBottom=-halfdim+1;
267 }
268 toffs=rayCenter-si+co;
269 tpow2=rayCenter*rayCenter*bpZoom*bpZoom;
270 for(; y>=yBottom; y--) {
271 xRight=(int)sqrt(tpow2-((float)y+0.5)*((float)y+0.5)) + 1;
272 if(xRight>=halfdim) {
273 xRight=halfdim-1;
274 x=-halfdim;
275 } else {
276 x=-xRight;
277 }
278 /* distance between projection ray and origo */
279 t=toffs - (float)y*sir + ((float)(x+1))*cor;
280 imgp=iOrigin-y*dim+x;
281 for(; x<=xRight; x++, t+=cor, imgp++) {
282 ti=(int)t;
283 fract=t-(float)ti;
284 sdata[ti] += *imgp * (1.0-fract);
285 sdata[ti+1] += *imgp * fract;
286 }
287 }
288}
289/*****************************************************************************/
290
291/*****************************************************************************/
295 float *data,
297 int n
298) {
299 int i;
300 float tmp, prev=0.0, w;
301
302 w=1.0/3.0;
303 for(i=1; i<n-1; i++) {
304 tmp=(data[i-1] + data[i] + data[i+1])*w;
305 data[i-1]=prev;
306 prev=tmp;
307 }
308 data[i-1]=prev; data[i]=0.0;
309}
310/*****************************************************************************/
311
312/*****************************************************************************/
316 float *data,
318 int n
319) {
320 int i;
321 float tmp, prev2, prev, w;
322
323 prev=prev2=data[2]; w=0.2;
324 for(i=2; i<n-2; i++) {
325 tmp=(data[i-2] + data[i-1] + data[i] + data[i+1] + data[i+2])*w;
326 data[i-2]=prev2;
327 prev2=prev;
328 prev=tmp;
329 }
330 data[i-2]=prev2; data[i-1]=prev;
331}
332/*****************************************************************************/
333
334/*****************************************************************************/
338 float *data,
340 int n
341) {
342 int i;
343 float me, prev=0.0, a, b, c;
344
345 for(i=1; i<n-1; i++) {
346 a=data[i-1]; b=data[i]; c=data[i+1];
347 if(a>=b && a<=c) me=a;
348 else if(b>=a && b<=c) me=b;
349 else me=c;
350 data[i-1]=prev;
351 prev=me;
352 }
353 data[i-1]=prev; data[i]=0.0;
354}
355/*****************************************************************************/
356
357/*****************************************************************************/
361 float *prj,
363 float *idata,
365 int dim,
367 int view,
370 int viewNr,
372 int rayNr,
374 float *sinB,
376 float *sinBrot,
378 float offsX,
380 float offsY,
382 float bpZoom
383) {
384 int halfdim=dim/2;
385 float *iOrigin=idata+dim*(halfdim-1)+halfdim;
386 float si, co, sir, cor;
387 /* Set sin and cos for x,y-shift */
388 si=sinB[view]*offsY;
389 co=sinB[viewNr/2+view]*offsX;
390 /* Set sin and cos for backprojection */
391 sir=sinBrot[view];
392 cor=sinBrot[viewNr/2+view];
393
394 /* Set rotation point */
395 float rayCenter, toffs, tpow2;
396 int x, y, yBottom, xRight;
397 rayCenter=(float)rayNr/2.0;
398 y=halfdim-2;
399 if((float)y>rayCenter*bpZoom) {
400 y=(int)(rayCenter*bpZoom);
401 yBottom=-y;
402 } else {
403 yBottom=-halfdim+1;
404 }
405 toffs=rayCenter-si+co;
406
407 float *iptr, fract, t;
408 int ti;
409 tpow2=rayCenter*rayCenter*bpZoom*bpZoom;
410 for(; y>=yBottom; y--) {
411 xRight=(int)sqrt(tpow2-((float)y+0.5)*((float)y+0.5)) + 1;
412 if(xRight>=halfdim) {
413 xRight=halfdim-1;
414 x=-halfdim;
415 } else {
416 x=-xRight;
417 }
418 /* distance between projection ray and origo */
419 t=toffs - (float)y*sir + ((float)(x+1))*cor;
420 iptr=iOrigin-y*dim+x;
421 for(; x<=xRight; x++, t+=cor, iptr++) {
422 ti=(int)t;
423 fract=t-(float)ti;
424 *iptr+= prj[ti] + (prj[ti+1] - prj[ti])*fract;
425 }
426 }
427}
428/*****************************************************************************/
429
430/*****************************************************************************/
int imgAllocate(IMG *image, int planes, int rows, int columns, int frames)
Definition img.c:194
void imgEmpty(IMG *image)
Definition img.c:121
#define IMG_TYPE_RAW
#define IMG_STATUS_OCCUPIED
#define IMG_DC_UNKNOWN
Header file for libtpcrec.
void recSinTables(int views, float *sinB, float *sinBrot, float rotation)
Definition recutil.c:12
void reprojectionMed3(float *data, int n)
void viewBackprojection(float *prj, float *idata, int dim, int view, int viewNr, int rayNr, float *sinB, float *sinBrot, float offsX, float offsY, float bpZoom)
void viewReprojection(float *idata, float *sdata, int view, int dim, int viewNr, int rayNr, float *sinB, float *sinBrot, float offsX, float offsY, float bpZoom)
void reprojectionAvg3(float *data, int n)
int reprojection(float *image, int dim, int rays, int views, float bpzoom, float *sinogram, int verbose)
int imgReprojection(IMG *img, IMG *scn, int verbose)
void reprojectionAvg5(float *data, int n)
float sizex
unsigned short int dimx
char type
float sampleDistance
float **** m
char decayCorrection
float transaxialFOV
char unit
char status
time_t scanStart
int _fileFormat
unsigned short int dimt
int * planeNumber
float sizey
float * start
unsigned short int dimz
unsigned short int dimy
float * end
float zoom
char radiopharmaceutical[32]
float isotopeHalflife
char studyNr[MAX_STUDYNR_LEN+1]
float axialFOV
float * mid
char isWeight
float sizez