TPCCLIB
Loading...
Searching...
No Matches
reprojection.c File Reference

Image reprojection. More...

#include "libtpcrec.h"

Go to the source code of this file.

Functions

int imgReprojection (IMG *img, IMG *scn, int verbose)
int reprojection (float *image, int dim, int rays, int views, float bpzoom, float *sinogram, int verbose)
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)
void reprojectionAvg5 (float *data, int n)
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)

Detailed Description

Image reprojection.

Based on the codes written by Sakari Alenius for Sun UNIX workstations.

Author
Vesa Oikonen

Definition in file reprojection.c.

Function Documentation

◆ imgReprojection()

int imgReprojection ( IMG * img,
IMG * scn,
int verbose )

Image reprojection to 2D sinogram.

Returns
Returns 0 if ok.
Parameters
imgPointer to IMG struct containing the input image data. img->sizez is used to determine the scanner specific parameters including sinogram dimensions.
scnPointer to initiated IMG struct in which the sinogram will be written.
verboseVerbose level; if zero, then nothing is printed to stderr or stdout

Definition at line 16 of file reprojection.c.

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}
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
void recSinTables(int views, float *sinB, float *sinBrot, float rotation)
Definition recutil.c:12
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)
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

◆ reprojection()

int reprojection ( float * image,
int dim,
int rays,
int views,
float bpzoom,
float * sinogram,
int verbose )

Reprojection of one 2D image matrix to sinogram when data is provided as arrays of floats.

See also
imgReprojection, fbp,
Returns
Returns 0 if ok.
Parameters
imagePointer to float array containing dim*dim image pixel values.
dimImage x and y dimensions; must be an even number.
raysNr of rays (bins or columns) in sinogram data.
viewsNr of views (rows) in sinogram data; usually larger or equal to the image dimensions.
bpzoomBackprojection zoom factor; imagezoom*dim/rays
sinogramPointer to pre-allocated sinogram data; size must be at least rays*views.
verboseVerbose level; if zero, then nothing is printed to stderr or stdout

Definition at line 154 of file reprojection.c.

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}

Referenced by atnMake().

◆ reprojectionAvg3()

void reprojectionAvg3 ( float * data,
int n )

Average over three samples for image reprojection (1D 3-point mean).

Parameters
dataPointer to data array
nArray length

Definition at line 293 of file reprojection.c.

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}

Referenced by imgReprojection(), and reprojection().

◆ reprojectionAvg5()

void reprojectionAvg5 ( float * data,
int n )

Average over five samples for image reprojection (1D 5-point mean).

Parameters
dataPointer to data array
nArray length

Definition at line 314 of file reprojection.c.

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}

Referenced by imgReprojection(), and reprojection().

◆ reprojectionMed3()

void reprojectionMed3 ( float * data,
int n )

Median over three samples for image reprojection (1D 3-point median).

Parameters
dataPointer to data array
nArray length

Definition at line 336 of file reprojection.c.

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}

◆ viewBackprojection()

void viewBackprojection ( float * prj,
float * idata,
int dim,
int view,
int viewNr,
int rayNr,
float * sinB,
float * sinBrot,
float offsX,
float offsY,
float bpZoom )

Back-projection of one angle (view)

Parameters
prjPointer to source projection data.
idataPointer to output image data of size dim*dim (upper left corner).
dimImage dimension; must be an even number
viewProjection view (in order to get correct sine from tables)
viewNrNumber of projection views (sinogram rows) (to get correct sine from tables)
rayNrNumber of rays (bins, columns)
sinBPre-computed sine table for reprojection.
sinBrotPre-computed sine table for reprojection with rotation.
offsXx offset in pixels; shift_x/pixsize.
offsYy offset in pixels; shift_x/pixsize.
bpZoomZoom

Definition at line 359 of file reprojection.c.

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}

Referenced by mrp(), and trmrp().

◆ viewReprojection()

void viewReprojection ( float * idata,
float * sdata,
int view,
int dim,
int viewNr,
int rayNr,
float * sinB,
float * sinBrot,
float offsX,
float offsY,
float bpZoom )

Reprojection of one angle (view)

Parameters
idataPointer to source input image data of size dim*dim
sdataPointer to preallocated output sinogram projection view (angle, row)
viewProjection view (in order to get correct sine from tables)
dimImage dimension; must be an even number
viewNrNumber of projection views (sinogram rows) (to get correct sine from tables)
rayNrNumber of rays (bins, columns)
sinBPre-computed sine table for reprojection.
sinBrotPre-computed sine table for reprojection with rotation.
offsXx offset in pixels; shift_x/pixsize.
offsYy offset in pixels; shift_x/pixsize.
bpZoomZoom

Definition at line 216 of file reprojection.c.

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}

Referenced by imgReprojection(), mrp(), reprojection(), and trmrp().