TPCCLIB
Loading...
Searching...
No Matches
libtpcrec.h File Reference

Header file for libtpcrec. More...

#include "tpcclibConfig.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <float.h>
#include <ctype.h>
#include <time.h>
#include "libtpcmisc.h"
#include "libtpcimgio.h"

Go to the source code of this file.

Data Structures

struct  ELLIPSE
 Ellipse on two dimensional plane. More...
struct  PRMAT
struct  RADON

Enumerations

enum  { ELLIPSE_STATUS_UNINITIALIZED , ELLIPSE_STATUS_INITIALIZED , ELLIPSE_STATUS_OCCUPIED , ELLIPSE_STATUS_ERROR }
enum  {
  FBP_FILTER_NONE , FBP_FILTER_RAMP , FBP_FILTER_BUTTER , FBP_FILTER_HANN ,
  FBP_FILTER_HAMM , FBP_FILTER_PARZEN , FBP_FILTER_SHEPP
}
enum  {
  PRMAT_STATUS_UNINITIALIZED , PRMAT_STATUS_INITIALIZED , PRMAT_STATUS_BS_OCCUPIED , PRMAT_STATUS_LU_OCCUPIED ,
  PRMAT_STATUS_PR_OCCUPIED , PRMAT_STATUS_ERROR
}
enum  { PRMAT_TYPE_ECAT931 , PRMAT_TYPE_GE , PRMAT_TYPE_NA }
enum  { PRMAT_DMODE_01 , PRMAT_DMODE_LOI , PRMAT_DMODE_EA , PRMAT_DMODE_NN }
enum  { RADON_STATUS_UNINITIALIZED , RADON_STATUS_INITIALIZED , RADON_STATUS_OCCUPIED , RADON_STATUS_ERROR }

Functions

void ellipseInit (ELLIPSE *ell)
void ellipseEmpty (ELLIPSE *ell)
void ellipseInfo (ELLIPSE *ell)
int ellipseAllocate (ELLIPSE *ell, int imgDim)
int ellipseSetFromParams (ELLIPSE *ell, int imgDim, float *semis, float *cent, float incli, float val)
int ellipseReadEllipse (FILE *fp, ELLIPSE *ell)
int ellipseSaveEllipse (ELLIPSE *ell, FILE *fp)
float ellipseGetMajor (ELLIPSE *ell)
float ellipseGetMinor (ELLIPSE *ell)
float ellipseGetCenterX (ELLIPSE *ell)
float ellipseGetCenterY (ELLIPSE *ell)
float ellipseGetInclination (ELLIPSE *ell)
int ellipseGetImgSize (ELLIPSE *ell)
int ellipseGetValue (ELLIPSE *ell)
int ** ellipseGetArray (ELLIPSE *ell)
int ellipseIsInside (ELLIPSE *ell, int row, int col)
int fbp (float *sinogram, int rays, int views, int dim, int filter, float cutoff, float *image)
int imgFBP (IMG *scn, IMG *img, int imgDim, float zoom, int filter, float cutoff, float shiftX, float shiftY, float rotation, int verbose)
int fbpMakeFilter (float *sinFFT, float *cosFFT, float cutoff, int filter, int lenFFT, int views, float *fbpFilter, int verbose)
void fbp_fft_bidir_complex_radix2 (float *real, float *imag, int direct, int n, float *sine, float *cosine)
void fbp_back_proj (float *prj, float *imgCorner, int imgDim, int view, int views, int rays, float offsX, float offsY, float *sinB, float *sinBrot)
void fbp_back_proj_round (float *prj, float *imgOrigin, int imgDim, int view, int views, int rays, float offsX, float offsY, float bpZoom, float *sinB, float *sinBrot)
int imgMRP (IMG *scn, IMG *img, int imgDim, float zoom, float shiftX, float shiftY, float rotation, int maxIterNr, int skipPriorNr, float beta, int maskDim, int osSetNr, int verbose)
void mrpUpdate (float *coef, float *img, float *oimg, int n)
void mrpProjectionCorrection (float *measured, float *proj, float *correct, int os_sets, int rays, int views)
int mrp (float *sinogram, int rays, int views, int iter, int os_sets, int maskdim, float zoom, float beta, int skip_prior, int dim, float *image, int verbose)
void do_prior (float *img, float beta, float *med_coef, int dim, float small, int maskdim, float *maxm)
float med9 (float *inp, int dim)
float med21 (float *inp, int dim)
void prmatInit (PRMAT *mat)
void prmatEmpty (PRMAT *mat)
int prmatAllocate (PRMAT *mat, int set, unsigned int rows, unsigned int *coords)
unsigned int prmatGetNV (PRMAT *mat)
unsigned int prmatGetNB (PRMAT *mat)
unsigned int prmatGetID (PRMAT *mat)
unsigned int prmatGetPIX (PRMAT *mat)
unsigned int prmatGetPixCoord (PRMAT *mat, int row)
unsigned int prmatGetRays (PRMAT *mat, int row)
unsigned int prmatGetBinView (PRMAT *mat, int row, int ind)
unsigned int prmatGetRows (PRMAT *mat)
unsigned int prmatGetPixels (PRMAT *mat, int row)
unsigned int prmatGetCoord (PRMAT *mat, int row, int pix)
unsigned int prmatGetXCoord (PRMAT *mat, int row, int pix)
unsigned int prmatGetYCoord (PRMAT *mat, int row, int pix)
float prmatGetFactor (PRMAT *mat, int row, int pix)
float prmatGetMajor (PRMAT *mat)
float prmatGetMinor (PRMAT *mat)
float prmatGetMin (PRMAT *mat)
float prmatGetMax (PRMAT *mat)
float prmatGetFactorSum (PRMAT *mat)
float prmatGetFactorSqrSum (PRMAT *mat, int row)
int prmatReadMatrix (char *fname, PRMAT *mat)
int prmatSaveMatrix (PRMAT *mat)
void radonEmpty (RADON *radtra)
int radonSet (RADON *radtra, int mode, int imgDim, int viewNr, int binNr)
int radonGetMO (RADON *radtra)
int radonGetID (RADON *radtra)
int radonGetNV (RADON *radtra)
int radonGetNB (RADON *radtra)
float radonGetSD (RADON *radtra)
int radonGetHI (RADON *radtra)
int radonGetCB (RADON *radtra)
float radonGetSin (RADON *radtra, int nr)
int radonFwdTransform (RADON *radtra, int set, int setNr, float *imgdata, float *scndata)
int radonFwdTransformEA (RADON *radtra, int set, int setNr, float *imgdata, float *scndata)
int radonFwdTransformSA (RADON *radtra, int set, int setNr, float *imgdata, float *scndata)
int radonFwdTransformPRM (PRMAT *mat, int set, int setNr, float *imgdata, float *scndata)
int radonBackTransform (RADON *radtra, int set, int setNr, float *scndata, float *imgdata)
int radonBackTransformEA (RADON *radtra, int set, int setNr, float *scndata, float *imgdata)
int radonBackTransformSA (RADON *radtra, int set, int setNr, float *imgdata, float *scndata)
int radonBackTransformPRM (PRMAT *mat, int set, int setNr, float *scndata, float *imgdata)
int radonSetBases (RADON *radtra, ELLIPSE *elli, PRMAT *mat)
int radonSetBasesEA (RADON *radtra, ELLIPSE *elli, PRMAT *mat)
int radonSetLUT (RADON *radtra, ELLIPSE *elli, PRMAT *mat)
int radonSetLORS (RADON *radtra, ELLIPSE *elli, PRMAT *mat)
void recSinTables (int views, float *sinB, float *sinBrot, float rotation)
void recInterpolateSinogram (float *srcsino, float *newsino, int srcrays, int newrays, int views)
int bit_rev_int (int x, int n)
void set_os_set (int os_sets, int *set_seq)
int recGetStatistics (float *buf, int n, float *osum, float *omin, float *omax, int skip_zero_mins)
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)
int trmrp (float *bla, float *tra, int dim, float *image, int iter, int sets, int rays, int views, int maskdim, float zoom, float beta, float axial_fov, float sample_distance, int skip_prior, int osl, float shiftX, float shiftY, float rotation, int verbose)

Variables

int ELLIPSE_TEST
 Drive in test mode if not 0.
int ELLIPSE_VERBOSE
 Drive in verbose mode if not 0.
int PRMAT_TEST
 If not 0 drive in test mode.
int PRMAT_VERBOSE
 If not 0 drive in verbose mode.
int RADON_TEST
 Drive in test mode if not 0.
int RADON_VERBOSE
 Drive in verbose mode if not 0.

Detailed Description

Header file for libtpcrec.

Author
Vesa Oikonen

Definition in file libtpcrec.h.

Enumeration Type Documentation

◆ anonymous enum

anonymous enum

Definition at line 147 of file libtpcrec.h.

147 {PRMAT_STATUS_UNINITIALIZED, PRMAT_STATUS_INITIALIZED,
148 PRMAT_STATUS_BS_OCCUPIED, PRMAT_STATUS_LU_OCCUPIED, PRMAT_STATUS_PR_OCCUPIED,
149 PRMAT_STATUS_ERROR
150};

◆ anonymous enum

anonymous enum

Definition at line 82 of file libtpcrec.h.

82 {FBP_FILTER_NONE, FBP_FILTER_RAMP, FBP_FILTER_BUTTER, FBP_FILTER_HANN,
83 FBP_FILTER_HAMM, FBP_FILTER_PARZEN, FBP_FILTER_SHEPP
84};

◆ anonymous enum

anonymous enum

Definition at line 246 of file libtpcrec.h.

246 {RADON_STATUS_UNINITIALIZED, RADON_STATUS_INITIALIZED,
247 RADON_STATUS_OCCUPIED, RADON_STATUS_ERROR
248};

◆ anonymous enum

anonymous enum

Definition at line 152 of file libtpcrec.h.

152{PRMAT_DMODE_01, PRMAT_DMODE_LOI, PRMAT_DMODE_EA, PRMAT_DMODE_NN};

◆ anonymous enum

anonymous enum

Definition at line 151 of file libtpcrec.h.

151{PRMAT_TYPE_ECAT931, PRMAT_TYPE_GE, PRMAT_TYPE_NA};

◆ anonymous enum

anonymous enum

Definition at line 26 of file libtpcrec.h.

26 {ELLIPSE_STATUS_UNINITIALIZED, ELLIPSE_STATUS_INITIALIZED,
27 ELLIPSE_STATUS_OCCUPIED, ELLIPSE_STATUS_ERROR};

Function Documentation

◆ bit_rev_int()

int bit_rev_int ( int x,
int n )
extern

Bit-reverse for integers in a list, used by set_os_set().

See also
set_os_set()
Returns
the converted integer.
Parameters
xInteger to bit-convert.
nNumber of elements.

Definition at line 77 of file recutil.c.

82 {
83 unsigned char c=(char)x;
84 switch(n) {
85 case 4:
86 c = (c&1)<<1 | (c&2)>>1;
87 break;
88 case 8:
89 c = ((c&1) << 2) | (c&2) | ((c&4) >> 2);
90 break;
91 case 16:
92 c = ((c&1) << 3) | ((c&2) << 1) | ((c&4) >> 1) | ((c&8) >> 3);
93 break;
94 case 32:
95 c = ((c&1)<<4) | ((c&2)<<2) | (c&4) | ((c&8)>>2) | ((c&16)>>4);
96 break;
97 case 64:
98 c = ((c&1)<<5) | ((c&2)<<3) | ((c&4)<<1) | ((c&8)>>1) | ((c&16)>>3) |
99 ((c&32)>>5);
100 break;
101 case 128:
102 c = ((c&1)<<6) | ((c&2)<<4) | ((c&4)<<2) | (c&8) | ((c&16)>>2) |
103 ((c&32)>>4) | ((c&64)>>6);
104 break;
105 default: break;
106 }
107 return((int)c);
108}

Referenced by set_os_set().

◆ do_prior()

void do_prior ( float * img,
float beta,
float * med_coef,
int dim,
float small,
int maskdim,
float * maxm )
extern

Do prior in MRP reconstruction.

Parameters
imgFloat array of size dim*dim containing the image data.
betaBeta value.
med_coefMedian coefficients, an array of size dim*dim, calculated here.
dimImage dimensions.
smallLimit for too small values.
maskdimMask dimensions; 3 or 5.
maxmMax median coefficient; enter NULL if not needed.

Definition at line 77 of file mrprior.c.

92 {
93 int i, j;
94 float *iptr, *mptr, med, f, mmax=0.0;
95 float one_minus_beta=1.0-beta;
96
97 //printf("do_prior(%d, %d)\n", dim, maskdim); fflush(stdout);
98 for(i=0; i<dim*dim; i++) med_coef[i]=0.0;
99
100 if(maskdim==3) {
101 iptr=img+dim+1;
102 mptr=med_coef+dim+1;
103 for(j=1; j<dim-1; j++) {
104 for(i=1; i<dim-1; i++) {
105 if(*iptr<=small) {
106 *mptr=0.0;
107 } else {
108 med=med9(iptr, dim);
109 if(med==0.0) {
110 *mptr=0.0;
111 } else {
112 f=med/(beta*(*iptr) + one_minus_beta*med);
113 if(f>1.0E-08) *mptr=f; else *mptr=0.0;
114 }
115 }
116 if(*mptr>mmax) mmax=*mptr;
117 iptr++; mptr++;
118 }
119 iptr+=2; mptr+=2;
120 }
121 if(maxm!=NULL) *maxm=mmax;
122 //printf("out from do_prior()\n"); fflush(stdout);
123 return;
124 }
125
126 if(maskdim==5) {
127 iptr=img+2*dim+2;
128 mptr=med_coef+2*dim+2;
129 for(j=2; j<dim-2; j++) {
130 for(i=2; i<dim-2; i++) {
131 if(*iptr<=small) {
132 *mptr=0.0;
133 } else {
134 med=med21(iptr, dim);
135 if(med==0.0) {
136 *mptr=0.0;
137 } else {
138 f=med/(beta*(*iptr) + one_minus_beta*med);
139 if(f>1.0E-08) *mptr=f; else *mptr=0.0;
140 }
141 }
142 if(*mptr>mmax) mmax=*mptr;
143 iptr++; mptr++;
144 }
145 iptr+=4; mptr+=4;
146 }
147 if(maxm!=NULL) *maxm=mmax;
148 //printf("out from do_prior()\n"); fflush(stdout);
149 return;
150 }
151}
float med21(float *inp, int dim)
Definition mrprior.c:49
float med9(float *inp, int dim)
Definition mrprior.c:15

Referenced by mrp(), and trmrp().

◆ ellipseAllocate()

int ellipseAllocate ( ELLIPSE * ell,
int imgDim )
extern

Allocates memory for ELLIPSE data. Normally used only in SET-functions.

Precondition
ell is initialized && imgDim is positive
Postcondition
memory is allocated for ELLIPSE structure.
Parameters
ellpointer to ellipse for which the allocation is done.
imgDimsize of the image plane on which the ellipse is to be done.
Returns
0 if ok.

Definition at line 94 of file ellipse.c.

95{
96 int i;
97 if(ELLIPSE_VERBOSE) printf("ELLIPSE:ellipseAllocate(*ell,%i) \n",imgDim);
98
99 /*check the arguments*/
100 if(ell->status==ELLIPSE_STATUS_UNINITIALIZED) return(1);
101 if(imgDim<1 || imgDim>4096) return(2);
102
103 //allocate memory
104 ell->ellipseptr=(int**)calloc(imgDim,sizeof(int*));
105 for(i=0;i<imgDim;i++){
106 ell->ellipseptr[i]=(int*)calloc(imgDim,sizeof(int));
107 }
108 return(0);
109}
int ELLIPSE_VERBOSE
Drive in verbose mode if not 0.
Definition ellipse.c:9
char status
ellipse status.
Definition libtpcrec.h:39
int ** ellipseptr
Definition libtpcrec.h:55

Referenced by ellipseSetFromParams().

◆ ellipseEmpty()

void ellipseEmpty ( ELLIPSE * ell)
extern

Frees the memory allocated for ellipse. All data is cleared.

Postcondition
ellipse is emptied.
Parameters
ellpointer to ellipse to be emptied.

Definition at line 47 of file ellipse.c.

48{
49 if(ELLIPSE_VERBOSE) printf("ELLIPSE: ellipseEmpty(). \n");
50
51 //if ell is already empty
52 if(ell->status<ELLIPSE_STATUS_OCCUPIED) return;
53
54 //free the memory occupied by ellipse array
55 free(ell->ellipseptr);
56
57 //Init the information again
58 ell->semiaxis[0]=ell->semiaxis[1]=0.;
59 ell->center[0]=ell->center[1]=0.;
60 ell->inclination=0.;
61 ell->imageDim=0;
62 ell->value=0;
63 /*Init the ellipse array*/
64 ell->ellipseptr=(int**)NULL;
65
66 ell->status=ELLIPSE_STATUS_INITIALIZED;
67}
float value
Value inside the ellipse.
Definition libtpcrec.h:57
float inclination
Inclination (degrees).
Definition libtpcrec.h:48
float semiaxis[2]
Definition libtpcrec.h:43
int imageDim
Size of the image plane on which the ellipse is defined.
Definition libtpcrec.h:50
float center[2]
Definition libtpcrec.h:46

Referenced by ellipseReadEllipse().

◆ ellipseGetArray()

int ** ellipseGetArray ( ELLIPSE * ell)
extern

Returns the ellipse array of the given ellipse.

Ellipse array contains n x n items, single item is one if it is inside the ellipse and zero otherwise. Coordinates on a two dimensional plane are numbered from upper left corner.

Parameters
ellpointer to ellipse.
Returns
the ellipse array of the given ellipse.

Definition at line 339 of file ellipse.c.

340{
341 if(ELLIPSE_VERBOSE) printf("ELLIPSE:ellipseGetArray(). \n");
342 if(ell->status==ELLIPSE_STATUS_UNINITIALIZED) return((int**)-1);
343 return(ell->ellipseptr);
344}

◆ ellipseGetCenterX()

float ellipseGetCenterX ( ELLIPSE * ell)
extern

Returns the center x-coordinate of the ellipse.

Parameters
ellpointer to ellipse.
Returns
the center x-coordinate of the given ellipse, some negative value if ERROR.

Definition at line 277 of file ellipse.c.

278{
279 if(ELLIPSE_VERBOSE) printf("ELLIPSE:ellipseGetCenterX(). \n");
280 if(ell->status==ELLIPSE_STATUS_UNINITIALIZED) return(-1);
281 return(ell->center[0]);
282}

◆ ellipseGetCenterY()

float ellipseGetCenterY ( ELLIPSE * ell)
extern

Returns the center y-coordinate of the ellipse.

Parameters
ellpointer to ellipse.
Returns
the center y-coordinate of the given ellipse, some negative value if ERROR.

Definition at line 289 of file ellipse.c.

290{
291 if(ELLIPSE_VERBOSE) printf("ELLIPSE:ellipseGetCenterY(). \n");
292 if(ell->status==ELLIPSE_STATUS_UNINITIALIZED) return(-1);
293 return(ell->center[1]);
294}

◆ ellipseGetImgSize()

int ellipseGetImgSize ( ELLIPSE * ell)
extern

Returns the size of the image plane on which the ellipse is drawn.

Parameters
ellpointer to ellipse.
Returns
the size of the image plane of the given ellipse, some negative value if ERROR.

Definition at line 312 of file ellipse.c.

313{
314 if(ELLIPSE_VERBOSE) printf("ELLIPSE:ellipseGetImgSize(). \n");
315 if(ell->status==ELLIPSE_STATUS_UNINITIALIZED) return(-1);
316 return(ell->imageDim);
317}

◆ ellipseGetInclination()

float ellipseGetInclination ( ELLIPSE * ell)
extern

Returns the inclination of the ellipse.

Parameters
ellpointer to ellipse.
Returns
the inclination of the given ellipse, some negative value if ERROR.

Definition at line 300 of file ellipse.c.

301{
302 if(ELLIPSE_VERBOSE) printf("ELLIPSE:ellipseGetInclination(). \n");
303 if(ell->status==ELLIPSE_STATUS_UNINITIALIZED) return(-1);
304 return(ell->inclination);
305}

◆ ellipseGetMajor()

float ellipseGetMajor ( ELLIPSE * ell)
extern

Returns the major semiaxe of the ellipse.

Parameters
ellpointer to ellipse.
Returns
the major semiaxe of the given ellipse, some negative value if ERROR.

Definition at line 254 of file ellipse.c.

255{
256 if(ELLIPSE_VERBOSE) printf("ELLIPSE:ellipseGetMajor(). \n");
257 if(ell->status==ELLIPSE_STATUS_UNINITIALIZED) return(-1);
258 return(ell->semiaxis[0]);
259}

Referenced by radonSetBases(), and radonSetBasesEA().

◆ ellipseGetMinor()

float ellipseGetMinor ( ELLIPSE * ell)
extern

Returns the minor semiaxe of the ellipse.

Parameters
ellpointer to ellipse.
Returns
the minor semiaxe of the given ellipse, some negative value if ERROR.

Definition at line 265 of file ellipse.c.

266{
267 if(ELLIPSE_VERBOSE) printf("ELLIPSE:ellipseGetMinor(). \n");
268 if(ell->status==ELLIPSE_STATUS_UNINITIALIZED) return(-1);
269 return(ell->semiaxis[1]);
270}

Referenced by radonSetBases(), and radonSetBasesEA().

◆ ellipseGetValue()

int ellipseGetValue ( ELLIPSE * ell)
extern

Returns the value of the pixels inside the ellipse.

Parameters
ellpointer to ellipse.
Returns
the value of the pixels inside the ellipse.

Definition at line 323 of file ellipse.c.

324{
325 if(ELLIPSE_VERBOSE) printf("ELLIPSE:ellipseGetValue(). \n");
326 if(ell->status==ELLIPSE_STATUS_UNINITIALIZED) return(-1);
327 return(ell->value);
328}

◆ ellipseInfo()

void ellipseInfo ( ELLIPSE * ell)
extern

Prints the information of the ellipse to the screen.

Parameters
ellpointer to ellipse to be printed.

Definition at line 73 of file ellipse.c.

74{
75 printf("ellipseInfo()\n");
76 if(ell->status==ELLIPSE_STATUS_UNINITIALIZED){
77 printf("Ellipse data not initialized.\n"); return;
78 }
79 printf("Semiaxis: (%.5f,%.5f)\n",ell->semiaxis[0], ell->semiaxis[1]);
80 printf("Center: (%.2f,%.2f)\n",ell->center[0],ell->center[1]);
81 printf("Inclination (degrees): %f\n",ell->inclination);
82 printf("Image dimension: %i\n",ell->imageDim);
83 printf("Value: %f\n",ell->value);
84}

◆ ellipseInit()

void ellipseInit ( ELLIPSE * ell)
extern

Initializes ELLIPSE datatype for use. To be used before any use of ELLIPSE type variables.

Postcondition
ellipse is initialized.
Parameters
ellpointer to ellipse to be initialized.

Definition at line 23 of file ellipse.c.

24{
25 if(ELLIPSE_VERBOSE) printf("ELLIPSE: ellipseInit(). \n");
26
27 /*Init the information on ellipse.*/
28 //buffer ell to contain zero
29 memset(ell, 0, sizeof(ELLIPSE));
30 ell->status=ELLIPSE_STATUS_INITIALIZED;
31 ell->semiaxis[0]=ell->semiaxis[1]=0.;
32 ell->center[0]=ell->center[1]=0.;
33 ell->inclination=0.;
34 ell->imageDim=0;
35 ell->value=0;
36
37 /*Init the ellipse array*/
38 ell->ellipseptr=(int**)NULL;
39}
Ellipse on two dimensional plane.
Definition libtpcrec.h:37

◆ ellipseIsInside()

int ellipseIsInside ( ELLIPSE * ell,
int row,
int col )
extern

Tests whether the given pixel is inside the given ellipse or not.

Returns
one if the given pixel is inside the given ellipse zero otherwise, some negative value if ERROR.
Parameters
ellellipse on which the testing is to be done.
Precondition
ell is initialized && 0<=row<=imgDim-1 && 0<=col<=imgDim-1.
Parameters
rowrow coordinate of a pixel.
colcolumn coordinate of a pixel.

Definition at line 352 of file ellipse.c.

360 {
361 //no checking on parameters to accelerate use inside a loop
362 return(ell->ellipseptr[row][col]);
363}

Referenced by radonSetBases(), radonSetBasesEA(), and radonSetLUT().

◆ ellipseReadEllipse()

int ellipseReadEllipse ( FILE * fp,
ELLIPSE * ell )
extern

Reads one ellipse from the given file to the given ELLIPSE structure.

A coordinate file contains the parameters of the ellipses in one line in the following order: Coordinate 1: v the additive intensity value of the ellipse Coordinate 2: a the length of the horizontal semi-axis of the ellipse Coordinate 3: b the length of the vertical semi-axis of the ellipse Coordinate 4: x the x-coordinate of the center of the ellipse Coordinate 5: y the y-coordinate of the center of the ellipse Coordinate 6: p the angle (in degrees) between the horizontal semi-axis of the ellipse and the x-axis of the image
Coordinate 7: d the image dimension

Postcondition
An ellipse is read from the file fname.
Returns
0 if ok 1 if there were no more ellipses.
Parameters
fpA pointer to open file containing ellipse(s) in correct format.
ellpointer to ELLIPSE structure where the read ellipse is to be set.
Precondition
ell is initialized.

Definition at line 198 of file ellipse.c.

204 {
205 float v, incli, semiaxis[2], center[2], imgDim;
206 int ret=0;
207
208 if(ELLIPSE_VERBOSE) printf("ellipseReadEllipse() \n");
209
210 if(fread(&v,sizeof(float),1,fp)==0) {fclose(fp); return(2);}
211 if(fread(&semiaxis[0],sizeof(float),1,fp)==0) {fclose(fp); return(2);}
212 if(fread(&semiaxis[1],sizeof(float),1,fp)==0) {fclose(fp); return(2);}
213 if(fread(&center[0],sizeof(float),1,fp)==0) {fclose(fp); return(2);}
214 if(fread(&center[1],sizeof(float),1,fp)==0) {fclose(fp); return(2);}
215 if(fread(&incli,sizeof(float),1,fp)==0) {fclose(fp); return(2);}
216 if(fread(&imgDim,sizeof(float),1,fp)==0) {fclose(fp); return(2);}
217
218 if(feof(fp)) return 1;
219
220 //create the ellipse
221 ret=ellipseSetFromParams(ell, imgDim, semiaxis, center, incli,v);
222 if(ret){ ellipseEmpty(ell); return ret;}
223 return 0;
224}
int ellipseSetFromParams(ELLIPSE *ell, int imgDim, float *semis, float *cent, float incli, float val)
Definition ellipse.c:119
void ellipseEmpty(ELLIPSE *ell)
Definition ellipse.c:47

◆ ellipseSaveEllipse()

int ellipseSaveEllipse ( ELLIPSE * ell,
FILE * fp )
extern

Adds the given ellipse to the file.

Postcondition
ellipse is saved in the file called fname.
Returns
0 if OK.
Parameters
ellPointer to the ellipse to be saved.
fpOpen file for saving.

Definition at line 230 of file ellipse.c.

235 {
236 if(ELLIPSE_VERBOSE) printf("ellipseSaveEllipse()\n");
237
238 // Put ellipse in the file.
239 fwrite(&(ell->value),sizeof(float),1,fp);
240 fwrite(&(ell->semiaxis[0]),sizeof(float),1,fp);
241 fwrite(&(ell->semiaxis[1]),sizeof(float),1,fp);
242 fwrite(&(ell->center[0]),sizeof(float),1,fp);
243 fwrite(&(ell->center[1]),sizeof(float),1,fp);
244 fwrite(&(ell->inclination),sizeof(float),1,fp);
245 fwrite(&(ell->imageDim),sizeof(float),1,fp);
246
247 return(0);
248}

◆ ellipseSetFromParams()

int ellipseSetFromParams ( ELLIPSE * ell,
int imgDim,
float * semis,
float * cent,
float incli,
float val )
extern

Sets the ellipse according to given coordinates and image dimension.

Note
The origin is in the middle.
Postcondition
ellipse is set.
Returns
0 if ok.
Parameters
ellpointer to ellipse for which the setting is to be done.
Precondition
ell is initialized.
Parameters
imgDimsize of the image plane.
Precondition
imgDim is positive.
Parameters
semismajor and minor semiaxis of the ellipse.
Precondition
semis[i] are positive.
Parameters
centcenter of the ellipse.
Precondition
-imgDim/2<=cent[i]<=imgDim/2.
Parameters
incliinclination of the ellipse.
valvalue inside the ellipse.

Definition at line 119 of file ellipse.c.

136 {
137 float d, x, y, inclination;
138 int row, col;
139
140 /*check the arguments*/
141 if(ell->status==ELLIPSE_STATUS_UNINITIALIZED) return(1);
142 if(imgDim<1 || imgDim>4096) return(2);
143 if(0>semis[0] || 0>semis[1]) return(3);
144 if(-(float)imgDim/2.>cent[0] || (float)imgDim/2.<cent[0]) return(4);
145 if(-(float)imgDim/2.>cent[1] || (float)imgDim/2.<cent[1]) return(5);
146
147 //allocate memory for ellipse
148 ellipseAllocate(ell,imgDim);
149
150 //set the information on ellipse
151 ell->semiaxis[0]=semis[0];
152 ell->semiaxis[1]=semis[1];
153 ell->center[0]=cent[0];
154 ell->center[1]=cent[1];
155 ell->inclination=incli;
156 ell->imageDim=imgDim;
157 ell->value=val;
158
159 //set inclination ratio for setting inclination approximately
160 inclination= -(float)(incli/90.);
161
162 //set ellipse array according to given arguments
163 for(row=0; row<imgDim; row++) {
164 for(col=0; col<imgDim; col++) {
165 // the y-coordinate of row in coordinates where origin is set in the middle
166 y=(float)imgDim*0.5 - (float)row - cent[1];
167 /* the x-coordinate of column in coordinates where origin is set in
168 the middle and inclination is added */
169 x=(float)col - (float)imgDim*0.5 - (cent[0] + inclination*y);
170 d=(x*x)/(semis[0]*semis[0]) + (y*y)/(semis[1]*semis[1]);
171 //if this pixel is inside the ellipse
172 if(d<1.0) {
173 //put 1 in place (row,col)
174 ell->ellipseptr[row][col]=1;
175 }
176 }//END OF COL-LOOP
177 }//END OF ROW-LOOP
178 return(0);
179}
int ellipseAllocate(ELLIPSE *ell, int imgDim)
Definition ellipse.c:94

Referenced by ellipseReadEllipse().

◆ fbp()

int fbp ( float * sinogram,
int rays,
int views,
int dim,
int filter,
float cutoff,
float * image )
extern

Filtered back-projection (FBP) reconstruction of one 2D data matrix given as an array of floats.

Image cannot be zoomed (zoom=1), rotated, or shifted.

See also
imgFBP, reprojection
Returns
Returns 0 if ok.
Parameters
sinogramPointer to float array containing rays*views sinogram values.
raysNr of rays (bins or columns) in sinogram data.
viewsNr of views (rows) in sinogram data.
dimImage x and y dimensions; must be an even number, preferrably the same as number of rays, but there is no reason for it to be any larger than that.
filterFilter: 0=None, 1=Ramp, 2=Butter, 3=Hann, 4=Hamm, 5=Parzen, 6=Shepp.
cutoffNoise cut-off (for example 0.3).
imagePointer to pre-allocated image data; size must be at least dim*dim.

Definition at line 20 of file fbp.c.

37 {
38 if(sinogram==NULL || rays<2 || views<2 || dim<2 || image==NULL) return(1);
39 if(dim%2) return(2);
40 if(cutoff<0.05 || cutoff>0.99) return(2);
41
42 int i, n;
43
44 /* Set FFT array length */
45 int lenFFT=(2*rays)-1;
46 if(lenFFT<256) lenFFT=256; else if(lenFFT<512) lenFFT=512;
47 else if(lenFFT<1024) lenFFT=1024; else if(lenFFT<2048) lenFFT=2048;
48 else if(lenFFT<4096) lenFFT=4096; else if(lenFFT<8192) lenFFT=8192;
49 else if(lenFFT<16384) lenFFT=16384; else return(3);
50
51 /* Set image pixel values to zero */
52 for(i=0; i<dim*dim; i++) image[i]=0.0;
53
54 /* Allocate memory and set data pointers */
55 float *locData=
56 calloc((2*lenFFT + (lenFFT+1) + 5*lenFFT/4 + 3*views/2), sizeof(float));
57 if(locData==NULL) return(4);
58 float *real, *imag;
59 float *sinFFT, *cosFFT, *fbpFilter, *sinBP;
60 real=locData; imag=real+lenFFT;
61 fbpFilter=imag+lenFFT;
62 sinFFT=fbpFilter+(lenFFT+1);
63 cosFFT=sinFFT+lenFFT/4; // sinFFT and cosFFT overlap on purpose
64 sinBP=sinFFT+5*lenFFT/4;
65
66 /* Pre-compute the sine and cosine tables for FFT */
67 {
68 double df, dg;
69 dg=(double)M_PI*2.0/(double)lenFFT;
70 for(i=0, df=0.0; i<5*lenFFT/4; i++, df+=dg) sinFFT[i]=(float)sin(df);
71 }
72 /* Compute reconstruction filter coefficients */
73 n=fbpMakeFilter(sinFFT, cosFFT, cutoff, filter, lenFFT, views, fbpFilter, 0);
74 if(n) {free(locData); return(100+n);}
75 /* Compute the sine tables for back-projection */
76 recSinTables(views, sinBP, NULL, 0.0);
77
78 /* Process each sinogram row (projection, view), two at the same time */
79 for(int pi=0; pi<views; pi+=2) {
80 /* Copy the data to real and imag arrays */
81 for(i=0; i<rays; i++) real[i]=sinogram[pi*rays+i];
82 for(i=0; i<rays; i++) imag[i]=sinogram[pi*rays+rays+i];
83 for(i=rays; i<lenFFT; i++) real[i]=imag[i]=0.0; // zero padding
84 /* Forward FFT */
85 fbp_fft_bidir_complex_radix2(real, imag, 1, lenFFT, sinFFT, cosFFT);
86 /* Filter */
87 for(i=0; i<lenFFT; i++) real[i]*=fbpFilter[i];
88 for(i=0; i<lenFFT; i++) imag[i]*=fbpFilter[i];
89 /* Inverse FFT */
90 fbp_fft_bidir_complex_radix2(real, imag, -1, lenFFT, sinFFT, cosFFT);
91 /* Back-projection */
92 fbp_back_proj_round(real, image+dim*(dim/2-1)+dim/2, dim, pi, views, rays,
93 0.0, 0.0, 1.0, sinBP, sinBP);
94 fbp_back_proj_round(imag, image+dim*(dim/2-1)+dim/2, dim, pi+1, views, rays,
95 0.0, 0.0, 1.0, sinBP, sinBP);
96 } // next two projections
97
98 free(locData);
99 return(0);
100}
int fbpMakeFilter(float *sinFFT, float *cosFFT, float cutoff, int filter, int lenFFT, int views, float *fbpFilter, int verbose)
Definition fbp.c:382
void fbp_fft_bidir_complex_radix2(float *real, float *imag, int direct, int n, float *sine, float *cosine)
Definition fbp.c:512
void fbp_back_proj_round(float *prj, float *imgOrigin, int imgDim, int view, int views, int rays, float offsX, float offsY, float bpZoom, float *sinB, float *sinBrot)
Definition fbp.c:655
void recSinTables(int views, float *sinB, float *sinBrot, float rotation)
Definition recutil.c:12

◆ fbp_back_proj()

void fbp_back_proj ( float * prj,
float * imgCorner,
int imgDim,
int view,
int views,
int rays,
float offsX,
float offsY,
float * sinB,
float * sinBrot )
extern

Backprojection with all projection profiles overlapping the image area.

Parameters
prjpointer to projection data
imgCornerpointer to destination image (upper left corner)
imgDimimage dimension
viewprojection view number
viewsnumber of projection views
raysnumber of rays
offsXx offset
offsYy offset
sinBSine tables
sinBrotSinBrot array

Definition at line 599 of file fbp.c.

620 {
621 float si, co, tleft, sir, cor, rayCenter, dif;
622 float t; /* distance between projection ray and origin */
623 int x, y, halfDim, leftX, rightTopLimit, yBottom, ti;
624
625 float *imgp=imgCorner;
626
627 halfDim=imgDim/2;
628 leftX=-halfDim;
629 rightTopLimit=halfDim-1;
630 yBottom=-halfDim;
631 rayCenter=0.5*(float)rays;
632 si=sinB[view]; /* Sine and cosine for x,y-shift */
633 co=sinB[view+views/2];
634 sir=sinBrot[view]; /* Sine and cosine for backprojection */
635 cor=sinBrot[view+views/2];
636 x=leftX; y=rightTopLimit;
637 tleft= rayCenter - (float)y*sir - offsY*si + ((float)(x+1))*cor + offsX*co;
638 for(; y>=yBottom; y--) {
639 t=tleft;
640 for(x=leftX; x<=rightTopLimit; x++, t+=cor) {
641 ti=(int)t; dif=t-(float)ti;
642 //ti=(int)(t+0.5); *imgp++ += prj[ti];
643 *imgp++ += prj[ti] + (prj[ti+1]-prj[ti])*dif;
644 }
645 tleft+=sir;
646 }
647}

Referenced by imgFBP().

◆ fbp_back_proj_round()

void fbp_back_proj_round ( float * prj,
float * imgOrigin,
int imgDim,
int view,
int views,
int rays,
float offsX,
float offsY,
float bpZoom,
float * sinB,
float * sinBrot )
extern

Backprojection with projection profiles NOT overlapping the image area.

The corner pixels are left unchanged.

Parameters
prjpointer to projection data
imgOriginpointer to image origin (center)
imgDimimage dimension
viewprojection view number
viewsnumber of projection views
raysnumber of rays
offsXx offset in pixels
offsYy offset in pixels
bpZoomZoom
sinBSine tables
sinBrotsinBrot array

Definition at line 655 of file fbp.c.

678 {
679 if(0) printf("fbp_back_proj_round(..., %d, %d, %d, %d, %g, %g, %g, ...)\n",
680 imgDim, view, views, rays, offsX, offsY, bpZoom);
681
682 float *imgp, si, co, sir, cor, toffs, rayCenter, tPow2, yph, dif;
683 float t; /* distance between projection ray and origo */
684 int x, y, halfDim, right_top_limit, xrightround, ybottomround, ti;
685
686 /* Sine and cosine for x,y-shift */
687 si=sinB[view]*offsY;
688 co=sinB[views/2+view]*offsX;
689 /* Sine and cosine for backprojection */
690 sir=sinBrot[view];
691 cor=sinBrot[views/2+view];
692 halfDim=imgDim/2;
693 y=halfDim-2;
694 rayCenter=0.5*(float)rays;
695 if((float)y>(rayCenter*bpZoom)) {
696 y=(int)(rayCenter*bpZoom);
697 ybottomround=-y;
698 } else {
699 ybottomround=-halfDim+1;
700 }
701 toffs=rayCenter-si+co;
702 tPow2=rayCenter*rayCenter*bpZoom*bpZoom;
703 right_top_limit=halfDim-1;
704 for(; y>=ybottomround; y--) {
705 yph=0.5+(float)y;
706 xrightround=(int)sqrt(tPow2 - yph*yph) + 1;
707 if(xrightround>=halfDim) {
708 xrightround=right_top_limit;
709 x=-halfDim;
710 } else {
711 x=-xrightround;
712 }
713 t=toffs-(float)y*sir+((float)(x+1))*cor;
714 imgp=imgOrigin-y*imgDim+x;
715 for(; x<=xrightround; x++, t+=cor) {
716 ti=(int)t; dif=t-(float)ti;
717 *imgp++ += prj[ti] + (prj[ti+1] - prj[ti])*dif;
718 }
719 }
720}

Referenced by fbp(), and imgFBP().

◆ fbp_fft_bidir_complex_radix2()

void fbp_fft_bidir_complex_radix2 ( float * real,
float * imag,
int direct,
int n,
float * sine,
float * cosine )
extern

In-place bidirectional radix-2 discrete FFT of complex data, applying pre-computed sine and cosine tables.

Adapted from subroutine FOUREA listed in Programs for Digital Signal Processing Edited by Digital Signal Processing Committee IEEE Acoustics Speech and Signal Processing Committee Chapter 1 Section 1.1 Page 1.1-4,5

Author
Sakari Alenius
Parameters
realArray of real part complex data
imagArray of imaginary part complex data
directdirection: 0 and 1=forward FFT, -1=inverse FFT
nArray length
sineSine table
cosineCosine table

Definition at line 512 of file fbp.c.

525 {
526 int i, j, m, halfn, mmax, istep, ind;
527 float c, s, treal, timag;
528
529 halfn=n/2;
530
531
532#if(0)
533 for(i=j=1; i<=n; i++) {
534 if(i<j) {
535 treal=real[j-1]; timag=imag[j-1];
536 real[j-1]=real[i-1]; imag[j-1]=imag[i-1];
537 real[i-1]=treal; imag[i-1]=timag;
538 }
539 m=halfn;
540 while(j>m) {j-=m; m++; m/=2;}
541 j+=m;
542 }
543
544 mmax=1;
545 while(mmax<n) {
546 istep=2*mmax;
547 for(m=1; m<=mmax; m++) {
548 ind=(int)((float)(halfn*(m-1))/(float)mmax);
549 c=cosine[ind]; s=(direct>=0)?sine[ind]:-sine[ind];
550 for(i=m; i<=n; i+=istep) {
551 j=i+mmax;
552 treal=real[j-1]*c - imag[j-1]*s;
553 timag=imag[j-1]*c + real[j-1]*s;
554 real[j-1]=real[i-1]-treal;
555 imag[j-1]=imag[i-1]-timag;
556 real[i-1]+=treal;
557 imag[i-1]+=timag;
558 }
559 }
560 mmax=istep;
561 }
562
563#else
564 for(i=j=0; i<n; i++) {
565 if(i<j) {
566 treal=real[j]; timag=imag[j];
567 real[j]=real[i]; imag[j]=imag[i];
568 real[i]=treal; imag[i]=timag;
569 }
570 m=halfn;
571 while(j>=m) {j-=m; m++; m/=2;}
572 j+=m;
573 }
574
575 mmax=1;
576 while(mmax<n) {
577 istep=2*mmax;
578 for(m=0; m<mmax; m++) {
579 ind=(int)((float)(halfn*m)/(float)mmax);
580 c=cosine[ind]; s=(direct>=0)?sine[ind]:-sine[ind];
581 for(i=m; i<n; i+=istep) {
582 j=i+mmax;
583 treal=real[j]*c - imag[j]*s;
584 timag=imag[j]*c + real[j]*s;
585 real[j]=real[i]-treal;
586 imag[j]=imag[i]-timag;
587 real[i]+=treal;
588 imag[i]+=timag;
589 }
590 }
591 mmax=istep;
592 }
593#endif
594}

Referenced by fbp(), and imgFBP().

◆ fbpMakeFilter()

int fbpMakeFilter ( float * sinFFT,
float * cosFFT,
float cutoff,
int filter,
int lenFFT,
int views,
float * fbpFilter,
int verbose )
extern

Compute filter coefficients for FBP reconstruction.

The filter is made by multiplying a ramp by a window function, according to the filter type.

Returns
Returns 0 if ok.
Parameters
sinFFTSine table for FFT
cosFFTCosine table for FFT
cutoffNoise cut-off
filterFilter code: 0=None, 1=Ramp, 2=Butter, 3=Hann, 4=Hamm, 5=Parzen, 6=Shepp.
lenFFTlength of FFT array; must be 256, 512, 1024, 2048, ...
viewsnr of scan views (dim y)
fbpFilterfilter array for FBP (output); allocated outside with size lenFFT+1
verboseVerbose level; if zero, then nothing is printed to stderr or stdout

Definition at line 382 of file fbp.c.

399 {
400 if(verbose>0)
401 printf("fbpMakeFilter(..., %g, %d, %d, %d, ...)\n",
402 cutoff, filter, lenFFT, views);
403 if(sinFFT==NULL || cosFFT==NULL || fbpFilter==NULL) return(1);
404
405 int i, istop;
406 float *ramp, f;
407 float invNr, bp_ifft_scale, rampDC, rampSlope;
408
409 /* Check arguments */
410 if(lenFFT<2 || views<2) return(1);
411
412 /*
413 * Make the ramp to be used in building the reconstruction filter.
414 * Multiplied later by a window to get the actual filter.
415 * Ramp filter:
416 * filt[i] = i/N 0 <= i <= N/2
417 * filt[i] = (N-i)/N N/2+1 <= i <= N-1
418 */
419 float *locData=calloc(lenFFT, sizeof(float));
420 if(locData==NULL) return(2);
421 ramp=locData;
422
423 invNr=1.0/(float)lenFFT;
424 bp_ifft_scale=M_PI/(float)(views*lenFFT);
425 if(verbose>1) printf("invNr=%g bp_ifft_scale=%g\n", invNr, bp_ifft_scale);
426 /* Construct the direct method (original VAX) to calculate the ramp function: */
427 ramp[0]=0.0;
428 for(i=1; i<=lenFFT/2; i++)
429 ramp[i]=ramp[lenFFT-i]=(float)i*invNr;
430 rampDC=ramp[0];
431 rampSlope=ramp[lenFFT/2]-rampDC; // height of ramp
432 if(verbose>1) printf("rampDC=%g rampSlope=%g\n", rampDC, rampSlope);
433 /* FFT filter is made by multiplying a ramp by a window function, */
434 /* according to the filter type */
435 istop=(int)(cutoff*(float)lenFFT+0.5);
436 if(istop>lenFFT/2) istop=lenFFT/2;
437
438 switch(filter) {
439 case FBP_FILTER_RAMP: /* Ramp */
440 fbpFilter[0]=ramp[0]*bp_ifft_scale;
441 for(i=1; i<=istop; i++)
442 fbpFilter[i]=fbpFilter[lenFFT-i]=ramp[i]*bp_ifft_scale;
443 for(; i<=lenFFT/2; i++)
444 fbpFilter[i]=fbpFilter[lenFFT-i]=0.0;
445 break;
446 case FBP_FILTER_HANN: /* Hann */
447 fbpFilter[0]=ramp[0]*bp_ifft_scale;
448 for(i=1; i<=istop; i++) {
449 f=0.5+0.5*cosf(M_PI*invNr*(float)i/cutoff);
450 fbpFilter[i]=fbpFilter[lenFFT-i]=ramp[i]*f*bp_ifft_scale;
451 }
452 for(; i<=lenFFT/2; i++) fbpFilter[i]=fbpFilter[lenFFT-i]=0.0;
453 break;
454 case FBP_FILTER_HAMM: /* Hamm */
455 fbpFilter[0]=ramp[0];
456 for(i=1; i<=istop; i++) {
457 f=0.54+0.46*cosf(M_PI*invNr*(float)i/cutoff);
458 fbpFilter[i]=fbpFilter[lenFFT-i]=ramp[i]*f*bp_ifft_scale;
459 }
460 for(; i<=lenFFT/2; i++) fbpFilter[i]=fbpFilter[lenFFT-i]=0.0;
461 break;
462 case FBP_FILTER_PARZEN: /* Parzen */
463 fbpFilter[0]=ramp[0];
464 for(i=1; i<=istop/2; i++) {
465 f=(float)i/(float)istop; f=1.0-6.0*f*f*(1.0-f);
466 fbpFilter[i]=fbpFilter[lenFFT-i]=ramp[i]*f*bp_ifft_scale;
467 }
468 for(; i<=istop; i++) {
469 f=1.0-(float)i/(float)istop; f=2.0*f*f*f;
470 fbpFilter[i]=fbpFilter[lenFFT-i]=ramp[i]*f*bp_ifft_scale;
471 }
472 for(; i<=lenFFT/2; i++) fbpFilter[i]=fbpFilter[lenFFT-i]=0.0;
473 break;
474 case FBP_FILTER_SHEPP: /* Shepp */
475 fbpFilter[0]=ramp[0];
476 for(i=1; i<=istop; i++) {
477 f=0.5*(float)i/(float)istop; f=sinf(f*M_PI)/(f*M_PI);
478 fbpFilter[i]=fbpFilter[lenFFT-i]=ramp[i]*f*bp_ifft_scale;
479 }
480 for(; i<=lenFFT/2; i++) fbpFilter[i]=fbpFilter[lenFFT-i]=0.0;
481 break;
482 case FBP_FILTER_BUTTER: /* Butter */
483 fprintf(stderr, "Warning: Butter filter not implemented, using None.\n");
484 /* __attribute__((fallthrough)); */
485 /* FALLTHROUGH */
486 case FBP_FILTER_NONE: /* None */
487 for(i=0; i<lenFFT; i++) fbpFilter[i]=bp_ifft_scale;
488 rampSlope=0.0; /* Reset the ramp slope value */
489 break;
490 default:
491 fprintf(stderr, "Error: invalid filter requested.\n");
492 free(locData);
493 return(1);
494 } /* switch */
495
496 free(locData);
497 return(0);
498}

Referenced by fbp(), and imgFBP().

◆ imgFBP()

int imgFBP ( IMG * scn,
IMG * img,
int imgDim,
float zoom,
int filter,
float cutoff,
float shiftX,
float shiftY,
float rotation,
int verbose )
extern

Filtered back-projection (FBP) reconstruction using data in IMG struct.

See also
fbp, imgReprojection
Returns
Returns 0 if ok.
Parameters
scnSinogram (input) data.
imgImage (output) data; allocated here.
imgDimImage dimension (size, usually 128 or 256); must be an even number.
zoomZoom factor (for example 2.45)
filterFilter code: 0=None, 1=Ramp, 2=Butter, 3=Hann, 4=Hamm, 5=Parzen, 6=Shepp.
cutoffNoise cut-off (for example 0.3).
shiftXPossible shifting in x dimension (mm).
shiftYPossible shifting in y dimension (mm).
rotationPossible image rotation (in degrees).
verboseVerbose level; if zero, then nothing is printed to stderr or stdout.

Definition at line 108 of file fbp.c.

130 {
131 if(verbose>0)
132 printf("imgFBP(scn, img, %d, %g, %d, %g, %g, %g, %g)\n",
133 imgDim, zoom, filter, cutoff, shiftX, shiftY, rotation);
134
135 int i, j, ret, plane, frame, fullBP;
136 int lenFFT, halfDim;
137 float *sinB, *sinBrot, *sinFFT, *cosFFT;
138 float *oReal, *oImag, *real, *imag, *scnData, *imgData, *imgOrigin;
139 float *fbpFilter, bpZoom, bpZoomInv, *fptr, *gptr, *row1, *row2, f;
140 float offsX, offsY, pixSize; /* note that pixSize is in cm */
141
142
143 /* Check the arguments */
144 if(scn->status!=IMG_STATUS_OCCUPIED) return(1);
145 if(imgDim<2 || imgDim>4096 || imgDim%2) return(1);
146 if(zoom<0.01 || zoom>1000.) return(1);
147 if(filter<0 || filter>6) return(1);
148 if(cutoff<=0.0 || cutoff>=1.0) return(1);
149 if(scn->dimx<=1 || scn->dimx>16384) return(1);
150
151 /*
152 * Allocate output image
153 */
154 if(verbose>1) {printf("allocating memory for the image\n"); fflush(stdout);}
155 imgEmpty(img);
156 ret=imgAllocate(img, scn->dimz, imgDim, imgDim, scn->dimt);
157 if(ret) return(3);
158
159 /* Set image "header" information */
160 if(verbose>1) {printf("setting image header\n"); fflush(stdout);}
161 img->type=IMG_TYPE_IMAGE;
162 img->unit=CUNIT_COUNTS; /* This will convert to ECAT counts/sec */
163 img->scanStart=scn->scanStart;
164 img->axialFOV=scn->axialFOV;
166 img->sizez=scn->sizez;
167 strcpy(img->studyNr, scn->studyNr);
169 if(scn->sampleDistance<=0.0) {
170 if(scn->dimx==281) {
171 img->sizez=4.25;
172 scn->sampleDistance=1.95730;
173 scn->axialFOV=150.; scn->transaxialFOV=550.;
174 } else {
175 img->sizez=6.75;
176 scn->sampleDistance=3.12932;
177 scn->axialFOV=108.; scn->transaxialFOV=600.829;
178 }
179 }
180 pixSize=scn->sampleDistance*(float)scn->dimx/((float)imgDim*zoom);
181 img->sizex=img->sizey=pixSize;
182 for(plane=0; plane<scn->dimz; plane++)
183 img->planeNumber[plane]=scn->planeNumber[plane];
184 strcpy(img->radiopharmaceutical, scn->radiopharmaceutical);
187 for(frame=0; frame<scn->dimt; frame++) {
188 img->start[frame]=scn->start[frame]; img->end[frame]=scn->end[frame];
189 img->mid[frame]=0.5*(img->start[frame]+img->end[frame]);
190 }
191 img->isWeight=0;
192
193 /*
194 * Preparations for reconstruction
195 */
196 /* Allocate memory for scan and image data arrays */
197 if(verbose>1) {printf("allocating memory for matrices\n"); fflush(stdout);}
198 i=scn->dimx*scn->dimy + img->dimx*img->dimy;
199 float *matData=calloc(i, sizeof(float));
200 if(matData==NULL) {
201 imgEmpty(img);
202 return(4);
203 }
204 scnData=matData; imgData=matData+(scn->dimx*scn->dimy);
205
206 /* Set FFT array length */
207 lenFFT=(2*scn->dimx)-1;
208 if(lenFFT<256) lenFFT=256; else if(lenFFT<512) lenFFT=512;
209 else if(lenFFT<1024) lenFFT=1024; else if(lenFFT<2048) lenFFT=2048;
210 else if(lenFFT<4096) lenFFT=4096; else if(lenFFT<8192) lenFFT=8192;
211 else if(lenFFT<16384) lenFFT=16384; else return(1);
212 if(verbose>2)
213 printf("rays=%d views=%d lenFFT=%d\n", scn->dimx, scn->dimy, lenFFT);
214
215 /* Allocate memory for pre-computed tables */
216 i=3*scn->dimy/2 + 3*scn->dimy/2 + 5*lenFFT/4;
217 if(verbose>1) printf("allocating memory for pre-computed tables\n");
218 float *tabData=calloc(i, sizeof(float));
219 if(tabData==NULL) {
220 imgEmpty(img); free(matData);
221 return(4);
222 }
223 sinB=tabData; sinBrot=tabData+3*scn->dimy/2;
224 sinFFT=sinBrot+3*scn->dimy/2;
225
226 /* Pre-compute the sine tables for back-projection (note the rotation!) */
227 if(verbose>1) printf("computing sine tables for back-projection\n");
228 recSinTables(scn->dimy, sinB, sinBrot, rotation);
229
230 /* Pre-compute the sine and cosine tables for FFT */
231 if(verbose>1) printf("computing sine and cosine tables for FFT\n");
232 {
233 double df=0.0, dg;
234 dg=(double)M_PI*2.0/(double)lenFFT;
235 for(i=0; i<5*lenFFT/4; i++, df+=dg) sinFFT[i]=(float)sin(df);
236 cosFFT=sinFFT+lenFFT/4;
237 }
238
239 /* Allocate memory for reconstruction filter coefficients */
240 if(verbose>1) printf("allocating memory for reconstruction filters\n");
241 float *filData=calloc((5*lenFFT), sizeof(float));
242 if(filData==NULL) {
243 imgEmpty(img); free(matData); free(tabData);
244 return(4);
245 }
246 fbpFilter=filData; oReal=filData+lenFFT; oImag=oReal+2*lenFFT;
247 real=oReal+lenFFT/2; imag=oImag+lenFFT/2;
248
249 /* Compute reconstruction filter coefficients */
250 ret=fbpMakeFilter(sinFFT, cosFFT, cutoff, filter, lenFFT, scn->dimy,
251 fbpFilter, verbose-1);
252 if(ret) {
253 imgEmpty(img); free(matData); free(tabData); free(filData);
254 return(5);
255 }
256 if(verbose>3) {
257 printf("\nfbpFilter:\n");
258 for(i=0; i<lenFFT; i++) {
259 printf("%g ", fbpFilter[i]);
260 if((i+1)%7==0 || i==lenFFT-1) printf("\n");}
261 printf("\n");
262 }
263
264 /* Set the backprojection zoom and inverse (globals) */
265 bpZoom=zoom*(float)imgDim/(float)scn->dimx;
266 bpZoomInv=1.0/bpZoom;
267 if(verbose>2) printf("bpZoom=%g bpZoomInv=%g\n", bpZoom, bpZoomInv);
268
269 /* Check if image corners need to be processed */
270 if(zoom>M_SQRT2) fullBP=1; /* profile overlaps the image; 1.41421356 */
271 else fullBP=0; /* do not process image corners */
272 if(verbose>1) printf("fullBP := %d\n", fullBP);
273
274 /* Initialize variables used by back-projection */
275 if(verbose>1) printf("initialize variables for back-projection\n");
276 halfDim=imgDim/2;
277 offsX=shiftX/pixSize; offsY=shiftY/pixSize;
278 for(i=0; i<3*(scn->dimy)/2; i++) {
279 sinB[i]*=bpZoomInv;
280 sinBrot[i]*=bpZoomInv;
281 }
282 imgOrigin=imgData+imgDim*(halfDim-1)+halfDim;
283 if(verbose>2) {
284 printf("halfDim=%d offsX=%g offsY=%g\n", halfDim, offsX, offsY);
285 }
286
287 /*
288 * Reconstruct one matrix at a time
289 */
290 if(verbose>1) printf("reconstruct one matrix at a time...\n");
291 for(plane=0; plane<scn->dimz; plane++)
292 for(frame=0; frame<scn->dimt; frame++) {
293
294 if(verbose>3) {
295 printf("reconstructing plane %d frame %d\n",
296 scn->planeNumber[plane], frame+1);
297 fflush(stdout);
298 }
299
300 /* Copy scan data into the array */
301 for(i=0, fptr=scnData; i<scn->dimy; i++)
302 for(j=0; j<scn->dimx; j++)
303 *fptr++=scn->m[plane][i][j][frame];
304 if(verbose>8)
305 printf("scn->m[%d][158][116][%d]=%e\n",
306 plane, frame, scn->m[plane][64][56][frame]);
307
308 /* Initiate image buffer */
309 for(i=0, fptr=imgData; i<imgDim*imgDim; i++) *fptr++=0.0;
310
311 /* Process each sinogram row (projection), two at the same time */
312 for(int view=0; view<scn->dimy; view+=2) {
313
314 /* Fill FFT buffers with two rows */
315 for(j=0; j<2*lenFFT; j++) oReal[j]=0.0; /* zero padding */
316 for(j=0; j<2*lenFFT; j++) oImag[j]=0.0; /* zero padding */
317 row1=scnData+view*scn->dimx;
318 row2=row1+scn->dimx;
319 fptr=real; gptr=imag;
320 for(j=0; j<scn->dimx; j++) {
321 *fptr++ = *row1++;
322 *gptr++ = *row2++;
323 }
324
325 /* Forward FFT */
326 fptr=real; gptr=imag;
327 fbp_fft_bidir_complex_radix2(fptr, gptr, 1, lenFFT, sinFFT, cosFFT);
328
329 /* Due to symmetry properties, filtering the combined data together */
330 for(j=0, fptr=fbpFilter; j<lenFFT; j++) {
331 real[j] *= *fptr;
332 imag[j] *= *fptr++;
333 }
334
335 /* Inverse FFT */
336 fptr=real; gptr=imag;
337 fbp_fft_bidir_complex_radix2(fptr, gptr, -1, lenFFT, sinFFT, cosFFT);
338 fptr=real; gptr=imag;
339 if(fullBP) {
340 fbp_back_proj(fptr, imgData, imgDim, view, scn->dimy, scn->dimx,
341 offsX, offsY, sinB, sinBrot);
342 fbp_back_proj(gptr, imgData, imgDim, view+1, scn->dimy, scn->dimx,
343 offsX, offsY, sinB, sinBrot);
344 } else {
345 fbp_back_proj_round(fptr, imgOrigin, imgDim, view,
346 scn->dimy, scn->dimx, offsX, offsY, bpZoom, sinB, sinBrot);
347 fbp_back_proj_round(gptr, imgOrigin, imgDim, view+1,
348 scn->dimy, scn->dimx, offsX, offsY, bpZoom, sinB, sinBrot);
349 }
350
351 } /* next projection (view) */
352
353 /* Copy the image array to matrix data */
354 /* At the same time, correct for the frame length */
355 f=img->end[frame]-img->start[frame];
356 if(f<1.0) f=1.0;
357 f=1.0/f;
358 for(i=0, fptr=imgData; i<img->dimy; i++)
359 for(j=0; j<img->dimx; j++)
360 img->m[plane][i][j][frame] = (*fptr++)*f;
361 if(verbose>8)
362 printf("img->m[%d][64][56][%d]=%e\n",
363 plane, frame, img->m[plane][64][56][frame]);
364
365 } /* next matrix */
366
367 /* Free the memory */
368 free(matData); free(tabData); free(filData);
369
370 if(verbose>1) printf("imgFBP() done.\n");
371 return(0);
372}
void fbp_back_proj(float *prj, float *imgCorner, int imgDim, int view, int views, int rays, float offsX, float offsY, float *sinB, float *sinBrot)
Definition fbp.c:599
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_STATUS_OCCUPIED
#define IMG_DC_NONCORRECTED
#define IMG_TYPE_IMAGE
float sizex
unsigned short int dimx
char type
float sampleDistance
float **** m
char decayCorrection
float transaxialFOV
char unit
char status
time_t scanStart
unsigned short int dimt
int * planeNumber
float sizey
float * start
unsigned short int dimz
unsigned short int dimy
float * end
char radiopharmaceutical[32]
float isotopeHalflife
char studyNr[MAX_STUDYNR_LEN+1]
float axialFOV
float * mid
char isWeight
float sizez

◆ imgMRP()

int imgMRP ( IMG * scn,
IMG * img,
int imgDim,
float zoom,
float shiftX,
float shiftY,
float rotation,
int maxIterNr,
int skipPriorNr,
float beta,
int maskDim,
int osSetNr,
int verbose )
extern

Median Root Prior (MRP) reconstruction using data in IMG struct.

See also
imgFBP, mrp
Returns
Returns 0 if ok.
Parameters
scnSinogram (input) data. Data must be normalization and attenuation corrected.
imgImage (output) data; allocated here.
imgDimImage dimension (size, usually 128 or 256); must be an even number.
zoomZoom factor (for example 2.45 for the brain); 1=no zooming.
shiftXPossible shifting in x dimension (mm).
shiftYPossible shifting in y dimension (mm).
rotationPossible image rotation, -180 - +180 (in degrees).
maxIterNrNr of iterations, for example 150.
skipPriorNrNumber of iterations to skip before prior; usually 1.
betaBeta, 0.01 - 0.9; usually 0.3 for emission, 0.9 for transmission.
maskDimMedian filter mask dimension; 3 or 5 (9 or 21 pixels).
osSetNrNumber of Ordered Subset sets; 1, 2, 4, ... 128.
verboseVerbose level; if zero, then nothing is printed to stderr or stdout.

Definition at line 21 of file mrp.c.

49 {
50 if(verbose>1)
51 printf("imgMRP(scn, img, %d, %g, %g, %g, %g, %d, %d, %g, %d, %d)\n",
52 imgDim, zoom, shiftX, shiftY, rotation, maxIterNr, skipPriorNr, beta,
53 maskDim, osSetNr);
54
55
56 /* Check the arguments */
57 if(scn->status!=IMG_STATUS_OCCUPIED) return(1);
58 if(imgDim<2 || imgDim>4096 || imgDim%2) return(1);
59 if(zoom<0.01 || zoom>1000.) return(1);
60 if(scn->dimx<=1 || scn->dimx>16384) return(1);
61 if(beta<0.0) return(1);
62 if(maskDim!=3 && maskDim!=5) return(1);
63
64
65 /*
66 * Allocate output image
67 */
68 if(verbose>1) printf("allocating memory for the image\n");
69 imgEmpty(img);
70 if(imgAllocate(img, scn->dimz, imgDim, imgDim, scn->dimt)!=0) return(3);
71
72 /* Set image "header" information */
73 if(verbose>1) printf("setting image header\n");
75 img->unit=CUNIT_CPS; /* (cnts/sec) */
76 img->scanStart=scn->scanStart;
77 img->axialFOV=scn->axialFOV;
79 img->sizez=scn->sizez;
80 strcpy(img->studyNr, scn->studyNr);
82 if(scn->sampleDistance<=0.0) {
83 if(scn->dimx==281) { // GE Advance
84 img->sizez=4.25;
85 scn->sampleDistance=1.95730;
86 scn->axialFOV=150.; scn->transaxialFOV=550.;
87 } else { // ECAT 931
88 img->sizez=6.75;
89 scn->sampleDistance=3.12932;
90 scn->axialFOV=108.; scn->transaxialFOV=600.829;
91 }
92 }
93 float pixSize; /* note that pixSize is in cm in the ECAT image */
94 pixSize=scn->sampleDistance*(float)scn->dimx/((float)imgDim*zoom);
95 img->sizex=img->sizey=pixSize;
96 int plane, frame;
97 for(plane=0; plane<scn->dimz; plane++)
98 img->planeNumber[plane]=scn->planeNumber[plane];
102 for(frame=0; frame<scn->dimt; frame++) {
103 img->start[frame]=scn->start[frame]; img->end[frame]=scn->end[frame];
104 img->mid[frame]=0.5*(img->start[frame]+img->end[frame]);
105 }
106 img->isWeight=0;
107
108 /*
109 * Preparations for reconstruction
110 */
111
112 /* Pre-compute the sine tables for back-projection (note the rotation!) */
113 if(verbose>1) printf("computing sine tables for back-projection\n");
114 float sinB[3*scn->dimy/2];
115 float sinBrot[3*scn->dimy/2];
116 recSinTables(scn->dimy, sinB, sinBrot, rotation);
117
118 /* Set the backprojection zoom and inverse (globals) */
119 float bpZoom, bpZoomInv;
120 bpZoom=zoom*(float)imgDim/(float)scn->dimx;
121 bpZoomInv=1.0/bpZoom;
122 if(verbose>2) printf("bpZoom=%g bpZoomInv=%g\n", bpZoom, bpZoomInv);
123
124 /* Initialize variables used by back-projection */
125 if(verbose>1) printf("initialize variables for back-projection\n");
126 float offsX, offsY;
127 int halfDim;
128 halfDim=imgDim/2;
129 offsX=shiftX/pixSize; offsY=shiftY/pixSize;
130 for(int i=0; i<3*(scn->dimy)/2; i++) {
131 sinB[i]*=bpZoomInv;
132 sinBrot[i]*=bpZoomInv;
133 }
134 if(verbose>2) {
135 printf("halfDim=%d offsX=%g offsY=%g\n", halfDim, offsX, offsY);
136 }
137
138
139 /*
140 * Reconstruct one matrix at a time
141 */
142 if(verbose>1) printf("reconstruct one matrix at a time...\n");
143 int failed=0;
144#pragma omp parallel for private(frame)
145 for(plane=0; plane<scn->dimz; plane++) {
146 for(frame=0; frame<scn->dimt; frame++) {
147 if(failed) break;
148
149 if(verbose>3) {
150 printf("reconstructing plane %d frame %d\n",
151 scn->planeNumber[plane], frame+1);
152 fflush(stdout);
153 }
154 int i, j, k, ret;
155
156 /* Copy scan data into the array */
157 float scnData[scn->dimx*scn->dimy];
158 float imgData[img->dimx*img->dimy];
159 //float *imgOrigin=imgData+imgDim*(halfDim-1)+halfDim;
160
161 for(i=0, k=0; i<scn->dimy; i++)
162 for(j=0; j<scn->dimx; j++)
163 scnData[k++]=scn->m[plane][i][j][frame];
164 /* Initiate image buffer */
165 for(i=0; i<imgDim*imgDim; i++) imgData[i]=0.0;
166
167 /* Reconstruct */
168 ret=mrp(scnData, scn->dimx, scn->dimy, maxIterNr, osSetNr, maskDim, zoom,
169 beta, skipPriorNr, imgDim, imgData, verbose-3);
170 if(ret!=0) {
171 if(verbose>0) fprintf(stderr, "mrp() return value %d\n", ret);
172 failed=ret; break;
173 }
174
175 /* Copy the image array to matrix data */
176 /* At the same time, correct for the frame length */
177 float f;
178 f=img->end[frame]-img->start[frame];
179 if(f<1.0) f=1.0;
180 f=1.0/f;
181 for(i=0, k=0; i<img->dimy; i++)
182 for(j=0; j<img->dimx; j++)
183 img->m[plane][i][j][frame] = imgData[k++]*f;
184 if(verbose==1) {fprintf(stdout, "."); fflush(stdout);}
185 } /* next frame */
186 } /* next plane */
187 if(verbose==1) {fprintf(stdout, "\n"); fflush(stdout);}
188 if(failed) return(8);
189
190 if(verbose>1) printf("imgMRP() done.\n");
191 return(0);
192}
int mrp(float *sinogram, int rays, int views, int iter, int os_sets, int maskdim, float zoom, float beta, int skip_prior, int dim, float *image, int verbose)
Definition mrp.c:262

◆ imgReprojection()

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

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}
#define IMG_TYPE_RAW
#define IMG_DC_UNKNOWN
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)
int _fileFormat
float zoom

◆ med21()

float med21 ( float * inp,
int dim )
extern

Compute 5x5 median without corners from image data inside float array.

Returns
Returns the median value.
Parameters
inpPointer to central pixel in image data, around which the median is computed.
dimImage dimensions.

Definition at line 49 of file mrprior.c.

54 {
55// oxxxo
56// xxxxx
57// xxXxx
58// xxxxx
59// oxxxo
60 float w[21], *p;
61
62 /* 1st row */
63 p=inp-2*dim-1; w[0]=*p++; w[1]=*p++; w[2]=*p;
64 /* 2nd row */
65 p=inp-dim-2; w[3]=*p++; w[4]=*p++; w[5]=*p++; w[6]=*p++; w[7]=*p;
66 /* 3rd row */
67 p=inp-2; w[8]=*p++; w[9]=*p++; w[10]=*p++; w[11]=*p++; w[12]=*p;
68 /* 4th row */
69 p=inp+dim-2; w[13]=*p++; w[14]=*p++; w[15]=*p++; w[16]=*p++; w[17]=*p;
70 /* 5th row */
71 p=inp+2*dim-1; w[18]=*p++; w[19]=*p++; w[20]=*p;
72 /* Median */
73 return(fmedian(w, 21));
74}
float fmedian(float *data, long long int n)
Definition imgminmax.c:593

Referenced by do_prior(), and trmrp().

◆ med9()

float med9 ( float * inp,
int dim )
extern

Compute 3x3 median from image data inside float array.

Returns
Returns the median value.
Parameters
inpPointer to central pixel in image data, around which the median is computed.
dimImage dimensions.

Definition at line 15 of file mrprior.c.

20 {
21// xxx
22// xXx
23// xxx
24 float w[9], *p;
25 int n=0;
26
27 /* upper row */
28 p=inp-dim-1;
29 w[n]=*p++; if(isfinite(w[n])) n++;
30 w[n]=*p++; if(isfinite(w[n])) n++;
31 w[n]=*p; if(isfinite(w[n])) n++;
32 /* mid row */
33 p=inp-1;
34 w[n]=*p++; if(isfinite(w[n])) n++;
35 w[n]=*p++; if(isfinite(w[n])) n++;
36 w[n]=*p; if(isfinite(w[n])) n++;
37 /* lower row */
38 p=inp+dim-1;
39 w[n]=*p++; if(isfinite(w[n])) n++;
40 w[n]=*p++; if(isfinite(w[n])) n++;
41 w[n]=*p; if(isfinite(w[n])) n++;
42 /* Median */
43 return(fmedian(w, n));
44}

Referenced by do_prior(), and trmrp().

◆ mrp()

int mrp ( float * sinogram,
int rays,
int views,
int iter,
int os_sets,
int maskdim,
float zoom,
float beta,
int skip_prior,
int dim,
float * image,
int verbose )
extern

Median Root Prior (MRP) reconstruction of one 2D data matrix given as an array of floats.

See also
trmrp, reprojection
Returns
Returns 0 if ok.
Parameters
sinogramPointer to float array containing rays*views sinogram values. Data must be normalization and attenuation corrected.
raysNr of rays (bins or columns) in sinogram data.
viewsNr of views (rows) in sinogram data.
iterNr of iterations.
os_setsLength of ordered subset process order array; 1, 2, 4, ... 128.
maskdimMask dimension; 3 or 5 (9 or 21 pixels).
zoomReconstruction zoom.
betaBeta.
skip_priorNumber of iteration before prior; usually 1.
dimImage x and y dimensions; must be an even number, preferably the same as number of rays, but there is no reason for it to be any larger than that.
imagePointer to pre-allocated image data; size must be at least dim*dim.
verboseVerbose level; if zero, then nothing is printed to stderr or stdout.

Definition at line 262 of file mrp.c.

290 {
291 if(verbose>0)
292 printf("mrp(%d, %d, %d, %d, %d, %g, %g, %d, %d)\n",
293 rays, views, iter, os_sets, maskdim, zoom, beta, skip_prior, dim);
294 if(sinogram==NULL || image==NULL) return(1);
295 if(rays<2 || views<2 || iter<1 || os_sets<1 || dim<2) return(1);
296 if(dim%2 || zoom<0.05) return(2);
297 if(maskdim!=3 && maskdim!=5) return(2);
298
299 int i, k;
300 int imgsize=dim*dim;
301 int halfdim=dim/2;
302 int views_in_set=views/os_sets;
303
304 /* Set scale */
305 int recrays;
306 float scale, bp_zoom;
307 recrays=(int)((float)dim*zoom);
308 bp_zoom=zoom*(float)dim/(float)recrays;
309 scale=((float)recrays/(float)rays)*bp_zoom*bp_zoom/(float)views;
310 if(verbose>1) {
311 printf(" recrays := %d\n", recrays);
312 printf(" bp_zoom := %g\n", bp_zoom);
313 printf(" scale := %g\n", scale);
314 }
315
316 /* Make the Ordered Subset process order (bit-reversed sequence) */
317 int seq[os_sets]; set_os_set(os_sets, seq);
318 if(verbose>2) {
319 printf("os_sets :=");
320 for(i=0; i<os_sets; i++) printf(" %d", seq[i]);
321 printf("\n"); fflush(stdout);
322 }
323
324 /* Arrange the sinogram and interpolate so that
325 bin width equals pixel width */
326 float sino[recrays*views];
327 {
328 float scnset[rays*views];
329 /* arrange */
330 for(int s=0; s<os_sets; s++) {
331 for(int j=0; j<views/os_sets; j++) {
332 memcpy((char*)(scnset + s*rays*views/os_sets + j*rays),
333 (char*)(sinogram + j*rays*os_sets + s*rays), rays*sizeof(float));
334 }
335 }
336 /* interpolate */
337 recInterpolateSinogram(scnset, sino, rays, recrays, views);
338 }
339
340 /* Get some statistics from the sinogram matrix */
341 int scnsize=recrays*views;
342 int nonzeroNr;
343 float counts;
344 nonzeroNr=recGetStatistics(sino, scnsize, &counts, NULL, NULL, 1);
345 if(verbose>1) {
346 printf(" total_counts := %g\n", counts);
347 printf(" non-zeroes := %d/%d\n", nonzeroNr, scnsize);
348 }
349
350
351 /* Make an initial image: an uniform disk enclosed by rays with a value
352 matching the total count */
353 if(verbose>1) printf("creating initial %dx%d image\n", dim, dim);
354 float current_img[imgsize];
355 for(i=0; i<imgsize; i++) image[i]=current_img[i]=0.0;
356 float init;
357 k=0;
358 init=counts/(M_PI*(float)((halfdim-1)*(halfdim-1)));
359 for(int j=halfdim-1; j>=-halfdim; j--) {
360 for(i=-halfdim; i<halfdim; i++) {
361 if((int)hypot((double)i, (double)j) < halfdim-1)
362 current_img[k]=init;
363 k++;
364 }
365 }
366
367
368 /* Pre-compute the sine tables for back-projection */
369 if(verbose>1) printf("computing sine table\n");
370 float sinB[3*views/2];
371 recSinTables(views, sinB, NULL, 0.0);
372 for(i=0; i<3*views/2; i++) sinB[i]/=bp_zoom;
373
374 /* Iterations */
375 if(verbose>1) {printf("iterations\n"); fflush(stdout);}
376 float current_proj[recrays*views_in_set+1];
377 float correction[recrays*views/os_sets];
378 float medcoefs[imgsize], mlcoefs[imgsize];
379 int s, itercount=1, view;
380 do {
381 if(verbose>3) {printf(" iteration %d\n", itercount); fflush(stdout);}
382
383 for(s=0; s<os_sets; s++) {
384 if(verbose>4) {
385 printf(" os_set %d; seq=%d\n", 1+s, seq[s]);
386 fflush(stdout);
387 }
388 /* Image reprojection */
389 for(i=0; i<recrays*views_in_set; i++) current_proj[i]=0.0;
390 for(i=0; i<views_in_set; i++) {
391 view=seq[s]+i*os_sets;
392 viewReprojection(current_img, current_proj+i*recrays, view, dim,
393 views, recrays, sinB, sinB, 0.0, 0.0, bp_zoom);
394 }
395 /* Calculate correction = measured / re-projected */
396 mrpProjectionCorrection(sino+seq[s]*recrays*views_in_set, current_proj,
397 correction, os_sets, recrays, views);
398 /* Make the ML coefficients */
399 for(i=0; i<imgsize; i++) mlcoefs[i]=0.0;
400 for(i=0; i<views_in_set; i++)
401 viewBackprojection(correction+i*recrays, mlcoefs, dim,
402 seq[s]+i*os_sets, views, recrays, sinB, sinB, 0.0, 0.0, bp_zoom);
403 /* Make the prior coefficients */
404 if(skip_prior<=0 && beta>0.0) {
405 if(verbose>3) {printf(" applying prior\n"); fflush(stdout);}
406 float maxv, maxm;
407 fMinMaxFin(current_img, imgsize, NULL, &maxv);
408 do_prior(current_img, beta, medcoefs, dim,
409 1.0E-08*maxv, maskdim, &maxm);
410 if(verbose>3) {
411 printf(" max value in current image := %g\n", maxv);
412 printf(" max median coefficient := %g\n", maxm);
413 }
414 /* Adjust ML coefficients */
415 mrpUpdate(medcoefs, mlcoefs, mlcoefs, imgsize);
416 }
417
418 /* Calculate next image */
419 mrpUpdate(mlcoefs, current_img, current_img, imgsize);
420
421 } // next set
422 itercount++; skip_prior--;
423 if(verbose>3) {printf(" -> next iteration maybe\n"); fflush(stdout);}
424 } while(itercount<iter);
425 if(verbose>2) {printf(" iterations done.\n"); fflush(stdout);}
426
427 for(i=0; i<imgsize; i++) image[i]=current_img[i]*=scale;
428
429 if(verbose>1) {printf("mrp() done.\n"); fflush(stdout);}
430 return(0);
431} // mrp()
void fMinMaxFin(float *data, long long int n, float *fmin, float *fmax)
Definition imgminmax.c:649
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 recInterpolateSinogram(float *srcsino, float *newsino, int srcrays, int newrays, int views)
Definition recutil.c:37
void set_os_set(int os_sets, int *set_seq)
Definition recutil.c:113
int recGetStatistics(float *buf, int n, float *osum, float *omin, float *omax, int skip_zero_mins)
Definition recutil.c:154
void do_prior(float *img, float beta, float *med_coef, int dim, float small, int maskdim, float *maxm)
Definition mrprior.c:77
void mrpProjectionCorrection(float *measured, float *proj, float *correct, int os_sets, int rays, int views)
Definition mrp.c:229
void mrpUpdate(float *coef, float *img, float *oimg, int n)
Definition mrp.c:201

Referenced by imgMRP().

◆ mrpProjectionCorrection()

void mrpProjectionCorrection ( float * measured,
float * proj,
float * correct,
int os_sets,
int rays,
int views )
extern

Calculate correction factors for EM-ML reconstruction. These factors will we back-projected over the image in order to get the ML-coefficients.

Divides the measured projection (sinogram) by the re-projected ray sum. If the divisor is close to zero, the factor is set to 0. The factor is not allowed to exceed a limit or to be negative.

Author
Sakari Alenius
Parameters
measuredMeasured sinogram data.
projProjection data.
correctCorrection matrix.
os_setsNumber of OS sets.
raysSinogram rays.
viewsSinogram views.

Definition at line 229 of file mrp.c.

242 {
243 for(int i=0; i<rays*views/os_sets; i++) {
244 if(fabs(proj[i])>1.0E-40) {
245 correct[i]=(float)os_sets*measured[i]/proj[i];
246 if(correct[i]>100.) correct[i]=100.;
247 else if(correct[i]<0.0) correct[i]=0.0;
248 } else {
249 correct[i]=0.0;
250 }
251 }
252}

Referenced by mrp().

◆ mrpUpdate()

void mrpUpdate ( float * coef,
float * img,
float * oimg,
int n )
extern

Update an image according to a set of coefficients.

Performs a pixel-by-pixel multiplication between the current image and the coefficients. The result is non-negative.

Parameters
coefPointer to an array of coefficients, of length n.
imgPointer to an array containing source image data, of length n.
oimgPointer to an array containing output image data, of length n.
nArray lengths

Definition at line 201 of file mrp.c.

210 {
211 for(int i=0; i<n; i++) {
212 oimg[i]=coef[i]*img[i];
213 if(oimg[i]<0.0) oimg[i]=0.0;
214 }
215}

Referenced by mrp().

◆ prmatAllocate()

int prmatAllocate ( PRMAT * mat,
int set,
unsigned int rows,
unsigned int * coords )
extern

Allocates memory for PRMAT data. Normally used only in SET-functions.
Allocates memory for look-up table if set = 0 and for projection matrix otherwise.

Precondition
*mat is initialized && rows is positive && *coords list contains as many positive integers as there are rows.
Postcondition
memory is allocated for PRMAT structure mat.
Parameters
matpointer to projection matrix for which the allocation is done.
settells for which part of the structure allocation is to be done.
rowsnumber of rows in a matrix.
coordslist of number of entries in each row.
Returns
0 if ok.

Definition at line 105 of file prmat.c.

106{
107 unsigned int *iptr, ir, ip;
108 if(PRMAT_VERBOSE) printf("PRMAT:prmatAllocate(*mat,%d,*coords) \n",rows);
109
110 /*check the arguments*/
111 if(mat->status==PRMAT_STATUS_UNINITIALIZED) return(1);
112 if(rows<1) return(2);
113
114 //If set != 0 allocate for projection matrix.
115 if(set){
116 /*allocate memory*/
117 mat->factor_sqr_sum=calloc(rows,sizeof(float));
118 mat->dimr=rows; //for dimr
119 mat->dime=calloc(rows,sizeof(int));
120 mat->_factdata=
121 (unsigned short int***)calloc(rows,sizeof(unsigned short int**));
122 //if not enough memory
123 if(mat->_factdata==NULL || mat->dime==NULL) return(4);
124 //iterate through the rows
125 for(ir=0,iptr=coords; ir<rows; ir++){
126 //copy the coords vector in the same loop
127 mat->dime[ir]=*iptr;
128 //*iptr is the number of (non-zero) factors in this row
129 mat->_factdata[ir]=
130 (unsigned short int**)calloc(*iptr,sizeof(unsigned short int*));
131 //if not enough memory
132 if(mat->_factdata[ir]==NULL) return(4);
133 //iterate through the factors in this row
134 for(ip=0; ip<(*iptr); ip++){
135 //NOTE that the leaves are coordinates and factor in this order
136 mat->_factdata[ir][ip]=
137 (unsigned short int*)calloc(3,sizeof(unsigned short int));
138 if(mat->_factdata[ir][ip]==NULL) return(4);
139 }
140 iptr++;
141 }
142 /*set data pointers; these pointers are used to avoid data loss*/
143 mat->fact=mat->_factdata;
144 } else {
145 //If set was 0 allocate for look-up table.
146 //allocate memory for look up table
147 mat->nrp=rows;
148 mat->_linesdata=(unsigned int**)calloc(rows,sizeof(unsigned int*));
149 //if not enough memory
150 if(mat->_linesdata==NULL) return(4);
151 //iterate through the rows
152 for(ir=0,iptr=coords; ir<rows; ir++){
153 //iptr is the number of lors belonging to this pixel
154 mat->_linesdata[ir]=(unsigned int*)calloc(*iptr + 2,sizeof(unsigned int));
155 //if not enough memory
156 if(mat->_linesdata[ir]==NULL) return(4);
157 iptr++;
158 }
159 //set data pointers; these pointers are used to avoid data loss
160 mat->lines=mat->_linesdata;
161 }
162 return(0);
163}
int PRMAT_VERBOSE
If not 0 drive in verbose mode.
Definition prmat.c:9
unsigned int ** lines
Definition libtpcrec.h:194
char status
Prmat status.
Definition libtpcrec.h:164
float * factor_sqr_sum
Square sums of factors in each row in the projection matrix.
Definition libtpcrec.h:202
unsigned short int *** fact
Definition libtpcrec.h:208
unsigned int * dime
Number of pixels hit by a line for every line.
Definition libtpcrec.h:204
unsigned int dimr
Dimension of rows (lines of response) in the projection matrix.
Definition libtpcrec.h:200
unsigned int nrp
Number of pixels inside the fov. i.e. number of rows in the look-up table.
Definition libtpcrec.h:189
unsigned int ** _linesdata
Hidden pointer for the actual data.
Definition libtpcrec.h:196
unsigned short int *** _factdata
Hidden pointer for the actual data.
Definition libtpcrec.h:210

Referenced by prmatReadMatrix(), radonSetLORS(), and radonSetLUT().

◆ prmatEmpty()

void prmatEmpty ( PRMAT * mat)
extern

Frees the memory allocated for mat. All data is cleared.

Parameters
matpointer to projection matrix to be emptied.

Definition at line 56 of file prmat.c.

57{
58 unsigned int ir, ip;
59 if(PRMAT_VERBOSE) printf("PRMAT:prmatEmpty() \n");
60
61 //if mat is allready empty
62 if(mat->status==PRMAT_STATUS_INITIALIZED) return;
63
64 //if look-up table is occupied
65 if(mat->status==PRMAT_STATUS_LU_OCCUPIED) {
66 /*free the occupied memory*/
67 for(ir=0; ir<mat->nrp; ir++) { //every row
68 free((unsigned int*)mat->_linesdata[ir]);
69 }
70 if(mat->nrp > 0) free(mat->_linesdata);
71 }
72
73 //if projection matrix is occupied
74 if(mat->status==PRMAT_STATUS_PR_OCCUPIED ||
75 mat->status==PRMAT_STATUS_BS_OCCUPIED )
76 {
77 free((float*)mat->factor_sqr_sum);
78 for(ir=0; ir<mat->dimr; ir++){ //every row
79 for(ip=0; ip<mat->dime[ir]; ip++){ //every factor
80 free((unsigned short int*)mat->_factdata[ir][ip]);
81 }
82 }
83
84 free((int*)mat->dime);
85
86 if(mat->dimr>0) free(mat->_factdata);
87 mat->dimr=0;
88 }
89 return;
90}

Referenced by prmatReadMatrix(), and radonSetLORS().

◆ prmatGetBinView()

unsigned int prmatGetBinView ( PRMAT * mat,
int row,
int ind )
extern

Returns coordinates of a line of response in place (row,ind) in the look-up table.

Precondition
0<=row<=prmatGetPIX(*mat) && 0<=ind<=prmatGetRays(*mat,row) && mat is initialized.
Parameters
matpointer to a projection matrix.
rowthe row index.
indthe (non-zero) lor index.
Returns
int coordinates (view*binNr + bin) of the referred line of response, some negative value if ERROR.

Definition at line 253 of file prmat.c.

254{
255 return mat->lines[row][ind+2];
256}

Referenced by prmatSaveMatrix().

◆ prmatGetCoord()

unsigned int prmatGetCoord ( PRMAT * mat,
int row,
int pix )
extern

Returns coordinate of a pixel in place (row,pix) in the given projection matrix.

Precondition
0<=row<=prmatGetLORS(*mat) && 0<=pix<=prmatGetPixels(row,*mat) && mat is initialized.
Parameters
matpointer to a projection matrix.
rowthe row index.
pixthe (non-zero) pixel index.
Returns
coordinate of the referred pixel, some negative value if ERROR.

Definition at line 297 of file prmat.c.

298{
299 return (int)(mat->fact[row][pix][1])*mat->imgDim + (int)(mat->fact[row][pix][0]);
300}
unsigned int imgDim
Scanner geometrics, field imgDim.
Definition libtpcrec.h:172

◆ prmatGetFactor()

float prmatGetFactor ( PRMAT * mat,
int row,
int pix )
extern

Returns factor (weighting coefficient) for a pixel in place (row,pix) in given projection matrix.

Precondition
0<=row<=prmatGetLORS(*mat) && 0<=pix<=prmatGetPixels(row,*mat) && mat is initialized.
Parameters
matpointer to a projection matrix.
rowthe row index.
pixthe (non-zero) pixel index.
Returns
factor for the referred pixel, some negative value if ERROR.

Definition at line 342 of file prmat.c.

343{
344 return((float)(mat->scaling_factor)*(mat->fact[row][pix][2]));
345}
float scaling_factor
Scaling factor for factors (notice that factors are stored in integers).
Definition libtpcrec.h:185

Referenced by radonBackTransformPRM(), and radonFwdTransformPRM().

◆ prmatGetFactorSqrSum()

float prmatGetFactorSqrSum ( PRMAT * mat,
int row )
extern

Returns square sum of all factors in given projection matrix in given row.

Precondition
mat is initialized && 0<=row<=prmatGetLORS(*mat).
Parameters
matpointer to a projection matrix.
rowrow index for accessing factors.
Returns
square sum of all factors in given projection matrix in given row.

Definition at line 409 of file prmat.c.

410{
411 return(mat->factor_sqr_sum[row]);
412}

Referenced by prmatSaveMatrix(), and radonSetLORS().

◆ prmatGetFactorSum()

float prmatGetFactorSum ( PRMAT * mat)
extern

Returns sum of all factors in given projection matrix. For initializing image matrix.

Precondition
mat is initialized.
Parameters
matpointer to a projection matrix.
Returns
sum of all factors in given projection matrix.

Definition at line 397 of file prmat.c.

398{
399 return(mat->factor_sum);
400}
float factor_sum
The sum of all factors in the projection matrix.
Definition libtpcrec.h:183

◆ prmatGetID()

unsigned int prmatGetID ( PRMAT * mat)
extern

Returns the image dimension in the geometrics.

Precondition
mat is initialized.
Parameters
matpointer to a projection matrix.
Returns
the image dimension in the geometrics.

Definition at line 197 of file prmat.c.

198{
199 return mat->imgDim;
200}

Referenced by radonBackTransformPRM(), and radonFwdTransformPRM().

◆ prmatGetMajor()

float prmatGetMajor ( PRMAT * mat)
extern

Returns major semiaxe of the FOV in given projection matrix.

Precondition
mat is initialized.
Parameters
matpointer to a projection matrix.
Returns
major semiaxe of the FOV in given projection matrix

Definition at line 353 of file prmat.c.

354{
355 return(mat->prmatfov[0]);
356}
int * prmatfov
Definition libtpcrec.h:177

◆ prmatGetMax()

float prmatGetMax ( PRMAT * mat)
extern

Returns greatest value in given projection matrix.

Precondition
mat is initialized.
Parameters
matpointer to a projection matrix.
Returns
maximal value in given projection matrix.

Definition at line 386 of file prmat.c.

386 {
387 return(mat->max);
388}
float max
Maximal factor value in the projection matrix.
Definition libtpcrec.h:181

◆ prmatGetMin()

float prmatGetMin ( PRMAT * mat)
extern

Returns minimal value in given projection matrix.

Precondition
mat is initialized.
Parameters
matpointer to a projection matrix.
Returns
minimal value in given projection matrix.

Definition at line 375 of file prmat.c.

376{
377 return(mat->min);
378}
float min
Minimal factor value in the projection matrix.
Definition libtpcrec.h:179

◆ prmatGetMinor()

float prmatGetMinor ( PRMAT * mat)
extern

Returns minor semiaxe of the FOV in given projection matrix.

Precondition
mat is initialized.
Parameters
matpointer to a projection matrix.
Returns
minor semiaxe of the FOV in given projection matrix

Definition at line 364 of file prmat.c.

365{
366 return(mat->prmatfov[1]);
367}

◆ prmatGetNB()

unsigned int prmatGetNB ( PRMAT * mat)
extern

Returns the number of bins (distances) in the geometrics.

Precondition
mat is initialized.
Parameters
matpointer to a projection matrix.
Returns
the number of bins in the geometrics.

Definition at line 186 of file prmat.c.

187{
188 return mat->binNr;
189}
unsigned int binNr
Scanner geometrics, field binNr.
Definition libtpcrec.h:170

Referenced by radonBackTransformPRM(), and radonFwdTransformPRM().

◆ prmatGetNV()

unsigned int prmatGetNV ( PRMAT * mat)
extern

Returns the number of views (angles) in the geometrics.

Precondition
mat is initialized.
Parameters
matpointer to a projection matrix.
Returns
the number of views in the geometrics.

Definition at line 175 of file prmat.c.

176{
177 return mat->viewNr;
178}
unsigned int viewNr
Scanner geometrics, field viewNr.
Definition libtpcrec.h:168

Referenced by radonBackTransformPRM(), and radonFwdTransformPRM().

◆ prmatGetPIX()

unsigned int prmatGetPIX ( PRMAT * mat)
extern

Returns number of rows (pixels) in the look-up table.

Precondition
mat is initialized.
Parameters
matpointer to a projection matrix.
Returns
number of pixels in look-up table, some negative value if ERROR.

Definition at line 210 of file prmat.c.

211{
212 return mat->nrp;
213}

Referenced by prmatReadMatrix(), and prmatSaveMatrix().

◆ prmatGetPixCoord()

unsigned int prmatGetPixCoord ( PRMAT * mat,
int row )
extern

Returns coordinates of a pixel in place 'row' in the look-up table.

Precondition
0<=row<=prmatGetPIX(*mat) && mat is initialized.
Parameters
matpointer to a projection matrix.
rowindex of the pixel whose coordinates are to be returned.
Returns
coordinates of a pixel in the look-up table, some negative value if ERROR.

Definition at line 223 of file prmat.c.

224{
225 return mat->lines[row][0];
226}

Referenced by prmatSaveMatrix().

◆ prmatGetPixels()

unsigned int prmatGetPixels ( PRMAT * mat,
int row )
extern

Returns number of pixels intersected by the given line of response.

Precondition
0<=row<=prmatGetLORS(*mat) && mat is initialized.
Parameters
matpointer to the projection matrix.
rowindex of the line of response for which the number of pixels is returned.
Returns
number of pixels intersected by given line of response, some negative value if ERROR.

Definition at line 282 of file prmat.c.

283{
284 return(mat->dime[row]);
285}

Referenced by prmatReadMatrix(), prmatSaveMatrix(), radonBackTransformPRM(), radonFwdTransformPRM(), radonSetLORS(), and radonSetLUT().

◆ prmatGetRays()

unsigned int prmatGetRays ( PRMAT * mat,
int row )
extern

Returns the number of lines of response (rays) intersecting the pixel in place 'row'.

Precondition
0<=row<=prmatGetPIX(*mat) && mat is initialized.
Parameters
matpointer to a projection matrix.
rowindex of the pixel for which the number of lors is returned.
Returns
number of lines of response intersecting the pixel, some negative value if ERROR.

Definition at line 237 of file prmat.c.

238{
239 return mat->lines[row][1];
240}

Referenced by prmatReadMatrix(), and prmatSaveMatrix().

◆ prmatGetRows()

unsigned int prmatGetRows ( PRMAT * mat)
extern

Returns number of rows (lines of response) in the given projection matrix.

Precondition
mat is initialized.
Parameters
matpointer to the projection matrix.
Returns
number of rows in the given projection matrix, some negative value if ERROR.

Definition at line 267 of file prmat.c.

268{
269 //NOTE no checking on parameters to accelerate iteration
270 return(mat->dimr);
271}

Referenced by prmatSaveMatrix(), and radonSetLORS().

◆ prmatGetXCoord()

unsigned int prmatGetXCoord ( PRMAT * mat,
int row,
int pix )
extern

Returns the x-coordinate of a pixel in place (row,pix) in the given projection matrix.

Precondition
0<=row<=prmatGetLORS(*mat) && 0<=pix<=prmatGetPixels(row,*mat) && mat is initialized.
Parameters
matpointer to a projection matrix.
rowthe row index.
pixthe (non-zero) pixel index.
Returns
coordinate of the referred pixel, some negative value if ERROR.

Definition at line 312 of file prmat.c.

313{
314 return (int)(mat->fact[row][pix][0]);
315}

Referenced by prmatSaveMatrix(), radonBackTransformPRM(), radonFwdTransformPRM(), radonSetLORS(), and radonSetLUT().

◆ prmatGetYCoord()

unsigned int prmatGetYCoord ( PRMAT * mat,
int row,
int pix )
extern

Returns the y-coordinate of a pixel in place (row,pix) in the given projection matrix.

Precondition
0<=row<=prmatGetLORS(*mat) && 0<=pix<=prmatGetPixels(row,*mat) && mat is initialized.
Parameters
matpointer to a projection matrix.
rowthe row index.
pixthe (non-zero) pixel index.
Returns
coordinate of the referred pixel, some negative value if ERROR.

Definition at line 327 of file prmat.c.

328{
329 return (int)(mat->fact[row][pix][1]);
330}

Referenced by prmatSaveMatrix(), radonBackTransformPRM(), radonFwdTransformPRM(), radonSetLORS(), and radonSetLUT().

◆ prmatInit()

void prmatInit ( PRMAT * mat)
extern

Initializes PRMAT datatype for use. To be utilised before any use of PRMAT type variables.

Parameters
matpointer to projection matrix to be initialized.

Definition at line 22 of file prmat.c.

23{
24 if(PRMAT_VERBOSE) printf("PRMAT:prmatInit() \n");
25
26 /*init the information of projection matrix*/
27 //buffer mat to contain zero
28 memset(mat, 0, sizeof(PRMAT));
29 mat->type=PRMAT_TYPE_NA;
30 mat->viewNr=0;
31 mat->binNr=0;
32 mat->mode=PRMAT_DMODE_01;
33 mat->prmatfov= (int*)NULL;
34 mat->max=mat->min=0.0;
35 mat->scaling_factor=1.0;
36 mat->factor_sum=0.0;
37 mat->factor_sqr_sum=(float*)NULL;
38
39 /*init look-up table*/
40 mat->nrp=0;
41 mat->lines=mat->_linesdata=(unsigned int**)NULL; //data array
42
43 /*init projection data*/
44 mat->dimr=0;
45 mat->dime=(unsigned int*)NULL;
46 mat->fact=mat->_factdata=(unsigned short int***)NULL; //data array
47
48 mat->status=PRMAT_STATUS_INITIALIZED;
49}
char type
Scanner information on the prmat. 0=ECAT931 1=GE Advance.
Definition libtpcrec.h:166
int mode
Discretisation model utilised.
Definition libtpcrec.h:174

Referenced by radonSetLORS().

◆ prmatReadMatrix()

int prmatReadMatrix ( char * fname,
PRMAT * mat )
extern

Reads one projection matrix from the given file to the given PRMAT structure mat.

Precondition
mat is initialized.
Postcondition
a projection matrix is read from the file fname.
Parameters
fnamefile name to read.
matpointer to the projection matrix datatype.
Returns
0 if OK.

Definition at line 550 of file prmat.c.

551{
552 unsigned int fov[2], *dimentry=NULL, *nrlor, *iptr, dimtmp, count=0;
553 unsigned int row, lor=0, ind, fac;
554 unsigned short int *nrlor_c, *nrlor_l, *usiptr, *usiptr_c;
555 unsigned short int x_coordinate=0, y_coordinate=0, value=0;
556 float *sqrsum=NULL, *fptr, sqrtmp;
557 FILE *fp;
558
559 if(PRMAT_VERBOSE) printf("\n PRMAT:prmatReadMatrix(%s,mat) \n",fname);
560 if(mat->status==PRMAT_STATUS_UNINITIALIZED) return(1);
561 prmatEmpty(mat);
562
563 fp=fopen(fname,"rb");
564 if(fp==NULL) return(1);
565
566 //read first the statical parts of the structure
567 if(fread(&(mat->status),sizeof(int),1,fp)==0) {fclose(fp); return(2);}
568 if(PRMAT_VERBOSE) printf("PRMAT: status: %i \n",mat->status);
569 if(fread(&(mat->type),sizeof(int),1,fp)==0) {fclose(fp); return(2);}
570 if(PRMAT_VERBOSE) printf("PRMAT: scanner type: %i \n",mat->type);
571 if(fread(&(mat->viewNr),sizeof(int),1,fp)==0) {fclose(fp); return(2);}
572 if(fread(&(mat->binNr),sizeof(int),1,fp)==0) {fclose(fp); return(2);}
573 if(fread(&(mat->imgDim),sizeof(int),1,fp)==0) {fclose(fp); return(2);}
574 if(PRMAT_VERBOSE)
575 printf("PRMAT: scanner geometrics: (%i,%i,%i) \n",
576 mat->viewNr,mat->binNr,mat->imgDim);
577 if(fread(&(mat->mode),sizeof(int),1,fp)==0) {fclose(fp); return(2);}
578 if(PRMAT_VERBOSE) printf("PRMAT: discretisation mode: %i \n",mat->mode);
579 if(fread(fov,sizeof(int),1,fp)==0) {fclose(fp); return(2);}
580 if(fread((fov+1),sizeof(int),1,fp)==0) {fclose(fp); return(2);}
581 mat->prmatfov=calloc(2,sizeof(int));
582 mat->prmatfov[0]=fov[0];
583 mat->prmatfov[1]=fov[1];
584 if(PRMAT_VERBOSE)
585 printf("PRMAT: FOV: (%i,%i) \n", mat->prmatfov[0],mat->prmatfov[1]);
586 // Read min, max, sum and scaling factor.
587 if(fread(&(mat->min),sizeof(float),1,fp)==0) {fclose(fp); return(2);}
588 if(PRMAT_VERBOSE) printf("PRMAT: min: %f \n",mat->min);
589 if(fread(&(mat->max),sizeof(float),1,fp)==0) {fclose(fp); return(2);}
590 if(PRMAT_VERBOSE) printf("PRMAT: max: %f \n",mat->max);
591 if(fread(&(mat->factor_sum),sizeof(float),1,fp)==0) {fclose(fp); return(2);}
592 if(PRMAT_VERBOSE) printf("PRMAT: sum of all factors: %f \n",mat->factor_sum);
593 if(fread(&(mat->scaling_factor),sizeof(float),1,fp)==0) {fclose(fp); return(2);}
594 if(PRMAT_VERBOSE) printf("PRMAT: scaling factor: %f \n",mat->scaling_factor);
595
596 // If projection matrix has been occupied.
597 if(mat->status >= PRMAT_STATUS_BS_OCCUPIED){
598 if(PRMAT_VERBOSE) printf("PRMAT: reading projection matrix \n");
599 if(fread(&(mat->dimr),sizeof(int),1,fp)==0) {fclose(fp); return(2);}
600 if(PRMAT_VERBOSE)
601 printf("PRMAT: number of rows in the projection matrix: %i \n",mat->dimr);
602 //read square sums
603 sqrsum=calloc(mat->dimr,sizeof(float));
604 for(row=0, fptr=sqrsum;row<(mat->dimr); row++, fptr++) {
605 if(fread(&sqrtmp,sizeof(float),1,fp)==0) {fclose(fp); return(2);}
606 *fptr=sqrtmp;
607 }
608 //read dime
609 dimentry=(unsigned int*)calloc(mat->dimr,sizeof(int));
610 count = 0;
611 for(row=0,iptr=dimentry;row<(mat->dimr);row++,iptr++){
612 if(fread(&dimtmp,sizeof(int),1,fp)==0) {fclose(fp); return(2);}
613 *iptr=dimtmp;
614 count += dimtmp;
615 }
616
617 //ready to allocate; NOTE that dime is also set in function prmatAllocate()
618 prmatAllocate(mat,1,mat->dimr,dimentry);
619 if(PRMAT_VERBOSE)
620 printf("PRMAT:prmatAllocate(mat) done in prmatReadMatrix(%s,mat)\n",fname);
621
622 //now we can set square sums
623 for(row=0, fptr=sqrsum;row<(mat->dimr);row++, fptr++){
624 mat->factor_sqr_sum[row]=*fptr;
625 }
626 //read the actual data _factdata
627 for(row=0;row<(mat->dimr);row++){
628 //read coordinates and values in every row
629 for(fac=0;fac<prmatGetPixels(mat,row);fac++){
630 if(fread(&x_coordinate,sizeof(unsigned short int),1,fp)==0) {
631 fclose(fp); return(2);}
632 mat->fact[row][fac][0]=x_coordinate;
633 if(fread(&y_coordinate,sizeof(unsigned short int),1,fp)==0) {
634 fclose(fp); return(2);}
635 mat->fact[row][fac][1]=y_coordinate;
636 if(fread(&value,sizeof(unsigned short int),1,fp)==0) {
637 fclose(fp); return(2);}
638 mat->fact[row][fac][2]=value;
639 }
640 }
641 }// END OF READING PROJECTIONS
642
643 // If look-up table has been occupied.
644 if(mat->status == PRMAT_STATUS_LU_OCCUPIED){
645 if(PRMAT_VERBOSE) printf("PRMAT: reading look-up table \n");
646 if(fread(&(mat->nrp),sizeof(int),1,fp)==0) {fclose(fp); return(2);}
647 if(PRMAT_VERBOSE)
648 printf("PRMAT: number of pixels inside the FOV: %i \n",mat->nrp);
649 //read nrlor
650 nrlor_c=(unsigned short int*)calloc(mat->nrp,sizeof(unsigned short int));
651 nrlor_l=(unsigned short int*)calloc(mat->nrp,sizeof(unsigned short int));
652
653 //first coordinates of pixels.
654 usiptr = nrlor_c;
655 for(row=0; row<mat->nrp; row++, usiptr++){
656 // Read next coordinate from file.
657 if(fread(usiptr,sizeof(unsigned short int),1,fp)==0) {fclose(fp); return(2);}
658 }
659 //then number of lors hitting a pixel
660 usiptr = nrlor_l;
661 for(row=0; row<mat->nrp; row++, usiptr++){
662 // Read next lornr from file.
663 if(fread(usiptr,sizeof(unsigned short int),1,fp)==0) {fclose(fp); return(2);}
664 }
665
666 if(PRMAT_VERBOSE){
667 // Get number of lors in lut.
668 usiptr = nrlor_l;
669 count = 0;
670 for(row=0; row<mat->nrp; row++, usiptr++){
671 count += *usiptr;
672 }
673 printf("PRMAT: nr of lors in lut: %i \n",count);
674 //printf(" nr of lors in ave: %i \n",count/mat->nrp);
675 }
676
677 // Copy list usi format to integer list.
678 nrlor = (unsigned int*)calloc(mat->nrp,sizeof(int));
679 usiptr = nrlor_l;
680 iptr = nrlor;
681 for(row=0; row<mat->nrp; row++, iptr++){
682 *iptr = (int)*usiptr++;
683 }
684
685 // Now we can allocate memory for look-up table.
686 prmatAllocate(mat, 0, mat->nrp, nrlor);
687 if(PRMAT_VERBOSE)
688 printf("PRMAT:prmatAllocate(mat) done in prmatReadMatrix(%s,mat)\n",fname);
689 // And fill mat->lines.
690 usiptr_c = nrlor_c;
691 usiptr = nrlor_l;
692 for(row=0;row<mat->nrp;row++ , usiptr++, usiptr_c++){
693 mat->lines[row][0] = *usiptr_c;
694 mat->lines[row][1] = *usiptr;
695 }
696
697 // Read the data _linesdata.
698 for(row=0;row<prmatGetPIX(mat);row++){
699 for(ind=0; ind<prmatGetRays(mat,row); ind++){
700 if(fread(&lor,sizeof(unsigned int),1,fp)==0) {fclose(fp); return(2);}
701 mat->lines[row][ind+2] = lor;
702 }
703 }
704
705 free((unsigned short int*)nrlor_l);
706 free((unsigned short int*)nrlor_c);
707 }// END OF READING LOOK-UP TABLE
708
709 if(PRMAT_VERBOSE) printf("PRMAT: prmatReadMatrix() done. \n");
710 free((float*)sqrsum); free((int*)dimentry);
711
712 fclose(fp);
713
714 return(0);
715}
unsigned int prmatGetPIX(PRMAT *mat)
Definition prmat.c:210
unsigned int prmatGetRays(PRMAT *mat, int row)
Definition prmat.c:237
void prmatEmpty(PRMAT *mat)
Definition prmat.c:56
int prmatAllocate(PRMAT *mat, int set, unsigned int rows, unsigned int *coords)
Definition prmat.c:105
unsigned int prmatGetPixels(PRMAT *mat, int row)
Definition prmat.c:282

◆ prmatSaveMatrix()

int prmatSaveMatrix ( PRMAT * mat)
extern

Adds the given projection matrix to the file called prTDXXYY.prm. Where T is the type of the scanner (E=ECAT931 and G=GE Advance), D is the type of discretisation (0='0/1', 1='length of intersection' and 2='exact area'), XX is the major semiaxe of the FOV, and YY the minor semiaxe. If file already exists it is NOT created or rewritten.

Precondition
mat is initialized (contains a projection matrix).
Postcondition
mat is saved in the file prTDXXYY.prm.
Parameters
matpointer to the projection matrix to be saved.
Returns
0 if OK.

Definition at line 428 of file prmat.c.

429{
430 char matrixfile[FILENAME_MAX], semi_x_c[2], semi_y_c[2], mod[2];
431 int semi_x=mat->prmatfov[0], semi_y=mat->prmatfov[1], mode=mat->mode, itmp;
432 unsigned short int x_coordinate, y_coordinate, value, p_coord, lors;
433 unsigned int lor, row, fac, ind;
434 float ftmp;
435 FILE *fp;
436
437 //Compose the file name to write
438 sprintf(semi_x_c,"%i",semi_x);
439 sprintf(semi_y_c,"%i",semi_y);
440 //decide the type
441 if(mat->type==PRMAT_TYPE_ECAT931) strcpy(matrixfile,"prE");
442 else
443 if(mat->type==PRMAT_TYPE_GE) strcpy(matrixfile,"prG");
444 else strcpy(matrixfile,"prN");
445 //decide the mode
446 sprintf(mod,"%i",mode);
447 strcat(matrixfile,mod);
448 strcat(matrixfile,semi_x_c);
449 strcat(matrixfile,semi_y_c);
450 strcat(matrixfile,".prm");
451
452 if(access(matrixfile, 0) != -1) {
453 if(PRMAT_VERBOSE) printf("PRMAT:File %s already exists.\n", matrixfile);
454 return(0);
455 }
456
457 fp=fopen(matrixfile,"wb+");
458 if(fp==NULL) return(1);
459
460 // Save status.
461 fwrite(&(mat->status),sizeof(int),1,fp);
462
463 // Save type of the scanner.
464 fwrite(&(mat->type),sizeof(int),1,fp);
465
466 // Save scanner geometrics.
467 fwrite(&(mat->viewNr),sizeof(int),1,fp);
468 fwrite(&(mat->binNr),sizeof(int),1,fp);
469 fwrite(&(mat->imgDim),sizeof(int),1,fp);
470
471 // Save mode.
472 fwrite(&(mat->mode),sizeof(int),1,fp);
473
474 // Save FOV.
475 fwrite(&(mat->prmatfov[0]),sizeof(int),1,fp);
476 fwrite(&(mat->prmatfov[1]),sizeof(int),1,fp);
477
478 // Save min, max, sum and scaling factor.
479 fwrite(&(mat->min),sizeof(float),1,fp);
480 fwrite(&(mat->max),sizeof(float),1,fp);
481 fwrite(&(mat->factor_sum),sizeof(float),1,fp);
482 fwrite(&(mat->scaling_factor),sizeof(float),1,fp);
483
484 // If projection matrix is set.
485 if(mat->status >= PRMAT_STATUS_BS_OCCUPIED){
486
487 fwrite(&(mat->dimr),sizeof(int),1,fp);
488 //square sums
489 for(row=0;row<prmatGetRows(mat);row++){
490 ftmp=prmatGetFactorSqrSum(mat,row);
491 fwrite(&ftmp,sizeof(float),1,fp);
492 }
493 //dime
494 for(row=0;row<prmatGetRows(mat);row++){
495 itmp=prmatGetPixels(mat,row);
496 fwrite(&itmp,sizeof(int),1,fp);
497 }
498 //the actual data _factdata
499 for(row=0;row<prmatGetRows(mat);row++){
500 //coordinates and values in every row
501 for(fac=0;fac<prmatGetPixels(mat,row);fac++){
502 x_coordinate=prmatGetXCoord(mat,row,fac);
503 fwrite(&x_coordinate,sizeof(unsigned short int),1,fp);
504 y_coordinate=prmatGetYCoord(mat,row,fac);
505 fwrite(&y_coordinate,sizeof(unsigned short int),1,fp);
506 //NOTE that we wan't to save the values in unsigned short ints
507 value=mat->fact[row][fac][2];
508 fwrite(&value,sizeof(unsigned short int),1,fp);
509 }
510 }
511 }// END OF SAVING PROJECTION MATRIX.
512
513 // If look-up table is set.
514 if(mat->status == PRMAT_STATUS_LU_OCCUPIED){
515 //save first the statical parts of the structure
516 fwrite(&(mat->nrp),sizeof(int),1,fp);
517 //save lines: first coordinates of pixels inside the fov,
518 for(row=0;row<prmatGetPIX(mat);row++){
519 p_coord=prmatGetPixCoord(mat,row);
520 fwrite(&p_coord,sizeof(unsigned short int),1,fp);
521 }
522 // then number of lors hitting a pixel.
523 for(row=0; row<prmatGetPIX(mat); row++){
524 lors=prmatGetRays(mat,row);
525 fwrite(&lors,sizeof(unsigned short int),1,fp);
526 }
527
528 //save lors
529 for(row=0;row<prmatGetPIX(mat);row++){
530 for(ind=0; ind<prmatGetRays(mat,row); ind++){
531 lor = prmatGetBinView(mat,row,ind);
532 fwrite(&lor,sizeof(unsigned int),1,fp);
533 }
534 }
535 }// END OF SAVING LOOK-UP TABLE.
536
537 fclose(fp);
538 return(0);
539}
unsigned int prmatGetBinView(PRMAT *mat, int row, int ind)
Definition prmat.c:253
unsigned int prmatGetRows(PRMAT *mat)
Definition prmat.c:267
float prmatGetFactorSqrSum(PRMAT *mat, int row)
Definition prmat.c:409
unsigned int prmatGetYCoord(PRMAT *mat, int row, int pix)
Definition prmat.c:327
unsigned int prmatGetXCoord(PRMAT *mat, int row, int pix)
Definition prmat.c:312
unsigned int prmatGetPixCoord(PRMAT *mat, int row)
Definition prmat.c:223

◆ radonBackTransform()

int radonBackTransform ( RADON * radtra,
int set,
int setNr,
float * scndata,
float * imgdata )
extern

Transforms the given sinogram in Radon domain to spatial domain. Parameters of the discrete Radon transform are stored in the RADON object. Transform is calculated only in those angles belonging into given subset. Subset contains angles starting from the index 'set' with spacing 'setNr'. Discretisation model utilised in this function is '0/1' or 'length of intersection' according to the given RADON object.

Precondition
scndata contains the projections in v x b lines of response.
Postcondition
scndata is mapped into the cartesian space.
Parameters
radtracontains an initialized radon transform object.
settells which set is to be utilized; 0 < set < setNr-1
setNrnumber of subsets
scndatav x b vector contains the projections.
imgdatan x n vector for storing the back-projection.
Returns
int 0 if ok

Definition at line 1429 of file radon.c.

1431 {
1432 float *imgptr, *scnptr; // pointers for the image and sinogram data
1433 float *Y, *X, *Xptr, *Yptr; // pointers for the values of LOR in integer points
1434 double sinus, cosinus, tanus; // sin, cosine and tangent
1435 double shift_x, shift_y; // shift for LOR
1436 int xp, xn, yp, yn, z; //integer points
1437 int x_left, x_right, y_top, y_bottom; // limits for fast search
1438 int col, row, view, bin; //counters
1439 int binNr, viewNr, imgDim;
1440 int half, center = -1, mode = 0;
1441 float sdist;
1442 float dx, dy , loi = 1; // delta x and y and length of intersection
1443
1444 //Check that the data for this radon transform is initialized
1445 if(radtra->status != RADON_STATUS_INITIALIZED) return -1;
1446
1447 //Retrieve the data from given radon transform object
1448 mode=radonGetMO(radtra);
1449 imgDim=radonGetID(radtra);
1450 binNr=radonGetNB(radtra);
1451 viewNr=radonGetNV(radtra);
1452 sdist=radonGetSD(radtra);
1453 half=radonGetHI(radtra);
1454 center=radonGetCB(radtra);
1455
1457 // Find pixel coordinates of the contributing pixels for lines of response
1458 // corresponding to first 1/4th of angles. From these pixel coordinates
1459 // others can be calculated via symmetries in projection space.
1460 // N.B. The line of response: a*x+b*y+c=cos(view)*x+sin(view)*y+k*bin=0
1461 // => solve y: y=-x*(cos(view)/sin(view)) - k*bin
1462 // solve x: x=-y*(sin(view)/cos(view))) - k*bin
1463
1464 X=(float*)calloc(imgDim+1,sizeof(float));
1465 Y=(float*)calloc(imgDim+1,sizeof(float));
1466 if(X==NULL || Y==NULL){
1467 return -2;
1468 }
1469 Xptr=X;
1470 Yptr=Y;
1471 imgptr=imgdata;
1472 scnptr=scndata;
1473 for(view=set; view<viewNr/4; view+=setNr){
1474 // Choose the type of the line of response according to view number
1475
1476 // Length of intersection is 1.
1477 loi = 1;
1478
1479 // 0. type: view=0 -> sin(view)=0
1480 if(view==0){
1481
1482 // Choose the pixels according to sample distance and pixel size,
1483 // for angles 0 and pi/2.
1484 for(bin=0; bin<binNr; bin++){
1485 col=floor((float)(bin+.5*sdist)*sdist);
1486 if(col==imgDim) col=imgDim-1;
1487
1488 // Iterate through the entries in the image matrix.
1489 // Calculate raysums for LORs in the same (absolute) distance from origin.
1490 for(row=0; row<imgDim; row++){
1491 imgptr[row*imgDim + col] += loi*scnptr[bin];
1492 imgptr[(imgDim - 1 - col)*imgDim + row] +=
1493 loi*scnptr[binNr*(viewNr/2) + bin];
1494 }
1495 }
1496 // End of view==0 (handles angles 0 and pi/2).
1497 } else {
1498 // Set sine and cosine for this angle.
1499 sinus=(double)radonGetSin(radtra,view);
1500 cosinus=(double)radonGetSin(radtra,viewNr/2 + view);
1501 tanus=sinus/cosinus;
1502
1504 // Set shift from origin for the first line of response (-n/2,theta).
1505 // NOTE that image matrix is on cartesian coordinate system where origin
1506 // is in the middle and shift is in pixels.
1507 shift_y = -(imgDim/2 -.5*sdist)/sinus;
1508 shift_x = -(imgDim/2 -.5*sdist)/cosinus;
1509
1510 // Evaluate the function of the first LOR in integer points [-n/2,n/2].
1511 // NOTE that image matrix is on cartesian coordinate system where origin
1512 // is in the middle.
1513 z=-imgDim/2;
1514 for(col=0; col<imgDim+1; col++){
1515 Yptr[col]=(float)(shift_y - z/tanus);
1516 Xptr[col]=(float)(shift_x - z*tanus);
1517 z++;
1518 }
1519
1520 // Set shift from the first LOR.
1521 shift_y = (double)(sdist/sinus);
1522 shift_x = (double)(sdist/cosinus);
1523
1524 // Iterate through half the bins in this view,
1525 // and determine coordinates of pixels contributing to this LOR.
1526 // NOTE that shift is added according to 'bin' in every loop.
1527 // Calculate also the length of intersection.
1528 // Others are determined via symmetry in projection space.
1529
1530 for(bin=0; bin<half; bin++){
1531
1532 // Limit (x-)indices for fast search.
1533 // Note that indices are non-negative integers.
1534
1535 x_left = floor((float)((Xptr[imgDim] + bin*shift_x) + imgDim/2));
1536 if(x_left < 0) x_left = 0;
1537 x_right = floor((float)((Xptr[0] + bin*shift_x) + imgDim/2));
1538 if(x_right <= 0) x_right = 1;
1539 if(x_right > imgDim) x_right = imgDim - 1;
1540
1541 /* Iterate through the values in vector Y, in integer points
1542 [x_left,x_rigth]. */
1543 for(z=x_left; z <= x_right; z++){
1544
1545 xp = z; //positive x-coordinate
1546 xn = imgDim - 1 - xp; //negative x-coordinate
1547
1548 // Look y from left.
1549 yp = imgDim/2 - floor(Yptr[xp + 1] + bin*shift_y) - 1;
1550 yn = imgDim - 1 - yp;
1551
1552 // If the y-value for this x (z) is inside the image grid.
1553 if(yp < imgDim && yp >= 0 && yn < imgDim && yn >= 0 && xp >= 0 &&
1554 xp < imgDim && xn < imgDim && xn >= 0)
1555 {
1556 if(!mode){
1557 loi = 1;
1558 } else {
1559 // Compute delta x and y from 'positive' coordinates.
1560 dx = 1 - (float)((Xptr[imgDim - yp] + bin*shift_x) + imgDim/2 - xp);
1561 dy = 1 - (float)(yp - (imgDim/2 - (Yptr[xp + 1] + bin*shift_y) - 1));
1562
1563 if(dx > 1 || dx < 0) dx = 1;
1564 if(dy > 1 || dy < 0) dy = 1;
1565 loi = sqrt(dx*dx + dy*dy);
1566 }
1567
1568 // Case: theta.
1569 // Add img(x,y)*k to the raysum of LOR (view,bin)
1570 imgptr[yp*imgDim + xp] += loi*scnptr[view*binNr + bin];
1571 // Add img(-x,-y)*k to the raysum of LOR (view,binNr-bin)
1572 if(bin != center)
1573 imgptr[yn*imgDim + xn] +=
1574 loi*scnptr[view*binNr + binNr - 1 - bin];
1575
1576 if(view != viewNr/4){
1577 // Mirror the original LOR on y-axis, i.e. x->-x
1578 // Case: pi-theta.
1579 // Add img(-x,y)*k to the raysum of LOR (viewNr-view,bin)
1580 imgptr[yp*imgDim + xn] += loi*scnptr[(viewNr - view)*binNr + bin];
1581 // Add img(x,-y)*k to the raysum of LOR (viewNr-view,binNr-bin)
1582 if(bin != center)
1583 imgptr[yn*imgDim + xp] +=
1584 loi*scnptr[(viewNr-view)*binNr + binNr - 1 - bin];
1585
1586 // Mirror the LOR on line x=y, i.e. x->y.
1587 // Case: pi/2-theta
1588 // Add img(-y,-x)*k to the raysum of LOR (viewNr/2-view,bin)
1589 imgptr[xn*imgDim + yn] += loi*scnptr[(viewNr/2 - view)*binNr + bin];
1590 // Add img(y,x)*k to the raysum of LOR (viewNr/2-view,binNr-bin)
1591 if(bin != center)
1592 imgptr[xp*imgDim + yp] +=
1593 loi*scnptr[(viewNr/2 - view)*binNr + binNr - 1 - bin];
1594 }
1595
1596 // Mirror the LOR on line x=y, and on y-axis i.e x->y and y->-y.
1597 // Case: pi/2+theta
1598 // Add img(y,-x)*k to the raysum of LOR (viewNr/2+view,bin)
1599 imgptr[xn*imgDim + yp] += loi*scnptr[(viewNr/2 + view)*binNr + bin];
1600 // Add img(y,-x)*k to the raysum of LOR (viewNr/2+view,binNr-bin)
1601 if(bin != center)
1602 imgptr[xp*imgDim + yn] +=
1603 loi*scnptr[(viewNr/2 + view)*binNr + binNr - 1 - bin];
1604
1605 }
1606 }
1607
1608 // Limit (y-)indices for fast search.
1609 // Note that indices are non-negative integers.
1610 y_bottom = floor((float)(Yptr[imgDim] + bin*shift_y + imgDim/2));
1611 if(y_bottom < 0) y_bottom = 0;
1612 if(y_bottom > imgDim) y_bottom = 0;
1613
1614 y_top = floor((float)(Yptr[0] + bin*shift_y + imgDim/2));
1615 if(y_top > imgDim) y_top = imgDim;
1616 if(y_top <= 0) y_top = 1;
1617
1618 /* Iterate through the values in vector X, in integer points
1619 [y_bottom,y_top]. */
1620 for(z=y_top; z >= y_bottom; z--) {
1621
1622 // Look y from this location.
1623 xp = floor(Xptr[z] + bin*shift_x) + imgDim/2;
1624 xn = imgDim - 1 - xp;
1625
1626 yp = imgDim - z - 1;
1627 yn = imgDim - yp - 1;
1628
1629 // If the x-value for this y (z) is inside the image grid.
1630 if(yp < imgDim && yp >= 0 && yn < imgDim && yn >= 0 && xp >= 0 &&
1631 xp < imgDim && xn < imgDim && xn >= 0)
1632 {
1633 if(!mode){
1634 loi = 1;
1635 } else{
1636 dx = (float)((Xptr[z] + bin*shift_x) + imgDim/2 - xp);
1637 dy = (float)(yp - (imgDim/2 - (Yptr[xp] + bin*shift_y) - 1));
1638 if(dy > 1 || dy < 0) dy = 1;
1639 loi = sqrt(dx*dx + dy*dy);
1640 }
1641 // Case: theta.
1642 // Add img(x,y)*k to the raysum of LOR (view,bin)
1643 imgptr[yp*imgDim + xp] += loi*scnptr[view*binNr + bin];
1644 // Add img(-x,-y)*k to the raysum of LOR (view,binNr-bin)
1645 if(bin != center)
1646 imgptr[yn*imgDim + xn] +=
1647 loi*scnptr[view*binNr + binNr - 1 - bin];
1648
1649 if(view != viewNr/4){
1650 // Mirror the LOR on y-axis, i.e. x->-x
1651 // Case: pi-theta.
1652 // Add img(-x,y)*k to the raysum of LOR (viewNr-view,bin)
1653 imgptr[yp*imgDim + xn] += loi*scnptr[(viewNr - view)*binNr + bin];
1654 // Add img(x,-y)*k to the raysum of LOR (viewNr-view,binNr-bin)
1655 if(bin != center)
1656 imgptr[yn*imgDim + xp] +=
1657 loi*scnptr[(viewNr-view)*binNr + binNr - 1 - bin];
1658
1659 // Mirror the LOR on line y=x, i.e. y->x.
1660 // Case: pi/2 - theta.
1661 // Add img(y,x)*k to the raysum of LOR (viewNr/2-view,bin)
1662 imgptr[xn*imgDim + yn] += loi*scnptr[(viewNr/2 - view)*binNr + bin];
1663 // Add img(-y,-x)*k to the raysum of LOR (viewNr/2-view,binNr-bin)
1664 if(bin != center)
1665 imgptr[xp*imgDim + yp] +=
1666 loi*scnptr[(viewNr/2 - view)*binNr + binNr - 1 - bin];
1667 }
1668
1669 // Mirror the LOR on line x=y, and on y-axis i.e x->y and y->-y.
1670 // Case: pi/2 + theta.
1671 // Add img(y,-x)*k to the raysum of LOR (viewNr/2+view,bin)
1672 imgptr[xn*imgDim + yp] += loi*scnptr[(viewNr/2 + view)*binNr + bin];
1673 // Add img(-y,x)*k to the raysum of LOR (viewNr-view,binNr-bin)
1674 if(bin != center)
1675 imgptr[xp*imgDim + yn] +=
1676 loi*scnptr[(viewNr/2 + view)*binNr + binNr - 1 - bin];
1677 }
1678 }
1679 } // END of X loop
1680 } // End of view>0.
1681 } // END OF VIEW LOOP
1682 free(X);
1683 free(Y);
1684 return 0;
1685} // END OF BACK (pro -> spa) TRANSFORM WITH 0/1 OR LOI-MODEL.
int radonGetMO(RADON *radtra)
Definition radon.c:119
int radonGetID(RADON *radtra)
Definition radon.c:128
int radonGetHI(RADON *radtra)
Definition radon.c:169
int radonGetNB(RADON *radtra)
Definition radon.c:148
int radonGetNV(RADON *radtra)
Definition radon.c:138
float radonGetSin(RADON *radtra, int nr)
Definition radon.c:192
int radonGetCB(RADON *radtra)
Definition radon.c:180
float radonGetSD(RADON *radtra)
Definition radon.c:159
char status
Definition libtpcrec.h:257

◆ radonBackTransformEA()

int radonBackTransformEA ( RADON * radtra,
int set,
int setNr,
float * scndata,
float * imgdata )
extern

Same as 'radonBackTransform()' but discretisation model in this function is 'exact area'.

Parameters
radtracontains an initialized radon transform object.
settells which set is to be utilized; 0 < set < setNr-1
setNrnumber of subsets
scndatav x b vector contains the projections.
imgdatan x n vector for storing the back-projection.
Returns
int 0 if ok

Definition at line 1696 of file radon.c.

1698 {
1699 float *imgptr, *scnptr; // pointers for the image and sinogram data
1700 float *Y, *X, *Xptr, *Yptr; // pointers for the values of LOR in integer points
1701 double sinus, cosinus, tanus; // sin, cosine and tangent
1702 double shift_x, shift_y; // shift for LOR
1703 int xp, xn, yp, yn, z, xp2; //integer points
1704 int x_left, x_right, y_top, y_bottom; // limits for fast search
1705 int col, col1, col2, row, view, bin; //counters
1706 int binNr, viewNr, imgDim, errors=0;
1707 int half, center = -1;
1708 float sdist;
1709 float a=0,b=0, c=0, d=0, g=0, h=0, A;
1710 float dx, dy , eps1 = 0, eps2 = 0, eps3 = 0; // delta x and y and factors.
1711
1712 // Check that the data for this radon transform is initialized.
1713 if(radtra->status != RADON_STATUS_INITIALIZED) return -1;
1714
1715 // Retrieve the data from given radon transform object.
1716 //mode=radonGetMO(radtra); // Should be 2.
1717 imgDim=radonGetID(radtra);
1718 binNr=radonGetNB(radtra);
1719 viewNr=radonGetNV(radtra);
1720 sdist=radonGetSD(radtra);
1721 half=radonGetHI(radtra);
1722 center=radonGetCB(radtra);
1723
1724 // Array for storing values f_x.
1725 X=(float*)calloc(imgDim+1,sizeof(float));
1726 // Array for storing values f_y.
1727 Y=(float*)calloc(imgDim+1,sizeof(float));
1728 if(X==NULL || Y==NULL){
1729 return -2;
1730 }
1731 Xptr=X;
1732 Yptr=Y;
1733
1734 imgptr=imgdata;
1735 scnptr=scndata;
1736
1738 // Find pixel coordinates of the contributing pixels for tubes of response
1739 // belonging to first 1/4th of angles. From these pixel coordinates
1740 // others can be calculated via symmetries in projection space.
1741 // N.B. The line of response: a*x+b*y+c
1742 // => solve y: y=-x/tan(view) + s*(cos(theta)/tan(theta) + sin(theta))
1743 // solve x: x=-y*tan(theta) + s*(sin(theta)*tan(theta) + cos(theta))
1744
1745 for(view=set; view<=viewNr/4; view+=setNr){
1746 // view=0 -> sin(theta)=0
1747 if(view==0){
1748
1749 // Choose column(s) according to sample distance for angles 0 and pi/2.
1750 col1 = 0;
1751 col2 = 0;
1752 for(bin = 0; bin < half; bin++){
1753
1754 col1 = col2;
1755 col2 = floor((float)(bin + 1)*sdist);
1756
1757 // Determine factor epsilon.
1758 if(col1 == col2){
1759 eps1 = sdist;
1760 eps2 = 0;
1761 eps3 = 0;
1762 }
1763 if((col2-col1) == 1){
1764 eps1 = (float)(col2 - (bin)*sdist);
1765 eps2 = 0;
1766 eps3 = (float)((bin+1)*sdist - col2);
1767
1768 }
1769 // If sdist > pixel size!
1770 if((col2-col1) > 1){
1771 eps1 = (float)(col1 + 1 - (bin)*sdist);
1772 eps2 = 1; // middle pixel.
1773 eps3 = (float)((bin+1)*sdist - col2);
1774
1775 }
1776
1777 /* Iterate through the entries in the image matrix.
1778 Calculate raysums for two LORs in the same distance from origin
1779 (do halfturn). */
1780 for(row=0; row<imgDim; row++){
1781 if(!eps3){
1782 imgptr[row*imgDim + col1] += eps1 * scnptr[bin];
1783 if(bin != center)
1784 imgptr[row*imgDim + (imgDim - 1 - col1)]+=
1785 eps1 * scnptr[binNr-bin-1] ;
1786 imgptr[(imgDim - 1 - col1)*imgDim + row] +=
1787 eps1 * scnptr[binNr*(viewNr/2) + bin];
1788 if(bin != center)
1789 imgptr[col1*imgDim + row]+=
1790 eps1 * scnptr[binNr*(viewNr/2) + (binNr-bin-1)];
1791 }
1792 if(eps3 && !eps2){
1793 imgptr[row*imgDim + col1] += eps1 * scnptr[bin];
1794 imgptr[row*imgDim + col2] += eps3 *scnptr[bin];
1795 if(bin != center){
1796 imgptr[row*imgDim + (imgDim - 1 - col1)] +=
1797 eps1 * scnptr[binNr-bin-1];
1798 imgptr[row*imgDim+(imgDim-1-col2)] +=
1799 eps3*scnptr[binNr-bin-1];
1800 }
1801
1802 imgptr[(imgDim-1-col1)*imgDim+row] +=
1803 eps1* scnptr[binNr*(viewNr/2) + bin];
1804 imgptr[(imgDim-1-col2)*imgDim+row] +=
1805 eps3*scnptr[binNr*(viewNr/2) + bin];
1806 if(bin != center){
1807 imgptr[col1*imgDim + row] +=
1808 eps1 * scnptr[binNr*(viewNr/2) + (binNr-bin-1)];
1809 imgptr[col2*imgDim + row] +=
1810 eps3 *scnptr[binNr*(viewNr/2) + (binNr-bin-1)];
1811 }
1812 }
1813 if(eps3 && eps2){
1814 for(col = col1; col<=col2; col++){
1815 if(col == col1){
1816 imgptr[row*imgDim + col1]+= eps1 * scnptr[bin];
1817 if(bin != center)
1818 imgptr[row*imgDim + (imgDim - 1 - col1)]+=
1819 eps1 * scnptr[binNr-bin-1] ;
1820 imgptr[(imgDim - 1 - col1)*imgDim + row]+=
1821 eps1 * scnptr[binNr*(viewNr/2) + bin];
1822 if(bin != center)
1823 imgptr[col1*imgDim + row]+=
1824 eps1 * scnptr[binNr*(viewNr/2) + (binNr-bin-1)];
1825 }
1826 if(col == col2){
1827 imgptr[row*imgDim + col2]+= eps3 * scnptr[bin];
1828 if(bin != center)
1829 imgptr[row*imgDim + (imgDim - 1 - col2)]+=
1830 eps3 * scnptr[binNr-bin-1];
1831 imgptr[(imgDim - 1 - col2)*imgDim + row]+=
1832 eps3 * scnptr[binNr*(viewNr/2) + bin];
1833 if(bin != center)
1834 imgptr[col2*imgDim + row]+=
1835 eps3 * scnptr[binNr*(viewNr/2) + (binNr-bin-1)];
1836 }
1837 if(col != col1 && col != col2){
1838 imgptr[row*imgDim + col]+= eps2 * scnptr[bin] ;
1839 if(bin != center)
1840 imgptr[row*imgDim + (imgDim - 1 - col)]+=
1841 eps2 * scnptr[binNr-bin-1];
1842 imgptr[(imgDim - 1 - col)*imgDim + row]+=
1843 eps2 * scnptr[binNr*(viewNr/2) + bin];
1844 if(bin != center)
1845 imgptr[col*imgDim + row]+=
1846 eps2 * scnptr[binNr*(viewNr/2) + (binNr-bin-1)];
1847 }
1848 }
1849 }
1850 }
1851 }
1852 // End of view==0 (handles angles 0 and pi/2).
1853 } else {
1854
1855 // Set sine and cosine for this angle.
1856 sinus = (double)radonGetSin(radtra,view);
1857 cosinus = (double)radonGetSin(radtra,viewNr/2 + view);
1858 tanus = sinus/cosinus;
1859
1860 // Set shift from origin for the first line of response (-n/2,theta).
1861 // NOTE that image matrix is on cartesian coordinate system where origin
1862 // is in the middle and shift is in pixels.
1863 shift_y = -(imgDim/2)/sinus;
1864 shift_x = -(imgDim/2)/cosinus;
1865
1866 // Evaluate the function of the first LOR in integer points [-n/2,n/2].
1867 // NOTE that image matrix is on cartesian coordinate system where origin
1868 // is in the middle.
1869 z=-imgDim/2;
1870 for(col=0; col<imgDim+1; col++){
1871 Yptr[col]=(float)(-z/tanus + shift_y);
1872 Xptr[col]=(float)(-z*tanus + shift_x);
1873 z++;
1874 }
1875
1876 // Set shift from the first LOR.
1877 shift_y = (double)(sdist/sinus);
1878 shift_x = (double)(sdist/cosinus);
1879
1880 // Iterate through half the bins in this view,
1881 // and determine coordinates of pixels contributing to this LOR.
1882 // NOTE that shift is added according to 'bin' in every loop.
1883 // Calculate also the length of intersection.
1884 // Others are determined via symmetry in projection space.
1885
1886 for(bin=0; bin<half; bin++){
1887
1888 // Limit (x-)indices for fast search.
1889 // Note that indices are non-negative integers.
1890
1891 x_left = floor((float)(Xptr[imgDim] + bin*shift_x + imgDim/2));
1892 if(x_left < 0) x_left = 0;
1893
1894 x_right = floor((float)(Xptr[0] + bin*shift_x + imgDim/2));
1895 if(x_right <= 0) x_right = 1;
1896 if(x_right > imgDim) x_right = imgDim - 1;
1897
1898 /* Iterate through the values in vector Y, in integer points
1899 [x_left,x_rigth]. */
1900 for(z=x_left; z <= x_right; z++) {
1901
1902 xp = z; //positive x-coordinate
1903 xn = imgDim - 1 - xp; //negative x-coordinate
1904
1905 // Look y from left.
1906 yp = imgDim/2 - floor(Yptr[xp + 1] + bin*shift_y) - 1;
1907 yn = imgDim - 1 - yp;
1908
1909 // If the y-value for this x (z) is inside the image grid.
1910 if(yp < imgDim && yp >= 0 && yn < imgDim && yn >= 0 && xp >= 0 &&
1911 xp < imgDim && xn < imgDim && xn >= 0)
1912 {
1913
1914 // NOTE that pixels found in this part are always hit from right side.
1915 // Compute a := |AF| and b := |FB|.
1916 a = (float)(xp + 1 - (imgDim/2 + Xptr[imgDim - yp] + bin*shift_x));
1917 b = (float)(floor(Yptr[xp + 1] + bin*shift_y) + 1 - (Yptr[xp + 1] +
1918 bin*shift_y));
1919
1920 // Calculate the area of lower triangle.
1921 A = a*b/2;
1922
1923 // c := |FC|
1924 c = (float)(xp + 1 - (imgDim/2 + Xptr[imgDim - yp] +
1925 (bin+1)*shift_x));
1926
1927 if(c > 0){
1928 // d := |FD|
1929 d = (float)(floor(Yptr[xp + 1] + (bin+1)*shift_y) + 1 -
1930 (Yptr[xp + 1] + (bin+1)*shift_y));
1931 // Subtract the area of upper triangle.
1932 A = A - c*d/2;
1933 }
1934
1935 eps1 = A;
1936 if((eps1 < 0 || eps1 > 1) && RADON_VERBOSE){
1937 printf("RADON: Error in factor: eps1=%.5f \n",eps1);
1938 errors++;
1939 }
1940
1941 // Case: theta.
1942 // Add img(x,y)*k to the raysum of TOR (view,bin)
1943 imgptr[yp*imgDim + xp]+= eps1 * scnptr[view*binNr + bin];
1944 // Add img(-x,-y)*k to the raysum of LOR (view,binNr-bin)
1945 if(bin != center)
1946 imgptr[yn*imgDim + xn]+=
1947 eps1 * scnptr[view*binNr + binNr - 1 - bin];
1948
1949 if(view != viewNr/4){
1950 // Mirror the original LOR on y-axis, i.e. x->-x
1951 // Case: pi-theta.
1952 // Add img(-x,y)*k to the raysum of LOR (viewNr-view,bin)
1953 imgptr[yp*imgDim + xn]+=
1954 eps1 * scnptr[(viewNr - view)*binNr + bin];
1955 // Add img(x,-y)*k to the raysum of LOR (viewNr-view,binNr-bin)
1956 if(bin != center)
1957 imgptr[yn*imgDim + xp]+=
1958 eps1 * scnptr[(viewNr-view)*binNr + binNr - 1 - bin];
1959
1960 // Mirror the LOR on line x=y, i.e. x->y.
1961 // Case: pi/2-theta
1962 // Add img(-y,-x)*k to the raysum of LOR (viewNr/2-view,bin)
1963 imgptr[xn*imgDim + yn]+=
1964 eps1 * scnptr[(viewNr/2 - view)*binNr + bin];
1965 // Add img(y,x)*k to the raysum of LOR (viewNr/2-view,binNr-bin)
1966 if(bin != center)
1967 imgptr[xp*imgDim + yp]+=
1968 eps1 * scnptr[(viewNr/2 - view)*binNr + binNr - 1 - bin];
1969 }
1970
1971 // Mirror the LOR on line x=y, and on y-axis i.e x->y and y->-y.
1972 // Case: pi/2+theta
1973 // Add img(y,-x)*k to the raysum of LOR (viewNr/2+view,bin)
1974 imgptr[xn*imgDim + yp]+= eps1 * scnptr[(viewNr/2 + view)*binNr + bin];
1975 // Add img(y,-x)*k to the raysum of LOR (viewNr/2+view,binNr-bin)
1976 if(bin != center)
1977 imgptr[xp*imgDim + yn]+=
1978 eps1 * scnptr[(viewNr/2 + view)*binNr + binNr - 1 - bin];
1979 }
1980 }
1981
1982 // Limit (y-)indices for fast search.
1983 // Note that indices are non-negative integers.
1984 y_bottom = floor((float)(Yptr[imgDim] + bin*shift_y + imgDim/2));
1985 if(y_bottom < 0) y_bottom = 0;
1986 if(y_bottom > imgDim) y_bottom = 0;
1987
1988 y_top = floor((float)(Yptr[0] + bin*shift_y + imgDim/2));
1989 if(y_top > imgDim) y_top = imgDim;
1990 if(y_top <= 0) y_top = 1;
1991
1992 // Iterate through the values in vector X, in integer points [y_bottom,y_top].
1993 for(z=y_top; z >= y_bottom; z--) {
1994
1995 // Look y from this location.
1996 xp = floor(Xptr[z] + bin*shift_x) + imgDim/2;
1997 xn = imgDim - 1 - xp;
1998
1999 yp = imgDim - z - 1;
2000 yn = imgDim - yp - 1;
2001
2002 // If the x-value for this y (z) is inside the image grid.
2003 if(yp < imgDim && yp >= 0 && yn < imgDim && yn >= 0 && xp >= 0
2004 && xp < imgDim && xn < imgDim && xn >= 0)
2005 {
2006 eps1=eps2=eps3=0;
2007
2008 dx = (float)(Xptr[z] + bin*shift_x + imgDim/2 - xp);
2009 dy = (float)(Yptr[xp] + bin*shift_y - z + imgDim/2);
2010
2011 if(dy < 1){ // Cases 3,4,5 and 6.
2012 // 1. PART
2013 // a := |HA|
2014 a = dy;
2015 // b := |HB| (b < 1 for angles in [0,pi/4))
2016 b = dx;
2017 // h := height of rectangle R.
2018 h = a + shift_y;
2019 if(h > 1){ // Cases 3,4 and 5.
2020 h = 1;
2021 g = b + shift_x;
2022 if(g > 1){ // Cases 3 and 4.
2023 g = 1;
2024 xp2 =floor(Xptr[z+1] + (bin+1)*shift_x) + imgDim/2;
2025 if(xp == xp2){ // Case 4.
2026 // c := |FC|
2027 c = (float)(xp + 1 - (imgDim/2 + Xptr[z+1] + (bin+1)*shift_x));
2028 // d := |FD|
2029 d = (float)(floor(Yptr[xp + 1] + (bin+1)*shift_y) + 1 -
2030 (Yptr[xp + 1] + (bin+1)*shift_y));
2031 eps1 = 1 - (a*b + c*d)/2;
2032 eps2 = 0;
2033 // Lower triangle on the next pixel (x+1,y).
2034 eps3 = (1 - d)*(b + shift_x - 1)/2;
2035 if((eps1<0 || eps1>1 || eps2<0 || eps2>1 || eps3<0 || eps3>1)
2036 && RADON_VERBOSE) printf(
2037 "4: (%i,%i) eps1=%f | (%i,%i) eps2=%f | (%i,%i) eps3=%f\n",
2038 xp,yp,eps1,xp+1,yp-1,eps2,xp+1,yp,eps3);
2039 } else{ // Case 3.
2040 // c=d=0.
2041 eps1 = 1 - a*b/2;
2042 // Calculate area on pixel in place (xp+1,yp-1).
2043 dy = (float)(Yptr[xp+1] + (bin+1)*shift_y - (z + 1) +
2044 imgDim/2);
2045 if(dy < 1){ // Case 11.
2046 // c := |HC|
2047 c = dy;
2048 // d := |HD|
2049 d = (float)(xp + 2 - (imgDim/2 + Xptr[z+1] +
2050 (bin+1)*shift_x));
2051 eps2 = c*d/2;
2052 } else { // Cases 9 and 10.
2053
2054 dx = (float)(xp + 2 - (imgDim/2 + Xptr[z+1] +
2055 (bin+1)*shift_x));
2056 if(dx < 1) { // Case 10.
2057 // g := length of rectangle Q.
2058 g = dx;
2059 // c := |CD| (on x-axis).
2060 c = dx - (float)(xp + 2 - (imgDim/2 + Xptr[z+2] +
2061 (bin+1)*shift_x));
2062 // Rectangle Q - triangle c*h (h = 1).
2063 eps2 = g - c/2;
2064 } else { // Case 9.
2065 // c := |FC|
2066 c = (float)(xp + 2 - (imgDim/2 + Xptr[z+2] +
2067 (bin+1)*shift_x));
2068 // d := |FD|
2069 d = (float)(floor(Yptr[xp + 2] + (bin+1)*shift_y) + 2 -
2070 (Yptr[xp + 2] + (bin+1)*shift_y));
2071 // Rectangle Q - triangle CFD.
2072 eps2 = 1 - c*d/2;
2073 }
2074 }
2075 // Calculate area on pixel in place (xp+1,yp).
2076 dx = (float)(xp + 2 - (imgDim/2 + Xptr[z] + (bin+1)*shift_x));
2077 if(dx < 1){ // Case 10.
2078 // g := length of rectangle Q.
2079 g = dx;
2080 // c := |CD| (on x-axis).
2081 c = dx - (float)(xp + 2 - (imgDim/2 + Xptr[z+1] +
2082 (bin+1)*shift_x));
2083 // Rectangle Q - triangle c*h (h = 1).
2084 eps3 = g - c/2;
2085 } else { // Case 9.
2086 // c := |FC|
2087 c = (float)(xp + 2 - (imgDim/2 + Xptr[z+1] +
2088 (bin+1)*shift_x));
2089 // d := |FD|
2090 d = (float)(floor(Yptr[xp + 2] + (bin+1)*shift_y) + 1 -
2091 (Yptr[xp + 2] + (bin+1)*shift_y));
2092 // Rectangle Q - triangle CFD.
2093 eps3 = 1 - c*d/2;
2094 }
2095 if((eps1<0 || eps1>1 || eps2<0 || eps2>1 || eps3<0 || eps3>1)
2096 && RADON_VERBOSE) printf(
2097 "3/v%i: (%i,%i) eps1=%f | (%i,%i) eps2=%f | (%i,%i) eps3=%f\n",
2098 view,xp,yp,eps1,xp+1,yp-1,eps2,xp+1,yp,eps3);
2099 }
2100 } else{ // Case 5. (g < 1)
2101 // c := |DC|.
2102 c = g - (imgDim/2 + Xptr[z+1] + (bin+1)*shift_x - xp);
2103 // d := heigth
2104 d = 1;
2105 eps1 = g*h - (a*b + c*d)/2;
2106 eps2 = 0;
2107 eps3 = 0;
2108 if((eps1<0 || eps1>1 || eps2<0 || eps2>1 || eps3<0 || eps3>1)
2109 && RADON_VERBOSE) printf(
2110 "5: (%i,%i) eps1=%f | (%i,%i) eps2=%f | (%i,%i) eps3=%f\n",
2111 xp,yp,eps1,xp+1,yp-1,eps2,xp+1,yp,eps3);
2112 }
2113 } else { // Case 6 (h <= 1).
2114 // g := legth of rectangle R
2115 g = b + shift_x;
2116 if(g > 1) // Should always be < 1 for angles in [0,pi/4)
2117 g = 1;
2118 eps1 = (g*h - a*b)/2;
2119 eps2 = 0;
2120 eps3 = 0;
2121 if((eps1<0 || eps1>1 || eps2<0 || eps2>1 || eps3<0 || eps3>1) &&
2122 RADON_VERBOSE) printf(
2123 "6: (%i,%i) eps1=%f | (%i,%i) eps2=%f | (%i,%i) eps3=%f\n",
2124 xp,yp,eps1,xp+1,yp-1,eps2,xp+1,yp,eps3);
2125 }
2126 } else { // 2. PART
2127 // Cases 2,7 and 8. (dy >= 1).
2128 // a := |HA|
2129 a = 1;
2130 // b := |HB| (>=1)
2131 b = dx - (float)(Xptr[z+1] + bin*shift_x + imgDim/2 - xp);
2132 // h := heigth of rectangle R
2133 h = 1;
2134 // g := length of rectangle R
2135 g = dx + shift_x;
2136 if(g > 1){ // Cases 2 and 8.
2137 g = 1 - (float)(Xptr[z+1] + bin*shift_x + imgDim/2 - xp);
2138 // positive x-coordinate (bin+1)
2139 xp2 = floor(Xptr[z+1] + (bin+1)*shift_x) + imgDim/2;
2140 if(xp == xp2){ // Case 8.
2141 // c := |FC|
2142 c = (float)(xp + 1 - (imgDim/2 + Xptr[z+1] + (bin+1)*shift_x));
2143 // d := |FD|
2144 d = (float)(floor(Yptr[xp + 1] + (bin+1)*shift_y) + 1 -
2145 (Yptr[xp + 1] + (bin+1)*shift_y));
2146
2147 eps1 = g*h - (a*b + c*d)/2;
2148 eps2 = 0;
2149 // Lower triangle on the next pixel (x+1,y).
2150 eps3 = (1 - d)*((Xptr[z] + (bin+1)*shift_x + imgDim/2) -
2151 (xp+1))/2;
2152 if((eps1<0 || eps1>1 || eps2<0 || eps2>1 || eps3<0 || eps3>1)
2153 && RADON_VERBOSE) printf(
2154 "8: (%i,%i) eps1=%f | (%i,%i) eps2=%f | (%i,%i) eps3=%f\n",
2155 xp,yp,eps1,xp+1,yp-1,eps2,xp+1,yp,eps3);
2156 } else { // Case 2.
2157 // c=d=0.
2158 eps1 = g*h - a*b/2;
2159
2160 /* Pixel in place (xp+1,yp-1) should have been found in
2161 the previous step. */
2162 eps2 = 0;
2163
2164 // Calculate area on pixel in place (xp+1,yp).
2165
2166 dx = (float)((imgDim/2 + Xptr[z] + (bin+1)*shift_x) - (xp+1));
2167 if(dx < 1){ // Case 10 (trapezium).
2168 // g := bottom of trapezium Q.
2169 g = dx;
2170 // c := top of trapezium Q.
2171 c = (float)((imgDim/2 + Xptr[z+1] + (bin+1)*shift_x) -
2172 (xp+1));
2173 // Area of trapezium Q. Heigth = 1.
2174 eps3 = (g + c)/2;
2175 if((eps1<0 || eps1>1 || eps2<0 || eps2>1 || eps3<0 ||
2176 eps3>1) && RADON_VERBOSE) printf(
2177 "2/10: (%i,%i) eps1=%f | (%i,%i) eps2=%f | (%i,%i) eps3=%f\n",
2178 xp,yp,eps1,xp+1,yp-1,eps2,xp+1,yp,eps3);
2179 } else { // Case 9.
2180 // c := |FC|
2181 c = (float)(xp + 2 - (imgDim/2 + Xptr[z+1] +
2182 (bin+1)*shift_x));
2183 // d := |FD|
2184 d = (float)(floor(Yptr[xp + 2] + (bin+1)*shift_y) + 1 -
2185 (Yptr[xp + 2] + (bin+1)*shift_y));
2186 // Rectangle Q - triangle CFD.
2187 eps3 = 1 - c*d/2;
2188 if((eps1<0 || eps1>1 || eps2<0 || eps2>1 || eps3<0 ||
2189 eps3>1) && RADON_VERBOSE) printf(
2190 "2/9: (%i,%i) eps1=%f | (%i,%i) eps2=%f | (%i,%i) eps3=%f\n",
2191 xp,yp,eps1,xp+1,yp-1,eps2,xp+1,yp,eps3);
2192 }
2193 }
2194 } else { // Case 7. (g < = 1)
2195
2196 // Area of the parallelogram R.
2197 eps1 = sdist/cosinus;
2198 eps2 = 0;
2199 eps3 = 0;
2200 if((eps1<0 || eps1>1 || eps2<0 || eps2>1 || eps3<0 || eps3>1) &&
2201 RADON_VERBOSE) printf(
2202 "7: (%i,%i) eps1=%f | (%i,%i) eps2=%f | (%i,%i) eps3=%f\n",
2203 xp,yp,eps1,xp+1,yp-1,eps2,xp+1,yp,eps3);
2204 }
2205 }
2206 if(!eps2 && !eps3) { // Cases 5,6 and 7.
2207 // Case: theta.
2208 // Add img(x,y)*k to the raysum of LOR (view,bin)
2209 imgptr[yp*imgDim + xp]+= eps1 * scnptr[view*binNr + bin];
2210 // Add img(-x,-y)*k to the raysum of LOR (view,binNr-bin)
2211 if(bin != center)
2212 imgptr[yn*imgDim + xn]+=
2213 eps1 * scnptr[view*binNr + binNr - 1 - bin];
2214
2215 if(view != viewNr/4) {
2216 // Mirror the LOR on y-axis, i.e. x->-x
2217 // Case: pi-theta.
2218 // Add img(-x,y)*k to the raysum of LOR (viewNr-view,bin)
2219 imgptr[yp*imgDim + xn]+=
2220 eps1 * scnptr[(viewNr - view)*binNr + bin];
2221 // Add img(x,-y)*k to the raysum of LOR (viewNr-view,binNr-bin)
2222 if(bin != center)
2223 imgptr[yn*imgDim + xp]+=
2224 eps1 * scnptr[(viewNr-view)*binNr + binNr - 1 - bin];
2225
2226 // Mirror the LOR on line y=x, i.e. y->x.
2227 // Case: pi/2 - theta.
2228 // Add img(y,x)*k to the raysum of LOR (viewNr/2-view,bin)
2229 imgptr[xn*imgDim + yn]+=
2230 eps1 * scnptr[(viewNr/2 - view)*binNr + bin];
2231 // Add img(-y,-x)*k to the raysum of LOR (viewNr/2-view,binNr-bin)
2232 if(bin != center)
2233 imgptr[xp*imgDim + yp]+=
2234 eps1 * scnptr[(viewNr/2 - view)*binNr + binNr - 1 - bin];
2235 }
2236
2237 // Mirror the LOR on line x=y, and on y-axis i.e x->y and y->-y.
2238 // Case: pi/2 + theta.
2239 // Add img(y,-x)*k to the raysum of LOR (viewNr/2+view,bin)
2240 imgptr[xn*imgDim + yp]+=
2241 eps1 * scnptr[(viewNr/2 + view)*binNr + bin];
2242 // Add img(-y,x)*k to the raysum of LOR (viewNr-view,binNr-bin)
2243 if(bin != center)
2244 imgptr[xp*imgDim + yn]+=
2245 eps1 * scnptr[(viewNr/2 + view)*binNr + binNr - 1 - bin];
2246
2247 } else {
2248 if(!eps2) { // <=> eps3 != 0 & eps2 = 0 <=> Cases 3,4 and 8.
2249 if(xp + 1 < imgDim && xn - 1 >= 0) {
2250 // Case: theta.
2251 // Add img(x,y)*k to the raysum of LOR (view,bin)
2252 imgptr[yp*imgDim + xp] += eps1 * scnptr[view*binNr + bin];
2253 imgptr[yp*imgDim + xp+1] += eps3 *scnptr[view*binNr + bin];
2254 // Add img(-x,-y)*k to the raysum of LOR (view,binNr-bin)
2255 if(bin != center){
2256 imgptr[yn*imgDim + xn] +=
2257 eps1 * scnptr[view*binNr + binNr - 1 - bin];
2258 imgptr[yn*imgDim + xn-1] +=
2259 eps3 * scnptr[view*binNr + binNr - 1 - bin];
2260 }
2261
2262 if(view != viewNr/4) {
2263 // Mirror the LOR on y-axis, i.e. x->-x
2264 // Case: pi-theta.
2265 // Add img(-x,y)*k to the raysum of LOR (viewNr-view,bin)
2266 imgptr[yp*imgDim + xn]+=
2267 eps1 * scnptr[(viewNr - view)*binNr + bin];
2268 imgptr[yp*imgDim + xn-1] +=
2269 eps3 * scnptr[(viewNr - view)*binNr + bin];
2270 /* Add img(x,-y)*k to the raysum of LOR
2271 (viewNr-view,binNr-bin) */
2272 if(bin != center) {
2273 imgptr[yn*imgDim + xp] +=
2274 eps1 * scnptr[(viewNr-view)*binNr + binNr - 1 - bin];
2275 imgptr[yn*imgDim + xp+1] +=
2276 eps3 *scnptr[(viewNr-view)*binNr + binNr - 1 - bin];
2277 }
2278 // Mirror the LOR on line y=x, i.e. y->x.
2279 // Case: pi/2 - theta.
2280 // Add img(y,x)*k to the raysum of LOR (viewNr/2-view,bin)
2281 imgptr[xn*imgDim + yn]+=
2282 eps1 * scnptr[(viewNr/2 - view)*binNr + bin];
2283 imgptr[(xn-1)*imgDim + yn] +=
2284 eps3 *scnptr[(viewNr/2 - view)*binNr + bin];
2285 /* Add img(-y,-x)*k to the raysum of LOR
2286 (viewNr/2-view,binNr-bin) */
2287 if(bin != center) {
2288 imgptr[xp*imgDim + yp]+=
2289 eps1 * scnptr[(viewNr/2 - view)*binNr + binNr - 1 - bin];
2290 imgptr[(xp+1)*imgDim+yp]+=
2291 eps3 * scnptr[(viewNr/2 - view)*binNr + binNr - 1 - bin];
2292 }
2293 }
2294
2295 // Mirror the LOR on line x=y, and on y-axis i.e x->y and y->-y.
2296 // Case: pi/2 + theta.
2297 // Add img(y,-x)*k to the raysum of LOR (viewNr/2+view,bin)
2298 imgptr[xn*imgDim + yp]+=
2299 eps1 * scnptr[(viewNr/2 + view)*binNr + bin];
2300 imgptr[(xn-1)*imgDim + yp] +=
2301 eps3 * scnptr[(viewNr/2 + view)*binNr + bin];
2302 // Add img(-y,x)*k to the raysum of LOR (viewNr-view,binNr-bin)
2303 if(bin != center){
2304 imgptr[xp*imgDim + yn]+=
2305 eps1 * scnptr[(viewNr/2 + view)*binNr + binNr - 1 - bin];
2306 imgptr[(xp+1)*imgDim+yn] +=
2307 eps3*scnptr[(viewNr/2 + view)*binNr + binNr - 1 - bin];
2308 }
2309 }
2310 } else { // <=> eps2!=0 && eps3!=0 <=> Case 3.
2311 if(xp+1 < imgDim && xn-1 >= 0 && yp-1 >= 0 && yn+1 < imgDim) {
2312
2313 // Case: theta.
2314 // Add img(x,y)*k to the raysum of LOR (view,bin)
2315 imgptr[yp*imgDim + xp] += eps1 * scnptr[view*binNr + bin];
2316 imgptr[yp*imgDim + xp+1] += eps3 *scnptr[view*binNr + bin];
2317 imgptr[(yp-1)*imgDim + xp+1] +=
2318 eps2 * scnptr[view*binNr + bin];
2319 // Add img(-x,-y)*k to the raysum of LOR (view,binNr-bin)
2320 if(bin != center){
2321 imgptr[yn*imgDim + xn] +=
2322 eps1 * scnptr[view*binNr + binNr - 1 - bin];
2323 imgptr[yn*imgDim + xn-1] +=
2324 eps3 * scnptr[view*binNr + binNr - 1 - bin];
2325 imgptr[(yn+1)*imgDim + xn-1] +=
2326 eps2 * scnptr[view*binNr + binNr - 1 - bin];
2327 }
2328 if(view != viewNr/4) {
2329 // Mirror the LOR on y-axis, i.e. x->-x
2330 // Case: pi-theta.
2331 // Add img(-x,y)*k to the raysum of LOR (viewNr-view,bin)
2332 imgptr[yp*imgDim + xn] +=
2333 eps1 * scnptr[(viewNr - view)*binNr + bin];
2334 imgptr[yp*imgDim + xn-1] +=
2335 eps3 *scnptr[(viewNr - view)*binNr + bin];
2336 imgptr[(yp-1)*imgDim + xn-1]+=
2337 eps2 * scnptr[(viewNr - view)*binNr + bin];
2338 /* Add img(x,-y)*k to the raysum of LOR
2339 (viewNr-view,binNr-bin) */
2340 if(bin != center) {
2341 imgptr[yn*imgDim + xp] +=
2342 eps1 * scnptr[(viewNr-view)*binNr + binNr - 1 - bin];
2343 imgptr[yn*imgDim + xp+1] +=
2344 eps3 * scnptr[(viewNr-view)*binNr + binNr - 1 - bin];
2345 imgptr[(yn+1)*imgDim + xp+1] +=
2346 eps2 * scnptr[(viewNr-view)*binNr + binNr - 1 - bin];
2347 }
2348
2349 // Mirror the LOR on line y=x, i.e. y->x.
2350 // Case: pi/2 - theta.
2351 // Add img(y,x)*k to the raysum of LOR (viewNr/2-view,bin)
2352 imgptr[xn*imgDim + yn]+=
2353 eps1 * scnptr[(viewNr/2 - view)*binNr + bin];
2354 imgptr[xn*imgDim + yn-1] +=
2355 eps3 *scnptr[(viewNr/2 - view)*binNr + bin];
2356 imgptr[(xn-1)*imgDim + (yn+1)] +=
2357 eps2 * scnptr[(viewNr/2 - view)*binNr + bin];
2358 /* Add img(-y,-x)*k to the raysum of LOR
2359 (viewNr/2-view,binNr-bin) */
2360 if(bin != center) {
2361 imgptr[xp*imgDim + yp]+=
2362 eps1 * scnptr[(viewNr/2 - view)*binNr + binNr - 1 - bin];
2363 imgptr[(xp+1)*imgDim+yp] +=
2364 eps3*scnptr[(viewNr/2 - view)*binNr + binNr - 1 - bin];
2365 imgptr[(xp+1)*imgDim+(yp-1)] +=
2366 eps2*scnptr[(viewNr/2 - view)*binNr + binNr - 1 - bin];
2367 }
2368 }
2369
2370 // Mirror the LOR on line x=y, and on y-axis i.e x->y and y->-y.
2371 // Case: pi/2 + theta.
2372 // Add img(y,-x)*k to the raysum of LOR (viewNr/2+view,bin).
2373 imgptr[xn*imgDim + yp] +=
2374 eps1 * scnptr[(viewNr/2 + view)*binNr + bin];
2375 imgptr[(xn-1)*imgDim + yp] +=
2376 eps3 * scnptr[(viewNr/2 + view)*binNr + bin];
2377 imgptr[(xn-1)*imgDim + (yp-1)] +=
2378 eps2 *scnptr[(viewNr/2 + view)*binNr + bin];
2379 // Add img(-y,x)*k to the raysum of LOR (viewNr-view,binNr-bin)
2380 if(bin != center){
2381 imgptr[xp*imgDim + yn]+=
2382 eps1 * scnptr[(viewNr/2 + view)*binNr + binNr - 1 - bin];
2383 imgptr[(xp+1)*imgDim+yn] +=
2384 eps3 * scnptr[(viewNr/2 + view)*binNr + binNr - 1 - bin];
2385 imgptr[(xp+1)*imgDim+yn+1] +=
2386 eps2*scnptr[(viewNr/2 + view)*binNr + binNr - 1 - bin];
2387 }
2388 }
2389 }
2390 }
2391 }
2392 }
2393 } // END of X loop
2394 } // End of view>0.
2395 } // END OF VIEW LOOP
2396 free(X);
2397 free(Y);
2398
2399 return 0;
2400
2401} // END OF EXACT AREA BACK TRANSFORM.
int RADON_VERBOSE
Drive in verbose mode if not 0.
Definition radon.c:13

◆ radonBackTransformPRM()

int radonBackTransformPRM ( PRMAT * mat,
int set,
int setNr,
float * scndata,
float * imgdata )
extern

Transforms the given sinogram in Radon domain to spatial domain. Transform is calculated by multiplying with the transpose of the given projection matrix from the right. Transform is calculated only in those angles belonging into given subset. Subset contains angles starting from the index 'set' with spacing 'setNr'. Discretisation model utilised in this function is '0/1', 'length of intersection' or 'exact area' according to the given projection matrix.

Precondition
scndata contains the projections with v x b lines of response.
Postcondition
scndata is mapped into the cartesian space.
Parameters
matpointer to structure where coordinates and values are stored.
settells which set is to be utilized; 0 < set < setNr-1
setNrnumber of subsets
scndatav x b vector contains the projections.
imgdatan x n vector for storing the back-projection.
Returns
int 0 if ok

Definition at line 2503 of file radon.c.

2505 {
2506 float *imgptr, *scnptr; // pointers for the image and sinogram data
2507 unsigned int imgDim=128, binNr=256, viewNr=192, view, bin, row, col;
2508 unsigned int half, centerbin;
2509 int xp, xn, yp, yn;
2510 float fact;
2511
2512 // Retrieve the data from given projection matrix.
2513 imgDim=prmatGetID(mat);
2514 binNr=prmatGetNB(mat); // Should be equal to imgDim.
2515 viewNr=prmatGetNV(mat);
2516
2517 // Calculate and set center bin for current geometrics.
2518 if((binNr%2) != 0){
2519 half = (binNr - 1)/2 + 1;
2520 centerbin = half - 1;
2521 } else {
2522 half = binNr/2;
2523 // In the case binNr is even there is no center bin.
2524 centerbin = -1;
2525 }
2526
2527 imgptr = imgdata;
2528 scnptr = scndata;
2529
2530 // Draw sinogram according to projection matrix.
2531 for(view=set; view<=viewNr/4; view=view+setNr){
2532 for(bin=0; bin<half; bin++){
2533 row = view*half + bin;
2534 for(col=0; col<prmatGetPixels(mat,row); col++){
2535
2536 fact = prmatGetFactor(mat,row,col);
2537 xp = prmatGetXCoord(mat,row,col);
2538 xn = imgDim - 1 - xp;
2539 yp = prmatGetYCoord(mat,row,col);
2540 yn = imgDim - 1 - yp;
2541
2542 // Add img(x,y)*k to the raysum of LOR (view,bin)
2543 imgptr[yp*imgDim + xp] += fact * scnptr[view*binNr + bin];
2544 if(bin != centerbin)
2545 // Add img(-x,-y)*k to the raysum of LOR (view,binNr-bin)
2546 imgptr[yn*imgDim + xn] += fact * scnptr[view*binNr + binNr - 1 - bin];
2547
2548 if(view != 0 && view != viewNr/4){
2549 // Mirror the original LOR on y-axis, i.e. x->-x
2550 // Case: pi-theta.
2551 // Add img(-x,y)*k to the raysum of LOR (viewNr-view,bin)
2552 imgptr[yp*imgDim + xn] += fact * scnptr[(viewNr - view)*binNr + bin];
2553 // Add img(x,-y)*k to the raysum of LOR (viewNr-view,binNr-bin)
2554 if(bin != centerbin)
2555 imgptr[yn*imgDim + xp] +=
2556 fact * scnptr[(viewNr-view)*binNr + binNr - 1 - bin];
2557
2558 // Mirror the LOR on line x=y, i.e. x->y.
2559 // Case: pi/2-theta
2560 // Add img(-y,-x)*k to the raysum of LOR (viewNr/2-view,bin)
2561 imgptr[xn*imgDim + yn] += fact * scnptr[(viewNr/2 - view)*binNr + bin];
2562 // Add img(y,x)*k to the raysum of LOR (viewNr/2-view,binNr-bin)
2563 if(bin != centerbin)
2564 imgptr[xp*imgDim + yp] +=
2565 fact * scnptr[(viewNr/2 - view)*binNr + binNr - 1 - bin];
2566 }
2567
2568 // Mirror the LOR on line x=y, and on y-axis i.e x->y and y->-y.
2569 // Case: pi/2+theta
2570 // Add img(y,-x)*k to the raysum of LOR (viewNr/2+view,bin)
2571 imgptr[xn*imgDim + yp] += fact * scnptr[(viewNr/2 + view)*binNr + bin];
2572 // Add img(y,-x)*k to the raysum of LOR (viewNr/2+view,binNr-bin)
2573 if(bin != centerbin)
2574 imgptr[xp*imgDim + yn] +=
2575 fact * scnptr[(viewNr/2 + view)*binNr + binNr - 1 - bin];
2576
2577 }
2578 }
2579 }
2580
2581 return 0;
2582}
unsigned int prmatGetNV(PRMAT *mat)
Definition prmat.c:175
unsigned int prmatGetYCoord(PRMAT *mat, int row, int pix)
Definition prmat.c:327
unsigned int prmatGetXCoord(PRMAT *mat, int row, int pix)
Definition prmat.c:312
unsigned int prmatGetID(PRMAT *mat)
Definition prmat.c:197
float prmatGetFactor(PRMAT *mat, int row, int pix)
Definition prmat.c:342
unsigned int prmatGetPixels(PRMAT *mat, int row)
Definition prmat.c:282
unsigned int prmatGetNB(PRMAT *mat)
Definition prmat.c:186

◆ radonBackTransformSA()

int radonBackTransformSA ( RADON * radtra,
int set,
int setNr,
float * scndata,
float * imgdata )
extern

Same as 'radonBackTransform()' but discretisation model in this function is 'linear interpolation' or 'nearest neighbour interpolation' according to the given Radon transform object.

Parameters
radtracontains an initialized radon transform object.
settells which set is to be utilized; 0 < set < setNr-1
setNrnumber of subsets
scndatav x b vector contains the projections.
imgdatan x n vector for storing the back-projection.
Returns
int 0 if ok
Note
first written by Sakari Alenius 1998.

Definition at line 2415 of file radon.c.

2417 {
2418 float *imgptr, *scnptr, *imgorigin;
2419 float sinus, cosinus;
2420 float t; // distance between projection ray and origo.
2421 int mode, imgDim, binNr, viewNr, halfImg, centerBin, view;
2422 int x, y, xright, ybottom;
2423 float tpow2;
2424
2425 // Retrieve the data from given radon transform object.
2426 mode=radonGetMO(radtra); // Should be 3 or 4.
2427 imgDim=radonGetID(radtra);
2428 binNr=radonGetNB(radtra); // Should be equal to imgDim.
2429 viewNr=radonGetNV(radtra);
2430 // Set the center ray and the square of it.
2431 centerBin=binNr/2;
2432 tpow2 = centerBin*centerBin;
2433
2434 if(imgDim != binNr) return -1;
2435
2436 // Set half of the image dimension.
2437 halfImg = imgDim/2;
2438
2439 // Transform one angle at a time.
2440 for(view=set; view<viewNr; view+=setNr){
2441
2442 imgorigin = imgdata + imgDim*(halfImg - 1) + halfImg;
2443
2444 sinus = radonGetSin(radtra,view);
2445 cosinus = radonGetSin(radtra,viewNr/2 + view);
2446
2447 y = halfImg - 2;
2448
2449 if((float)y > centerBin){
2450 y = (int)(centerBin);
2451 ybottom = -y;
2452 } else{
2453 ybottom = -halfImg + 1;
2454 }
2455 for(; y >= ybottom; y--){
2456 xright =
2457 (int)sqrt(/*fabs(*/tpow2 - ((float)y+0.5) * ((float)y+0.5)/*)*/) + 1;
2458 if(xright >= halfImg){
2459 xright = halfImg - 1;
2460 x = -halfImg;
2461 }
2462 else
2463 x = -xright;
2464
2466 // t = centerBin - (float)y * sinus + ((float)(x + 1)) * cosinus;
2467 t = centerBin + (float)y * sinus + ((float)(x + 1)) * cosinus;
2468
2469 imgptr = imgorigin - y*imgDim + x;
2470 scnptr = scndata + view*binNr;
2471 for(; x <= xright; x++, t += cosinus){
2472 if(mode == 3){ // If the linear interpolation is to be utilised.
2473 *imgptr++ +=
2474 ( *(scnptr+(int)t) + (*(scnptr+(int)t+1) - *(scnptr+(int)t))
2475 * (t - (float)(int)t) );
2476 } else {// If the nearest neighbour interpolation is to be utilised.
2477 *imgptr++ += *(scnptr+(int)(t + 0.5)); /* (float)(1.0 / (float)views)*/
2478 }
2479 }
2480 }
2481 }
2482 return 0;
2483}

◆ radonEmpty()

void radonEmpty ( RADON * radtra)
extern

Frees the memory allocated for radon transform. All data is cleared.

Postcondition
radon transform is emptied.
Parameters
radtrapointer to transform data to be emptied

Definition at line 27 of file radon.c.

28{
29 if(RADON_VERBOSE){
30 printf("RADON: radonEmpty() started. \n");
31 fflush(stdout);
32 }
33 //if radtra is already empty
34 if(radtra->status<RADON_STATUS_INITIALIZED){
35 if(RADON_VERBOSE){
36 printf("RADON: radon object already empty: status %i \n",radtra->status);
37 fflush(stdout);
38 }
39 //return;
40 }
41 //free the memory occupied by sine
42 free(radtra->sines);
43
44 if(RADON_VERBOSE){
45 printf("RADON: radonEmpty() finished. \n");
46 fflush(stdout);
47 }
48 return;
49}
float * sines
Definition libtpcrec.h:274

◆ radonFwdTransform()

int radonFwdTransform ( RADON * radtra,
int set,
int setNr,
float * imgdata,
float * scndata )
extern

Performs the perpendicular model of the radon transform for the given vector in spatial domain. The discretisation mode is chosen according to transform object, discretisation mode is 0 or 1. Transform is performed in those angles belonging in the given subset. The set of coincidence lines is divided into subsets in the following way: let i be the number of subsets, then every ith angle in the base set and the ones symmetrical with it belong to the same subset.

Precondition
imgdata contains pixel values for every pixel in dim*dim image grid
Postcondition
imgdata is mapped into the projection space.
Parameters
radtracontains an initialized radon transform object.
settells which set is to be utilized; 0 < set < setNr-1
setNrnumber of subsets
imgdatacontains pixel values for every pixel in dim*dim image grid.
scndataviewNr*binNr vector for storing the projection
Returns
int 0 if ok

Definition at line 216 of file radon.c.

218 {
219 float *imgptr, *scnptr; // pointers for the image and sinogram data
220 float *Y, *X, *Xptr, *Yptr; // pointers for the values of LOR in integer points
221 double sinus, cosinus, tanus; // sin, cosine and tangent
222 double shift_x, shift_y; // shift for LOR
223 double scalef; // scaling factor for angle
224 int xp, xn, yp, yn, z; //integer points
225 int x_left, x_right, y_top, y_bottom; // limits for fast search
226 int col, row, view, bin; //counters
227 int binNr, viewNr, imgDim, mode;
228 int half, center = -1;
229 float sdist;
230 float dx, dy , loi = 1; // delta x and y and length of intersection
231
232 if( RADON_VERBOSE ){
233 printf("RADON: radonFwdTransform() started.\n");
234 fflush(stdout);
235 }
236
237 // Check that the data for this radon transform is initialized.
238 if(radtra->status != RADON_STATUS_INITIALIZED) return -1;
239
240 // Retrieve the parameters from given radon transform object.
241 mode=radonGetMO(radtra);
242 imgDim=radonGetID(radtra);
243 binNr=radonGetNB(radtra);
244 viewNr=radonGetNV(radtra);
245 sdist=radonGetSD(radtra);
246 half=radonGetHI(radtra);
247 center=radonGetCB(radtra);
248
249 // Array for storing values f_x.
250 X=(float*)calloc(imgDim+1,sizeof(float));
251 // Array for storing values f_y.
252 Y=(float*)calloc(imgDim+1,sizeof(float));
253 if(X==NULL || Y==NULL){
254 return -2;
255 }
256 Xptr=X;
257 Yptr=Y;
258
259 imgptr=imgdata;
260 scnptr=scndata;
261
263 // Find pixel coordinates of the contributing pixels for lines of response
264 // belonging to first 1/4th of angles. From these pixel coordinates
265 // others can be calculated via symmetries in projection space.
266 // N.B. The line of response: a*x+b*y+c
267 // => solve y: y = (s - x*cos(theta))/sin(theta)
268 // solve x: x = (s - y*sin(theta))/cos(theta)
269
270 for(view=set; view<=viewNr/4; view=view+setNr){
271 // Choose the type of the line of response according to view number.
272
273 // view=0 -> sin(theta)=0
274 if(view==0){
275
276 // Length of intersection is 1.
277 loi = 1.;
278
279 // Choose column according to sample distance for angles 0 and pi/2.
280 col = 0;
281 for(bin=0; bin<half; bin++){
282 col = floor((float)(bin+.5*sdist)*sdist);
283
284 /* Iterate through the entries in the image matrix.
285 Calculate raysums for two LORs in the same distance from origin
286 (do halfturn). */
287 for(row=0; row<imgDim; row++) {
288
289 scnptr[bin] += loi * imgptr[row*imgDim + col];
290 if(bin != center)
291 scnptr[binNr-bin-1] += loi * imgptr[row*imgDim + (imgDim - 1 - col)];
292
293 scnptr[binNr*(viewNr/2) + bin] +=
294 loi * imgptr[(imgDim - 1 - col)*imgDim + row];
295 if(bin != center)
296 scnptr[binNr*(viewNr/2) + (binNr-bin-1)] +=
297 loi * imgptr[col*imgDim + row];
298 }
299
300 }
301 // End of view==0 (handles angles 0 and pi/2).
302 } else { // angles != 0
303
304 // Set sine and cosine for this angle.
305 sinus = (double)radonGetSin(radtra,view);
306 cosinus = (double)radonGetSin(radtra,viewNr/2 + view);
307 tanus = sinus/cosinus;
308
309 // Set shift from origin for the first line of response (-n/2,theta).
310 // NOTE that image matrix is on cartesian coordinate system where origin
311 // is in the middle and shift is in pixels.
312 shift_y = -(imgDim/2 -.5*sdist)/sinus;
313 shift_x = -(imgDim/2 -.5*sdist)/cosinus;
314
315 // Evaluate the function of the first LOR in integer points [-n/2,n/2].
316 // NOTE that image matrix is on cartesian coordinate system where origin
317 // is in the middle.
318 z=-imgDim/2;
319 for(col=0; col<imgDim+1; col++){
320 Yptr[col]=(float)(shift_y - z/tanus);
321 Xptr[col]=(float)(shift_x - z*tanus);
322 z++;
323 }
324
325 // Set shift from the first LOR.
326 shift_y = (double)(sdist/sinus);
327 shift_x = (double)(sdist/cosinus);
328
329 // Set scaling for angle.
330 scalef = sinus + cosinus;
331
332 // Iterate through half the bins in this view,
333 // and determine coordinates of pixels contributing to this LOR.
334 // NOTE that shift is added according to 'bin' in every loop.
335 // Calculate also the length of intersection.
336 // Others are determined via symmetry in projection space.
337
338 for(bin=0; bin<half; bin++) {
339
340 /* Set the number of intersected pixels to zero. */
341 /* np = 0; */
342
343 // Limit (x-)indices for fast search.
344 // Note that indices are non-negative integers.
345 x_left = floor((float)(Xptr[imgDim] + bin*shift_x + imgDim/2));
346 if(x_left < 0) x_left = 0;
347
348 x_right = floor((float)(Xptr[0] + bin*shift_x + imgDim/2));
349 if(x_right <= 0) x_right = 1;
350 if(x_right > imgDim) x_right = imgDim - 1;
351
352 /* Iterate through the values in vector Y, in integer points
353 [x_left,x_rigth]. */
354 for(z=x_left; z <= x_right; z++) {
355
356 xp = z; //positive x-coordinate
357 xn = imgDim - 1 - xp; //negative x-coordinate
358
359 // Look y from left. yp=positive y-coordinate
360 yp = imgDim/2 - floor(Yptr[xp + 1] + bin*shift_y) - 1;
361 yn = imgDim - 1 - yp;
362
363 // If the y-value for this x (z) is inside the image grid.
364 if(yp < imgDim && yp >= 0 && yn < imgDim && yn >= 0 && xp >= 0 &&
365 xp < imgDim && xn < imgDim && xn >= 0)
366 {
367
368 if(!mode) {
369 loi = 1;
370 } else {
371 // Compute delta x and y.
372 dx = fabs((float)(xp + 1 - (imgDim/2 + Xptr[imgDim - yp] +
373 bin*shift_x)));
374 dy = fabs((float)(floor(Yptr[xp + 1] + bin*shift_y) + 1 -
375 (Yptr[xp + 1] + bin*shift_y)));
376 if(dx > 1 || dx < 0) dx = 1;
377 if(dy > 1 || dy < 0) dy = 1;
378 loi = sqrt(dx*dx + dy*dy);
379 }
380 // Case: theta.
381 // Add img(x,y)*k to the raysum of LOR (view,bin)
382 scnptr[view*binNr + bin] += loi * imgptr[yp*imgDim + xp];
383 if(bin != center)
384 // Add img(-x,-y)*k to the raysum of LOR (view,binNr-bin)
385 scnptr[view*binNr + binNr - 1 - bin] +=
386 loi * imgptr[yn*imgDim + xn];
387
388 if(view != viewNr/4) {
389 // Mirror the original LOR on y-axis, i.e. x->-x
390 // Case: pi-theta.
391 // Add img(-x,y)*k to the raysum of LOR (viewNr-view,bin)
392 scnptr[(viewNr - view)*binNr + bin] +=
393 loi * imgptr[yp*imgDim + xn];
394 // Add img(x,-y)*k to the raysum of LOR (viewNr-view,binNr-bin)
395 if(bin != center)
396 scnptr[(viewNr-view)*binNr + binNr - 1 - bin] +=
397 loi * imgptr[yn*imgDim + xp];
398
399 // Mirror the LOR on line x=y, i.e. x->y.
400 // Case: pi/2-theta
401 // Add img(-y,-x)*k to the raysum of LOR (viewNr/2-view,bin)
402 scnptr[(viewNr/2 - view)*binNr + bin] +=
403 loi * imgptr[xn*imgDim + yn];
404 // Add img(y,x)*k to the raysum of LOR (viewNr/2-view,binNr-bin)
405 if(bin != center)
406 scnptr[(viewNr/2 - view)*binNr + binNr - 1 - bin] +=
407 loi * imgptr[xp*imgDim + yp];
408 }
409
410 // Mirror the LOR on line x=y, and on y-axis i.e x->y and y->-y.
411 // Case: pi/2+theta
412 // Add img(y,-x)*k to the raysum of LOR (viewNr/2+view,bin)
413 scnptr[(viewNr/2 + view)*binNr + bin] +=
414 loi * imgptr[xn*imgDim + yp];
415 // Add img(y,-x)*k to the raysum of LOR (viewNr/2+view,binNr-bin)
416 if(bin != center)
417 scnptr[(viewNr/2 + view)*binNr + binNr - 1 - bin] +=
418 loi * imgptr[xp*imgDim + yn];
419 }
420 }
421
422 // Limit (y-)indices for fast search.
423 // Note that indices are non-negative integers.
424 y_bottom = floor((float)(Yptr[imgDim] + bin*shift_y + imgDim/2));
425 if(y_bottom < 0) y_bottom = 0;
426 if(y_bottom > imgDim) y_bottom = 0;
427
428 y_top = floor((float)(Yptr[0] + bin*shift_y + imgDim/2));
429 if(y_top > imgDim) y_top = imgDim-1;
430 if(y_top <= 0) y_top = 1;
431
432 /* Iterate through the values in vector X, in integer points
433 [y_bottom,y_top]. */
434 for(z=y_top; z >= y_bottom; z--) {
435
436 // Look y from this location.
437 xp = floor(Xptr[z] + bin*shift_x) + imgDim/2;
438 xn = imgDim - 1 - xp;
439
440 yp = imgDim - z - 1;
441 yn = imgDim - yp - 1;
442
443 // If the x-value for this y (z) is inside the image grid.
444 if(yp < imgDim && yp >= 0 && yn < imgDim && yn >= 0 && xp >= 0 &&
445 xp < imgDim && xn < imgDim && xn >= 0)
446 {
447
448 if(!mode) {
449 loi = 1;
450 } else {
451 dx = (float)(Xptr[z] + bin*shift_x + imgDim/2 - xp);
452 dy = (float)(Yptr[xp] + bin*shift_y - z + imgDim/2);
453 if(dy > 1 || dy < 0){
454 dx = dx - (float)(Xptr[z+1] + bin*shift_x + imgDim/2 - xp);
455 dy = 1;
456 }
457 loi = sqrt(dx*dx + dy*dy);
458 }
459
460 // Case: theta.
461 // Add img(x,y)*k to the raysum of LOR (view,bin)
462 scnptr[view*binNr + bin] += loi * imgptr[yp*imgDim + xp];
463 // Add img(-x,-y)*k to the raysum of LOR (view,binNr-bin)
464 if(bin != center)
465 scnptr[view*binNr + binNr - 1 - bin] +=
466 loi * imgptr[yn*imgDim + xn];
467
468 if(view != viewNr/4) {
469 // Mirror the LOR on y-axis, i.e. x->-x
470 // Case: pi-theta.
471 // Add img(-x,y)*k to the raysum of LOR (viewNr-view,bin)
472 scnptr[(viewNr - view)*binNr + bin] += loi * imgptr[yp*imgDim + xn];
473 // Add img(x,-y)*k to the raysum of LOR (viewNr-view,binNr-bin)
474 if(bin != center)
475 scnptr[(viewNr-view)*binNr + binNr - 1 - bin] +=
476 loi * imgptr[yn*imgDim + xp];
477
478 // Mirror the LOR on line y=x, i.e. y->x.
479 // Case: pi/2 - theta.
480 // Add img(y,x)*k to the raysum of LOR (viewNr/2-view,bin)
481 scnptr[(viewNr/2 - view)*binNr + bin] +=
482 loi * imgptr[xn*imgDim + yn];
483 // Add img(-y,-x)*k to the raysum of LOR (viewNr/2-view,binNr-bin)
484 if(bin != center)
485 scnptr[(viewNr/2 - view)*binNr + binNr - 1 - bin] +=
486 loi * imgptr[xp*imgDim + yp];
487 }
488
489 // Mirror the LOR on line x=y, and on y-axis i.e x->y and y->-y.
490 // Case: pi/2 + theta.
491 // Add img(y,-x)*k to the raysum of LOR (viewNr/2+view,bin)
492 scnptr[(viewNr/2 + view)*binNr + bin] += loi * imgptr[xn*imgDim + yp];
493 // Add img(-y,x)*k to the raysum of LOR (viewNr-view,binNr-bin)
494 if(bin != center)
495 scnptr[(viewNr/2 + view)*binNr + binNr - 1 - bin] +=
496 loi * imgptr[xp*imgDim + yn];
497 }
498 }
499
500 // If mode==0 scale with sin(theta)+cos(theta).
501 if(mode==0) {
502 // Case: theta.
503 scnptr[view*binNr + bin] /= scalef;
504 if(bin != center)
505 scnptr[view*binNr + binNr - 1 - bin] /= scalef;
506
507 if(view != viewNr/4){
508 // Mirror the LOR on y-axis, i.e. x->-x
509 // Case: pi-theta.
510 scnptr[(viewNr - view)*binNr + bin] /= scalef;
511 if(bin != center)
512 scnptr[(viewNr-view)*binNr + binNr - 1 - bin] /= scalef;
513
514 // Mirror the LOR on line y=x, i.e. y->x.
515 // Case: pi/2 - theta.
516 scnptr[(viewNr/2 - view)*binNr + bin] /= scalef;
517 if(bin != center)
518 scnptr[(viewNr/2 - view)*binNr + binNr - 1 - bin] /= scalef;
519 }
520
521 // Mirror the LOR on line x=y, and on y-axis i.e x->y and y->-y.
522 // Case: pi/2 + theta.
523 scnptr[(viewNr/2 + view)*binNr + bin] /= scalef;
524 if(bin != center)
525 scnptr[(viewNr/2 + view)*binNr + binNr - 1 - bin] /= scalef;
526 }
527 }// END of X loop
528 }// End of view>0.
529 }// END OF VIEW LOOP
530 free(X);
531 free(Y);
532
533 if( RADON_VERBOSE ){
534 printf("RADON: radonFwdTransform() finished.\n");
535 fflush(stdout);
536 }
537
538 return 0;
539}// END OF FORWARD (spa -> pro) RADON TRANSFORM

◆ radonFwdTransformEA()

int radonFwdTransformEA ( RADON * radtra,
int set,
int setNr,
float * imgdata,
float * scndata )
extern

Same as 'radonFwdTransform()' but discretisation model in this function is 'exact area'.

Parameters
radtracontains an initialized radon transform object.
settells which set is to be utilized; 0 < set < setNr-1
setNrnumber of subsets
imgdatacontains pixel values for every pixel in dim*dim image grid.
scndataviewNr*binNr vector for storing the projection
Returns
int 0 if ok

Definition at line 550 of file radon.c.

552{
553 float *imgptr, *scnptr; // pointers for the image and sinogram data
554 float *Y, *X, *Xptr, *Yptr; // pointers for the values of LOR in integer points
555 double sinus, cosinus, tanus; // sin, cosine and tangent
556 double shift_x, shift_y; // shift for LOR
557 int xp, xn, yp, yn, z, xp2; //integer points
558 int x_left, x_right, y_top, y_bottom; // limits for fast search
559 int col, col1, col2, row, view, bin; //counters
560 int binNr, viewNr, imgDim, errors=0;
561 int half, center = -1;
562 float sdist;
563 float a=0,b=0, c=0, d=0, g=0, h=0, A;
564 float dx, dy , eps1 = 0, eps2 = 0, eps3 = 0; // delta x and y and factors.
565
566 if( RADON_VERBOSE ){
567 printf("RADON: radonFwdTransformEA() started.\n");
568 fflush(stdout);
569 }
570
571 // Check that the data for this radon transform is initialized.
572 if(radtra->status != RADON_STATUS_INITIALIZED) return -1;
573
574 // Retrieve the parameters from given radon transform object.
575 //mode=radonGetMO(radtra); // Should be 2.
576 imgDim=radonGetID(radtra);
577 binNr=radonGetNB(radtra);
578 viewNr=radonGetNV(radtra);
579 sdist=radonGetSD(radtra);
580 half=radonGetHI(radtra);
581 center=radonGetCB(radtra);
582
583 // Array for storing values f_x.
584 X=(float*)calloc(imgDim+1,sizeof(float));
585 // Array for storing values f_y.
586 Y=(float*)calloc(imgDim+1,sizeof(float));
587 if(X==NULL || Y==NULL){
588 return -2;
589 }
590 Xptr=X;
591 Yptr=Y;
592
593 imgptr=imgdata;
594 scnptr=scndata;
595
597 // Find pixel coordinates of the contributing pixels for tubes of response
598 // belonging to first 1/4th of angles. From these pixel coordinates
599 // others can be calculated via symmetries in projection space.
600 // N.B. The line of response: a*x+b*y+c
601 // => solve y: y = (s - x*cos(theta))/sin(theta)
602 // solve x: x = (s - y*sin(theta))/cos(theta)
603
604 for(view=set; view<=viewNr/4; view=view+setNr){
605 // Choose the type of the line of response according to view number.
606
607 // view=0 -> sin(theta)=0
608 if(view==0){
609
610 // Choose column(s) according to sample distance for angles 0 and pi/2.
611 col1 = 0;
612 col2 = 0;
613 for(bin = 0; bin < half; bin++){
614
615 col1 = col2;
616 col2 = floor((float)(bin + 1)*sdist);
617
618 // Determine factor epsilon.
619 if(col1 == col2){
620 eps1 = sdist;
621 eps2 = 0;
622 eps3 = 0;
623 }
624 if((col2-col1) == 1){
625 eps1 = (float)(col2 - (bin)*sdist);
626 eps2 = 0;
627 eps3 = (float)((bin+1)*sdist - col2);
628
629 }
630 // If sdist > pixel size!
631 if((col2-col1) > 1){
632 eps1 = (float)(col1 + 1 - (bin)*sdist);
633 eps2 = 1; // middle pixel.
634 eps3 = (float)((bin+1)*sdist - col2);
635
636 }
637
638 /* Iterate through the entries in the image matrix.
639 Calculate raysums for two LORs in the same distance from origin
640 (do halfturn). */
641 for(row=0; row<imgDim; row++) {
642
643 if(!eps3){
644 scnptr[bin] += eps1 * imgptr[row*imgDim + col1];
645 if(bin != center)
646 scnptr[binNr-bin-1] +=
647 eps1 * imgptr[row*imgDim + (imgDim - 1 - col1)];
648
649 scnptr[binNr*(viewNr/2) + bin] +=
650 eps1 * imgptr[(imgDim - 1 - col1)*imgDim + row];
651 if(bin != center)
652 scnptr[binNr*(viewNr/2) + (binNr-bin-1)] +=
653 eps1 * imgptr[col1*imgDim + row];
654 }
655
656 if(eps3 && !eps2){
657 scnptr[bin] += eps1 * imgptr[row*imgDim + col1] +
658 eps3 * imgptr[row*imgDim + col2];
659 if(bin != center)
660 scnptr[binNr-bin-1] +=
661 eps1 * imgptr[row*imgDim + (imgDim - 1 - col1)] +
662 eps3*imgptr[row*imgDim+(imgDim-1-col2)];
663
664 scnptr[binNr*(viewNr/2) + bin] +=
665 eps1*imgptr[(imgDim-1-col1)*imgDim+row] +
666 eps3*imgptr[(imgDim-1-col2)*imgDim+row];
667 if(bin != center)
668 scnptr[binNr*(viewNr/2) + (binNr-bin-1)] +=
669 eps1 * imgptr[col1*imgDim + row] +
670 eps3 * imgptr[col2*imgDim + row] ;
671 }
672
673 if(eps3 && eps2) {
674 for(col = col1; col<=col2; col++) {
675 if(col == col1){
676 scnptr[bin] += eps1 * imgptr[row*imgDim + col1];
677 if(bin != center)
678 scnptr[binNr-bin-1] += eps1 * imgptr[row*imgDim +
679 (imgDim - 1 - col1)];
680 scnptr[binNr*(viewNr/2) + bin] +=
681 eps1 * imgptr[(imgDim - 1 - col1)*imgDim + row];
682 if(bin != center)
683 scnptr[binNr*(viewNr/2) + (binNr-bin-1)] +=
684 eps1 * imgptr[col1*imgDim + row];
685 }
686 if(col == col2) {
687 scnptr[bin] += eps3 * imgptr[row*imgDim + col2];
688 if(bin != center)
689 scnptr[binNr-bin-1] += eps3 * imgptr[row*imgDim +
690 (imgDim - 1 - col2)];
691 scnptr[binNr*(viewNr/2) + bin] +=
692 eps3 * imgptr[(imgDim - 1 - col2)*imgDim + row];
693 if(bin != center)
694 scnptr[binNr*(viewNr/2) + (binNr-bin-1)] +=
695 eps3 * imgptr[col2*imgDim + row];
696 }
697 if(col != col1 && col != col2) {
698 scnptr[bin] += eps2 * imgptr[row*imgDim + col];
699 if(bin != center)
700 scnptr[binNr-bin-1] +=
701 eps2 * imgptr[row*imgDim + (imgDim - 1 - col)];
702 scnptr[binNr*(viewNr/2) + bin] +=
703 eps2 * imgptr[(imgDim - 1 - col)*imgDim + row];
704 if(bin != center)
705 scnptr[binNr*(viewNr/2) + (binNr-bin-1)] +=
706 eps2 * imgptr[col*imgDim + row];
707 }
708 }
709 }
710 }
711 }
712 // End of view==0 (handles angles 0 and pi/2).
713 } else {
714
715 // Set sine and cosine for this angle.
716 sinus = (double)radonGetSin(radtra,view);
717 cosinus = (double)radonGetSin(radtra,viewNr/2 + view);
718 tanus = sinus/cosinus;
719
720 // Set shift from origin for the first line of response (-n/2,theta).
721 // NOTE that image matrix is on cartesian coordinate system where origin
722 // is in the middle and shift is in pixels.
723 shift_y = -(imgDim/2)/sinus;
724 shift_x = -(imgDim/2)/cosinus;
725
726 // Evaluate the function of the first LOR in integer points [-n/2,n/2].
727 // NOTE that image matrix is on cartesian coordinate system where origin
728 // is in the middle.
729 z=-imgDim/2;
730 for(col=0; col<imgDim+1; col++){
731 Yptr[col]=(float)(-z/tanus + shift_y);
732 Xptr[col]=(float)(-z*tanus + shift_x);
733 z++;
734 }
735
736 // Set shift from the first TOR.
737 shift_y = (double)(sdist/sinus);
738 shift_x = (double)(sdist/cosinus);
739
740 // Iterate through half the bins in this view,
741 // and determine coordinates of pixels contributing to this TOR.
742 // NOTE that shift is added according to 'bin' in every loop.
743 // Others are determined via symmetry in projection space.
744
745 for(bin=0; bin<half; bin++){
746
747 // Limit (x-)indices for fast search.
748 // Note that indices are non-negative integers.
749
750 x_left = floor((float)(Xptr[imgDim] + bin*shift_x + imgDim/2));
751 if(x_left < 0) x_left = 0;
752
753 x_right = floor((float)(Xptr[0] + bin*shift_x + imgDim/2));
754 if(x_right <= 0) x_right = 1;
755 if(x_right > imgDim) x_right = imgDim - 1;
756
757 /* Iterate through the values in vector Y, in integer points
758 [x_left,x_rigth]. */
759 for(z=x_left; z <= x_right; z++) {
760
761 xp = z; //positive x-coordinate
762 xn = imgDim - 1 - xp; //negative x-coordinate
763
764 // Look y from left. yp=positive y-coordinate
765 yp = imgDim/2 - floor(Yptr[xp + 1] + bin*shift_y) - 1;
766 yn = imgDim - 1 - yp;
767
768 // If the y-value for this x (z) is inside the image grid.
769 if(yp < imgDim && yp >= 0 && yn < imgDim && yn >= 0 && xp >= 0 &&
770 xp < imgDim && xn < imgDim && xn >= 0)
771 {
772
773 /* NOTE that pixels found in this part are always hit from right
774 side. Compute a := |AF| and b := |FB|. */
775 a = (float)(xp + 1 - (imgDim/2 + Xptr[imgDim - yp] + bin*shift_x));
776 b = (float)(floor(Yptr[xp + 1] + bin*shift_y) + 1 - (Yptr[xp + 1] +
777 bin*shift_y));
778
779 // Calculate the area of lower triangle.
780 A = a*b/2;
781 // c := |FC|
782 c = (float)(xp + 1 - (imgDim/2 + Xptr[imgDim - yp] +
783 (bin+1)*shift_x));
784 if(c > 0){
785 // d := |FD|
786 d = (float)(floor(Yptr[xp + 1] + (bin+1)*shift_y) + 1 -
787 (Yptr[xp + 1] + (bin+1)*shift_y));
788 // Subtract the area of upper triangle.
789 A = A - c*d/2;
790 }
791
792 eps1 = A;
793 if( (eps1 < 0 || eps1 > 1) && RADON_VERBOSE){
794 printf("RADON: Error in factor: eps1=%.5f \n",eps1);
795 errors++;
796 }
797
798 // Case: theta.
799 // Add img(x,y)*k to the raysum of TOR (view,bin)
800 scnptr[view*binNr + bin] += eps1 * imgptr[yp*imgDim + xp];
801 // Add img(-x,-y)*k to the raysum of LOR (view,binNr-bin)
802 if(bin != center)
803 scnptr[view*binNr + binNr - 1 - bin] +=
804 eps1 * imgptr[yn*imgDim + xn];
805
806 if(view != viewNr/4){
807 // Mirror the original LOR on y-axis, i.e. x->-x
808 // Case: pi-theta.
809 // Add img(-x,y)*k to the raysum of LOR (viewNr-view,bin)
810 scnptr[(viewNr - view)*binNr + bin] +=
811 eps1 * imgptr[yp*imgDim + xn];
812 // Add img(x,-y)*k to the raysum of LOR (viewNr-view,binNr-bin)
813 if(bin != center)
814 scnptr[(viewNr-view)*binNr + binNr - 1 - bin] +=
815 eps1 * imgptr[yn*imgDim + xp];
816
817 // Mirror the LOR on line x=y, i.e. x->y.
818 // Case: pi/2-theta
819 // Add img(-y,-x)*k to the raysum of LOR (viewNr/2-view,bin)
820 scnptr[(viewNr/2 - view)*binNr + bin] +=
821 eps1 * imgptr[xn*imgDim + yn];
822 // Add img(y,x)*k to the raysum of LOR (viewNr/2-view,binNr-bin)
823 if(bin != center)
824 scnptr[(viewNr/2 - view)*binNr + binNr - 1 - bin] +=
825 eps1 * imgptr[xp*imgDim + yp];
826 }
827
828 // Mirror the LOR on line x=y, and on y-axis i.e x->y and y->-y.
829 // Case: pi/2+theta
830 // Add img(y,-x)*k to the raysum of LOR (viewNr/2+view,bin)
831 scnptr[(viewNr/2 + view)*binNr + bin] +=
832 eps1 * imgptr[xn*imgDim + yp];
833 // Add img(y,-x)*k to the raysum of LOR (viewNr/2+view,binNr-bin)
834 if(bin != center)
835 scnptr[(viewNr/2 + view)*binNr + binNr - 1 - bin] +=
836 eps1 * imgptr[xp*imgDim + yn];
837 }
838 }
839
840 // Limit (y-)indices for fast search.
841 // Note that indices are non-negative integers.
842 y_bottom = floor((float)(Yptr[imgDim] + bin*shift_y + imgDim/2));
843 if(y_bottom < 0) y_bottom = 0;
844 if(y_bottom > imgDim) y_bottom = 0;
845
846 y_top = floor((float)(Yptr[0] + bin*shift_y + imgDim/2));
847 if(y_top > imgDim) y_top = imgDim;
848 if(y_top <= 0) y_top = 1;
849
850 /* Iterate through the values in vector X, in integer points
851 [y_bottom,y_top]. */
852 for(z=y_top; z >= y_bottom; z--) {
853
854 // Look y from this location.
855 xp = floor(Xptr[z] + bin*shift_x) + imgDim/2;
856 xn = imgDim - 1 - xp;
857
858 yp = imgDim - z - 1;
859 yn = imgDim - yp - 1;
860
861 // If the x-value for this y (z) is inside the image grid.
862 if(yp < imgDim && yp >= 0 && yn < imgDim && yn >= 0 && xp >= 0 &&
863 xp < imgDim && xn < imgDim && xn >= 0)
864 {
865 eps1=eps2=eps3=0;
866 dx = (float)(Xptr[z] + bin*shift_x + imgDim/2 - xp);
867 dy = (float)(Yptr[xp] + bin*shift_y - z + imgDim/2);
868 if(dy < 1){ // Cases 3,4,5 and 6.
869 // 1. PART
870 // a := |HA|
871 a = dy;
872 // b := |HB| (b < 1 for angles in [0,pi/4))
873 b = dx;
874 // h := height of rectangle R.
875 h = a + shift_y;
876 if(h > 1){ // Cases 3,4 and 5.
877 h = 1;
878 g = b + shift_x;
879 if(g > 1){ // Cases 3 and 4.
880 g = 1;
881 xp2 =floor(Xptr[z+1] + (bin+1)*shift_x) + imgDim/2;
882 if(xp == xp2){ // Case 4.
883 // c := |FC|
884 c = (float)(xp + 1 - (imgDim/2 + Xptr[z+1] +
885 (bin+1)*shift_x));
886 // d := |FD|
887 d = (float)(floor(Yptr[xp + 1] + (bin+1)*shift_y) + 1 -
888 (Yptr[xp + 1] + (bin+1)*shift_y));
889 eps1 = 1 - (a*b + c*d)/2;
890 eps2 = 0;
891 // Lower triangle on the next pixel (x+1,y).
892 eps3 = (1 - d)*(b + shift_x - 1)/2;
893 if((eps1<0 || eps1>1 || eps2<0 || eps2>1 || eps3<0 || eps3>1)
894 && RADON_VERBOSE) printf(
895 "4: (%i,%i) eps1=%f | (%i,%i) eps2=%f | (%i,%i) eps3=%f\n",
896 xp,yp,eps1,xp+1,yp-1,eps2,xp+1,yp,eps3);
897 } else { // Case 3.
898 // c=d=0.
899 eps1 = 1 - a*b/2;
900
901 // Calculate area on pixel in place (xp+1,yp-1).
902 dy = (float)(Yptr[xp+1] + (bin+1)*shift_y - (z + 1) +
903 imgDim/2);
904 if(dy < 1){ // Case 11.
905 // c := |HC|
906 c = dy;
907 // d := |HD|
908 d = (float)(xp + 2 - (imgDim/2 + Xptr[z+1] +
909 (bin+1)*shift_x));
910 eps2 = c*d/2;
911 } else { // Cases 9 and 10.
912 dx = (float)(xp + 2 - (imgDim/2 + Xptr[z+1] +
913 (bin+1)*shift_x));
914 if(dx < 1) { // Case 10.
915 // g := length of rectangle Q.
916 g = dx;
917 // c := |CD| (on x-axis).
918 c = dx - (float)(xp + 2 - (imgDim/2 + Xptr[z+2] +
919 (bin+1)*shift_x));
920 // Rectangle Q - triangle c*h (h = 1).
921 eps2 = g - c/2;
922 } else { // Case 9.
923 // c := |FC|
924 c = (float)(xp + 2 - (imgDim/2 + Xptr[z+2] +
925 (bin+1)*shift_x));
926 // d := |FD|
927 d = (float)(floor(Yptr[xp + 2] + (bin+1)*shift_y) + 2 -
928 (Yptr[xp + 2] + (bin+1)*shift_y));
929 // Rectangle Q - triangle CFD.
930 eps2 = 1 - c*d/2;
931 }
932 }
933
934 // Calculate area on pixel in place (xp+1,yp).
935 dx = (float)(xp + 2 - (imgDim/2 + Xptr[z] + (bin+1)*shift_x));
936 if(dx < 1){ // Case 10.
937 // g := length of rectangle Q.
938 g = dx;
939 // c := |CD| (on x-axis).
940 c = dx - (float)(xp + 2 - (imgDim/2 + Xptr[z+1] +
941 (bin+1)*shift_x));
942 // Rectangle Q - triangle c*h (h = 1).
943 eps3 = g - c/2;
944 } else { // Case 9.
945 // c := |FC|
946 c = (float)(xp + 2 - (imgDim/2 + Xptr[z+1] +
947 (bin+1)*shift_x));
948 // d := |FD|
949 d = (float)(floor(Yptr[xp + 2] + (bin+1)*shift_y) + 1 -
950 (Yptr[xp + 2] + (bin+1)*shift_y));
951 // Rectangle Q - triangle CFD.
952 eps3 = 1 - c*d/2;
953 }
954 if((eps1<0 || eps1>1 || eps2<0 || eps2>1 || eps3<0 || eps3>1)
955 && RADON_VERBOSE) printf(
956 "3/v%i: (%i,%i) eps1=%f | (%i,%i) eps2=%f | (%i,%i) eps3=%f\n",
957 view,xp,yp,eps1,xp+1,yp-1,eps2,xp+1,yp,eps3);
958 }
959 } else { // Case 5. (g < 1)
960 // c := |DC|.
961 c = g - (imgDim/2 + Xptr[z+1] + (bin+1)*shift_x - xp);
962 // d := heigth
963 d = 1;
964 eps1 = g*h - (a*b + c*d)/2;
965 eps2 = 0;
966 eps3 = 0;
967 if((eps1<0 || eps1>1 || eps2<0 || eps2>1 || eps3<0 || eps3>1)
968 && RADON_VERBOSE) printf(
969 "5: (%i,%i) eps1=%f | (%i,%i) eps2=%f | (%i,%i) eps3=%f\n",
970 xp,yp,eps1,xp+1,yp-1,eps2,xp+1,yp,eps3);
971 }
972 } else{ // Case 6 (h <= 1).
973 // g := legth of rectangle R
974 g = b + shift_x;
975 if(g > 1) // Should always be < 1 for angles in [0,pi/4)
976 g = 1;
977 eps1 = (g*h - a*b)/2;
978 eps2 = 0;
979 eps3 = 0;
980 if((eps1<0 || eps1>1 || eps2<0 || eps2>1 || eps3<0 || eps3>1) &&
981 RADON_VERBOSE) printf(
982 "6: (%i,%i) eps1=%f | (%i,%i) eps2=%f | (%i,%i) eps3=%f\n",
983 xp,yp,eps1,xp+1,yp-1,eps2,xp+1,yp,eps3);
984 }
985 } else { // 2. PART
986 // Cases 2,7 and 8. (dy >= 1).
987 // a := |HA|
988 a = 1;
989 // b := |HB| (>=1)
990 b = dx - (float)(Xptr[z+1] + bin*shift_x + imgDim/2 - xp);
991 // h := heigth of rectangle R
992 h = 1;
993 // g := length of rectangle R
994 g = dx + shift_x;
995 if(g > 1){ // Cases 2 and 8.
996 g = 1 - (float)(Xptr[z+1] + bin*shift_x + imgDim/2 - xp);
997 // positive x-coordinate (bin+1)
998 xp2 = floor(Xptr[z+1] + (bin+1)*shift_x) + imgDim/2;
999 if(xp == xp2){ // Case 8.
1000 // c := |FC|
1001 c = (float)(xp + 1 - (imgDim/2 + Xptr[z+1] +
1002 (bin+1)*shift_x));
1003 // d := |FD|
1004 d = (float)(floor(Yptr[xp + 1] + (bin+1)*shift_y) + 1 -
1005 (Yptr[xp + 1] + (bin+1)*shift_y));
1006 eps1 = g*h - (a*b + c*d)/2;
1007 eps2 = 0;
1008 // Lower triangle on the next pixel (x+1,y).
1009 eps3 = (1 - d)*((Xptr[z] + (bin+1)*shift_x + imgDim/2) -
1010 (xp+1))/2;
1011 if((eps1<0 || eps1>1 || eps2<0 || eps2>1 || eps3<0 || eps3>1)
1012 && RADON_VERBOSE) printf(
1013 "8: (%i,%i) eps1=%f | (%i,%i) eps2=%f | (%i,%i) eps3=%f\n",
1014 xp,yp,eps1,xp+1,yp-1,eps2,xp+1,yp,eps3);
1015 } else{ // Case 2.
1016 // c=d=0.
1017 eps1 = g*h - a*b/2;
1018 /* Pixel in place (xp+1,yp-1) should have been found in
1019 the previous step. */
1020 eps2 = 0;
1021 // Calculate area on pixel in place (xp+1,yp).
1022 dx = (float)((imgDim/2 + Xptr[z] + (bin+1)*shift_x) - (xp+1));
1023 if(dx < 1){ // Case 10 (trapezium).
1024 // g := bottom of trapezium Q.
1025 g = dx;
1026 // c := top of trapezium Q.
1027 c = (float)((imgDim/2 + Xptr[z+1] + (bin+1)*shift_x) -
1028 (xp+1));
1029 // Area of trapezium Q. Heigth = 1.
1030 eps3 = (g + c)/2;
1031 if((eps1<0 || eps1>1 || eps2<0 || eps2>1 || eps3<0 ||
1032 eps3>1) && RADON_VERBOSE) printf(
1033 "2/10: (%i,%i) eps1=%f | (%i,%i) eps2=%f | (%i,%i) eps3=%f\n",
1034 xp,yp,eps1,xp+1,yp-1,eps2,xp+1,yp,eps3);
1035 } else { // Case 9.
1036 // c := |FC|
1037 c = (float)(xp + 2 - (imgDim/2 + Xptr[z+1] +
1038 (bin+1)*shift_x));
1039 // d := |FD|
1040 d = (float)(floor(Yptr[xp + 2] + (bin+1)*shift_y) + 1 -
1041 (Yptr[xp + 2] + (bin+1)*shift_y));
1042 // Rectangle Q - triangle CFD.
1043 eps3 = 1 - c*d/2;
1044 if((eps1<0 || eps1>1 || eps2<0 || eps2>1 || eps3<0 ||
1045 eps3>1) && RADON_VERBOSE) printf(
1046 "2/9: (%i,%i) eps1=%f | (%i,%i) eps2=%f | (%i,%i) eps3=%f\n",
1047 xp,yp,eps1,xp+1,yp-1,eps2,xp+1,yp,eps3);
1048 }
1049 }
1050 } else { // Case 7. (g < = 1)
1051 // Area of the parallelogram R.
1052 eps1 = sdist/cosinus;
1053 eps2 = 0;
1054 eps3 = 0;
1055 if((eps1<0 || eps1>1 || eps2<0 || eps2>1 || eps3<0 || eps3>1)
1056 && RADON_VERBOSE) printf(
1057 "7: (%i,%i) eps1=%f | (%i,%i) eps2=%f | (%i,%i) eps3=%f\n",
1058 xp,yp,eps1,xp+1,yp-1,eps2,xp+1,yp,eps3);
1059 }
1060 }
1061 if(!eps2 && !eps3){ // Cases 5,6 and 7.
1062 // Case: theta.
1063 // Add img(x,y)*k to the raysum of LOR (view,bin)
1064 scnptr[view*binNr + bin] += eps1 * imgptr[yp*imgDim + xp];
1065 // Add img(-x,-y)*k to the raysum of LOR (view,binNr-bin)
1066 if(bin != center)
1067 scnptr[view*binNr + binNr - 1 - bin] +=
1068 eps1 * imgptr[yn*imgDim + xn];
1069 if(view != viewNr/4){
1070 // Mirror the LOR on y-axis, i.e. x->-x
1071 // Case: pi-theta.
1072 // Add img(-x,y)*k to the raysum of LOR (viewNr-view,bin)
1073 scnptr[(viewNr - view)*binNr + bin] +=
1074 eps1 * imgptr[yp*imgDim + xn];
1075 // Add img(x,-y)*k to the raysum of LOR (viewNr-view,binNr-bin)
1076 if(bin != center)
1077 scnptr[(viewNr-view)*binNr + binNr - 1 - bin] +=
1078 eps1 * imgptr[yn*imgDim + xp];
1079
1080 // Mirror the LOR on line y=x, i.e. y->x.
1081 // Case: pi/2 - theta.
1082 // Add img(y,x)*k to the raysum of LOR (viewNr/2-view,bin).
1083 scnptr[(viewNr/2 - view)*binNr + bin] +=
1084 eps1 * imgptr[xn*imgDim + yn];
1085 // Add img(-y,-x)*k to the raysum of LOR (viewNr/2-view,binNr-bin)
1086 if(bin != center)
1087 scnptr[(viewNr/2 - view)*binNr + binNr - 1 - bin] +=
1088 eps1 * imgptr[xp*imgDim + yp];
1089 }
1090
1091 // Mirror the LOR on line x=y, and on y-axis i.e x->y and y->-y.
1092 // Case: pi/2 + theta.
1093 // Add img(y,-x)*k to the raysum of LOR (viewNr/2+view,bin)
1094 scnptr[(viewNr/2 + view)*binNr + bin] +=
1095 eps1 * imgptr[xn*imgDim + yp];
1096 // Add img(-y,x)*k to the raysum of LOR (viewNr-view,binNr-bin)
1097 if(bin != center)
1098 scnptr[(viewNr/2 + view)*binNr + binNr - 1 - bin] +=
1099 eps1 * imgptr[xp*imgDim + yn];
1100 } else {
1101 if(!eps2) { // <=> eps3 != 0 & eps2 = 0 <=> Cases 3,4 and 8.
1102 if(xp + 1 < imgDim && xn - 1 >= 0){
1103 // Case: theta.
1104 // Add img(x,y)*k to the raysum of LOR (view,bin)
1105 scnptr[view*binNr + bin] +=
1106 eps1 * imgptr[yp*imgDim + xp] +
1107 eps3 * imgptr[yp*imgDim + xp+1];
1108 // Add img(-x,-y)*k to the raysum of LOR (view,binNr-bin)
1109 if(bin != center)
1110 scnptr[view*binNr + binNr - 1 - bin] +=
1111 eps1 * imgptr[yn*imgDim + xn] +
1112 eps3 * imgptr[yn*imgDim + xn-1];
1113 if(view != viewNr/4) {
1114 // Mirror the LOR on y-axis, i.e. x->-x
1115 // Case: pi-theta.
1116 // Add img(-x,y)*k to the raysum of LOR (viewNr-view,bin)
1117 scnptr[(viewNr - view)*binNr + bin] +=
1118 eps1 * imgptr[yp*imgDim + xn] +
1119 eps3 * imgptr[yp*imgDim + xn-1];
1120 // Add img(x,-y)*k to the raysum of LOR (viewNr-view,binNr-bin)
1121 if(bin != center)
1122 scnptr[(viewNr-view)*binNr + binNr - 1 - bin] +=
1123 eps1 * imgptr[yn*imgDim + xp] +
1124 eps3 * imgptr[yn*imgDim + xp+1];
1125
1126 // Mirror the LOR on line y=x, i.e. y->x.
1127 // Case: pi/2 - theta.
1128 // Add img(y,x)*k to the raysum of LOR (viewNr/2-view,bin).
1129 scnptr[(viewNr/2 - view)*binNr + bin] +=
1130 eps1 * imgptr[xn*imgDim + yn] +
1131 eps3 * imgptr[(xn-1)*imgDim + yn];
1132 /* Add img(-y,-x)*k to the raysum of LOR
1133 (viewNr/2-view,binNr-bin) */
1134 if(bin != center)
1135 scnptr[(viewNr/2 - view)*binNr + binNr - 1 - bin] +=
1136 eps1 * imgptr[xp*imgDim + yp] +
1137 eps3*imgptr[(xp+1)*imgDim+yp];
1138 }
1139 // Mirror the LOR on line x=y, and on y-axis i.e x->y and y->-y.
1140 // Case: pi/2 + theta.
1141 // Add img(y,-x)*k to the raysum of LOR (viewNr/2+view,bin)
1142 scnptr[(viewNr/2 + view)*binNr + bin] +=
1143 eps1 * imgptr[xn*imgDim + yp] +
1144 eps3 * imgptr[(xn-1)*imgDim + yp];
1145 // Add img(-y,x)*k to the raysum of LOR (viewNr-view,binNr-bin)
1146 if(bin != center)
1147 scnptr[(viewNr/2 + view)*binNr + binNr - 1 - bin] +=
1148 eps1 * imgptr[xp*imgDim + yn] +
1149 eps3*imgptr[(xp+1)*imgDim+yn];
1150 }
1151 } else { // <=> eps2!=0 && eps3!=0 <=> Case 3.
1152 if(xp + 1 < imgDim && xn - 1 >= 0 && yp-1 >= 0 && yn+1 < imgDim) {
1153 // Case: theta.
1154 // Add img(x,y)*k to the raysum of LOR (view,bin)
1155 scnptr[view*binNr + bin] +=
1156 eps1 * imgptr[yp*imgDim + xp] +
1157 eps3 * imgptr[yp*imgDim + xp+1] +
1158 eps2 * imgptr[(yp-1)*imgDim + xp+1];
1159 // Add img(-x,-y)*k to the raysum of LOR (view,binNr-bin)
1160 if(bin != center)
1161 scnptr[view*binNr + binNr - 1 - bin] +=
1162 eps1 * imgptr[yn*imgDim + xn] +
1163 eps3 * imgptr[yn*imgDim + xn-1] +
1164 eps2 * imgptr[(yn+1)*imgDim + xn-1];
1165
1166 if(view != viewNr/4){
1167 // Mirror the LOR on y-axis, i.e. x->-x
1168 // Case: pi-theta.
1169 // Add img(-x,y)*k to the raysum of LOR (viewNr-view,bin)
1170 scnptr[(viewNr - view)*binNr + bin] +=
1171 eps1 * imgptr[yp*imgDim + xn] +
1172 eps3 * imgptr[yp*imgDim + xn-1] +
1173 eps2 * imgptr[(yp-1)*imgDim + xn-1];
1174 // Add img(x,-y)*k to the raysum of LOR (viewNr-view,binNr-bin)
1175 if(bin != center)
1176 scnptr[(viewNr-view)*binNr + binNr - 1 - bin] +=
1177 eps1 * imgptr[yn*imgDim + xp] +
1178 eps3 * imgptr[yn*imgDim + xp+1] +
1179 eps2 * imgptr[(yn+1)*imgDim + xp+1];
1180
1181 // Mirror the LOR on line y=x, i.e. y->x.
1182 // Case: pi/2 - theta.
1183 // Add img(y,x)*k to the raysum of LOR (viewNr/2-view,bin)
1184 scnptr[(viewNr/2 - view)*binNr + bin] +=
1185 eps1 * imgptr[xn*imgDim + yn] +
1186 eps3 * imgptr[xn*imgDim + yn-1] +
1187 eps2 * imgptr[(xn-1)*imgDim + (yn+1)];
1188 // Add img(-y,-x)*k to the raysum of LOR (viewNr/2-view,binNr-bin)
1189 if(bin != center)
1190 scnptr[(viewNr/2 - view)*binNr + binNr - 1 - bin] +=
1191 eps1 * imgptr[xp*imgDim + yp] +
1192 eps3*imgptr[(xp+1)*imgDim+yp] +
1193 eps2*imgptr[(xp+1)*imgDim+(yp-1)];
1194 }
1195
1196 // Mirror the LOR on line x=y, and on y-axis i.e x->y and y->-y.
1197 // Case: pi/2 + theta.
1198 // Add img(y,-x)*k to the raysum of LOR (viewNr/2+view,bin)
1199 scnptr[(viewNr/2 + view)*binNr + bin] +=
1200 eps1 * imgptr[xn*imgDim + yp] +
1201 eps3 * imgptr[(xn-1)*imgDim + yp] +
1202 eps2 * imgptr[(xn-1)*imgDim + (yp-1)];
1203 // Add img(-y,x)*k to the raysum of LOR (viewNr-view,binNr-bin)
1204 if(bin != center)
1205 scnptr[(viewNr/2 + view)*binNr + binNr - 1 - bin] +=
1206 eps1 * imgptr[xp*imgDim + yn] +
1207 eps3*imgptr[(xp+1)*imgDim+yn] +
1208 eps2*imgptr[(xp+1)*imgDim+yn+1];
1209 }
1210 }
1211 }
1212 }
1213 }
1214 }// END of X loop
1215 }// End of view>0.
1216 }// END OF VIEW LOOP
1217 free(X);
1218 free(Y);
1219 if( RADON_VERBOSE ){
1220 printf("RADON: radonFwdTransformEA() finished.\n");
1221 fflush(stdout);
1222 }
1223 return 0;
1224} // END OF EXACT AREA FORWARD TRANSFORM

◆ radonFwdTransformPRM()

int radonFwdTransformPRM ( PRMAT * mat,
int set,
int setNr,
float * imgdata,
float * scndata )
extern

Transforms the given intensity image in spatial domain to Radon domain. Transform is calculated by multiplying with the given projection matrix from the left. Transform is calculated only in those angles belonging into given subset. Subset contains angles starting from the index 'set' with spacing 'setNr'. Discretisation model utilised in this function is '0/1', 'length of intersection' or 'exact area' according to the given projection matrix.

Precondition
imgdata contains pixel values for every pixel in n x n image grid
Postcondition
imgdata is mapped into the projection space.
Parameters
matcontains an initialised projection matrix
settells which set is to be utilized; 0 < set < setNr-1
setNrnumber of subsets (spacing between indices)
imgdatacontains pixel values for every pixel in dim*dim image grid.
scndataviewNr*binNr vector for storing the projection
Returns
int 0 if ok

Definition at line 1328 of file radon.c.

1330 {
1331 float *imgptr, *scnptr; // pointers for the image and sinogram data
1332 unsigned int imgDim=128, binNr=256, viewNr=192, view, bin, row, col;
1333 unsigned int half, center;
1334 int xp, xn, yp, yn;
1335 float fact;
1336
1337 // Retrieve the data from given projection matrix.
1338 imgDim=prmatGetID(mat);
1339 binNr=prmatGetNB(mat); // Should be equal to imgDim.
1340 viewNr=prmatGetNV(mat);
1341
1342 // Calculate and set the center bin.
1343 if((binNr%2) != 0){
1344 half = (binNr - 1)/2 + 1;
1345 center = half - 1;
1346 } else{
1347 half = binNr/2;
1348 // In the case binNr is even there is no center bin.
1349 center = -1;
1350 }
1351
1352 imgptr = imgdata;
1353 scnptr = scndata;
1354
1355 // Draw sinogram according to projection matrix.
1356 for(view=set; view<=viewNr/4; view=view+setNr){
1357 for(bin=0; bin<half; bin++){
1358 row = view*half + bin;
1359 for(col=0; col<prmatGetPixels(mat,row); col++){
1360
1361 fact = prmatGetFactor(mat,row,col);
1362 xp = prmatGetXCoord(mat,row,col);
1363 xn = imgDim - xp - 1;
1364
1365 yp = prmatGetYCoord(mat,row,col);
1366 yn = imgDim - yp - 1;
1367
1368 // Case: theta.
1369 // Add img(x,y)*k to the raysum of LOR (view,bin)
1370 scnptr[view*binNr + bin] += fact * imgptr[yp*imgDim + xp];
1371 // Add img(-x,-y)*k to the raysum of LOR (view,binNr-bin)
1372 if(bin != center)
1373 scnptr[view*binNr + binNr - 1 - bin] += fact * imgptr[yn*imgDim + xn];
1374
1375 if(view != 0 && view != viewNr/4){
1376 // Mirror the LOR on y-axis, i.e. x->-x
1377 // Case: pi-theta.
1378 // Add img(-x,y)*k to the raysum of LOR (viewNr-view,bin)
1379 scnptr[(viewNr - view)*binNr + bin] += fact * imgptr[yp*imgDim + xn];
1380 // Add img(x,-y)*k to the raysum of LOR (viewNr-view,binNr-bin)
1381 if(bin != center)
1382 scnptr[(viewNr-view)*binNr + binNr - 1 - bin] +=
1383 fact * imgptr[yn*imgDim + xp];
1384
1385 // Mirror the LOR on line y=x, i.e. y->x.
1386 // Case: pi/2 - theta.
1387 // Add img(y,x)*k to the raysum of LOR (viewNr/2-view,bin)
1388 scnptr[(viewNr/2 - view)*binNr + bin] += fact * imgptr[xn*imgDim + yn];
1389 // Add img(-y,-x)*k to the raysum of LOR (viewNr/2-view,binNr-bin)
1390 if(bin != center)
1391 scnptr[(viewNr/2 - view)*binNr + binNr - 1 - bin] +=
1392 fact * imgptr[xp*imgDim + yp];
1393 }
1394
1395 // Mirror the LOR on line x=y, and on y-axis i.e x->y and y->-y.
1396 // Case: pi/2 + theta.
1397 // Add img(y,-x)*k to the raysum of LOR (viewNr/2+view,bin)
1398 scnptr[(viewNr/2 + view)*binNr + bin] += fact * imgptr[xn*imgDim + yp];
1399 // Add img(-y,x)*k to the raysum of LOR (viewNr-view,binNr-bin)
1400 if(bin != center)
1401 scnptr[(viewNr/2 + view)*binNr + binNr - 1 - bin] +=
1402 fact * imgptr[xp*imgDim + yn];
1403 }
1404 }
1405 }
1406
1407 return 0;
1408
1409}// END OF FORWARD TRANSFORM WITH A PROJECTION MATRIX

◆ radonFwdTransformSA()

int radonFwdTransformSA ( RADON * radtra,
int set,
int setNr,
float * imgdata,
float * scndata )
extern

Same as 'radonFwdTransform()' but discretisation model in this function is 'linear interpolation' or 'nearest neighbour interpolation' according to the given Radon transform object.

Parameters
radtracontains an initialized radon transform object.
settells which set is to be utilized; 0 < set < setNr-1
setNrnumber of subsets
imgdatacontains pixel values for every pixel in dim*dim image grid.
scndataviewNr*binNr vector for storing the projection
Returns
int 0 if ok
Note
First written by Sakari Alenius 1998.

Definition at line 1238 of file radon.c.

1240 {
1241 float *imgptr, *scnptr, *imgorigin;
1242 float sinus, cosinus;
1243 float t; // distance between projection ray and origo.
1244 int mode, imgDim, binNr, viewNr, halfImg, centerBin, view;
1245 int x, y, xright, ybottom;
1246 float fract, tpow2;
1247
1248 // Retrieve the data from given radon transform object.
1249 mode=radonGetMO(radtra); // Should be 3 or 4.
1250 imgDim=radonGetID(radtra);
1251 binNr=radonGetNB(radtra); // Should be equal to imgDim.
1252 viewNr=radonGetNV(radtra);
1253 // Set the center ray and the square of it.
1254 centerBin=binNr/2;
1255 tpow2 = centerBin*centerBin;
1256
1257 if(imgDim != binNr) return -1;
1258
1259 // Set half of the image dimension.
1260 halfImg = imgDim/2;
1261
1262 // Transform one angle at a time.
1263 for(view=set; view<viewNr; view+=setNr) {
1264
1265 imgorigin = imgdata + imgDim*(halfImg - 1) + halfImg;
1266
1267 sinus = radonGetSin(radtra,view);
1268 cosinus = radonGetSin(radtra,viewNr/2 + view);
1269
1270 y = halfImg - 2;
1271
1272 if((float)y > centerBin){
1273 y = (int)(centerBin);
1274 ybottom = -y;
1275 } else{
1276 ybottom = -halfImg + 1;
1277 }
1278
1279 for(; y >= ybottom; y--) {
1280 xright = (int)sqrt(/*fabs(*/tpow2 - ((float)y+0.5) *
1281 ((float)y+0.5)/*)*/) + 1;
1282 if(xright >= halfImg){
1283 xright = halfImg - 1;
1284 x = -halfImg;
1285 } else
1286 x = -xright;
1287
1289 // t = centerBin - (float)y * sinus + ((float)(x + 1)) * cosinus;
1290 t = centerBin + (float)y * sinus + ((float)(x + 1)) * cosinus;
1291
1292 imgptr = imgorigin - y*imgDim + x;
1293 scnptr = scndata + view*binNr;
1294 // for(; x <= xright; x++, t += cosinus){
1295 for(; x <= xright; x++, t += cosinus){
1296 if(mode == 3){ // If the linear interpolation is to be utilised.
1297 fract = t - (float)(int)t;
1298 *(scnptr+(int)t) += *imgptr * (1.0 - fract);
1299 *(scnptr+(int)t + 1) += *imgptr++ * fract;
1300 }
1301 else // If the nearest neighbour interpolation is to be utilised.
1302 *(scnptr+(int)(t + 0.5)) += *imgptr++;
1303 }
1304 }
1305 }
1306
1307 return 0;
1308}// END OF FORWARD TRANSFORM USING THE IMAGE ROTATION APPROACH

◆ radonGetCB()

int radonGetCB ( RADON * radtra)
extern

Returns the center bin in this radon transform.

Parameters
radtraradon transform for which the center bin is to be returned.
Returns
int index of the center bin.

Definition at line 180 of file radon.c.

181{
182 return radtra->centerBin;
183}
int centerBin
Definition libtpcrec.h:269

Referenced by radonBackTransform(), radonBackTransformEA(), radonFwdTransform(), radonFwdTransformEA(), and radonSetLUT().

◆ radonGetHI()

int radonGetHI ( RADON * radtra)
extern

Returns the half index of the bins in this radon transform.

Parameters
radtraradon transform for which the half index is to be returned.
Returns
int half index of the bins.

Definition at line 169 of file radon.c.

170{
171 return radtra->half;
172}
int half
Definition libtpcrec.h:267

Referenced by radonBackTransform(), radonBackTransformEA(), radonFwdTransform(), radonFwdTransformEA(), radonSetBases(), radonSetBasesEA(), and radonSetLUT().

◆ radonGetID()

int radonGetID ( RADON * radtra)
extern

Returns the image dimension in this radon transform.

Parameters
radtraradon transform for which the image dimension is to be returned.
Returns
int image dimension.

Definition at line 128 of file radon.c.

129{
130 return radtra->imgDim;
131}
int imgDim
Definition libtpcrec.h:261

Referenced by radonBackTransform(), radonBackTransformEA(), radonBackTransformSA(), radonFwdTransform(), radonFwdTransformEA(), radonFwdTransformSA(), radonSetBases(), radonSetBasesEA(), radonSetLORS(), and radonSetLUT().

◆ radonGetMO()

int radonGetMO ( RADON * radtra)
extern

Returns the discretization model of this radon transform.

Parameters
radtraradon transform for which the mode is to be returned.
Returns
int mode

Definition at line 119 of file radon.c.

120{
121 return radtra->mode;
122}
char mode
Definition libtpcrec.h:259

Referenced by radonBackTransform(), radonBackTransformSA(), radonFwdTransform(), radonFwdTransformSA(), radonSetBases(), and radonSetBasesEA().

◆ radonGetNB()

int radonGetNB ( RADON * radtra)
extern

Returns the number of bins in this radon transform.

Parameters
radtraradon transform for which the number of bins is to be returned.
Returns
int number of bins.

Definition at line 148 of file radon.c.

149{
150 return radtra->binNr;
151}
int binNr
Definition libtpcrec.h:265

Referenced by radonBackTransform(), radonBackTransformEA(), radonBackTransformSA(), radonFwdTransform(), radonFwdTransformEA(), radonFwdTransformSA(), radonSetBases(), radonSetBasesEA(), radonSetLORS(), and radonSetLUT().

◆ radonGetNV()

int radonGetNV ( RADON * radtra)
extern

Returns the number of views in this radon transform.

Parameters
radtraradon transform for which the number of views is to be returned.
Returns
int number of views.

Definition at line 138 of file radon.c.

139{
140 return radtra->viewNr;
141}
int viewNr
Definition libtpcrec.h:263

Referenced by radonBackTransform(), radonBackTransformEA(), radonBackTransformSA(), radonFwdTransform(), radonFwdTransformEA(), radonFwdTransformSA(), radonSetBases(), radonSetBasesEA(), radonSetLORS(), and radonSetLUT().

◆ radonGetSD()

float radonGetSD ( RADON * radtra)
extern

Returns the sample distance in this radon transform.

Parameters
radtraradon transform for which the sample distance is to be returned.
Returns
float sample distance.

Definition at line 159 of file radon.c.

160{
161 return radtra->sampleDist;
162}
float sampleDist
Definition libtpcrec.h:271

Referenced by radonBackTransform(), radonBackTransformEA(), radonFwdTransform(), radonFwdTransformEA(), radonSetBases(), radonSetBasesEA(), and radonSetLUT().

◆ radonGetSin()

float radonGetSin ( RADON * radtra,
int nr )
extern

Returns the sine for given angle (index).

Parameters
radtraradon transform for which the sine is to be returned.
nrindex of the angle to be returned (angle=nr*pi/radonGetNB(RADON)).
Returns
float sin(nr*pi/binNr).

Definition at line 192 of file radon.c.

193{
194 return radtra->sines[nr];
195}

Referenced by radonBackTransform(), radonBackTransformEA(), radonBackTransformSA(), radonFwdTransform(), radonFwdTransformEA(), radonFwdTransformSA(), radonSetBases(), and radonSetBasesEA().

◆ radonSet()

int radonSet ( RADON * radtra,
int mode,
int imgDim,
int viewNr,
int binNr )
extern

Sets the data for the 2-D Radon transform.

Precondition
dim > 0
Postcondition
Parameters for the radon transform are set
Parameters
radtraradon transform for which the paramaters are to be set
modediscretisation mode
imgDimimage dimension
viewNrNumber of views (angles)
binNrNumber of bins (distances)
Returns
0 if ok

Definition at line 62 of file radon.c.

63{
64 int i;
65
66 if( RADON_VERBOSE ){
67 printf("RADON: radonSet() started.\n");
68 fflush(stdout);
69 }
70
71 // Set the parameters.
72 radtra->mode=mode;
73
74 if(imgDim <= 0) return -1;
75 else radtra->imgDim=imgDim;
76
77 if(viewNr <= 0) return -2;
78 else radtra->viewNr=viewNr;
79
80 if(binNr <= 0) return -3;
81 else radtra->binNr=binNr;
82
83 radtra->sampleDist=(float)imgDim/(float)binNr;
84
85 // Calculate and set center bin for current geometrics.
86 if((binNr%2) != 0){
87 radtra->half = (binNr - 1)/2 + 1;
88 radtra->centerBin = radtra->half - 1;
89 } else {
90 radtra->half = binNr/2;
91 // In the case binNr is even there is no center bin.
92 radtra->centerBin = -1;
93 }
94
95 /* Set the sine table to contain values of sine to cover the required values
96 of cosine as well. */
97 radtra->sines=(float*)calloc(3*viewNr/2,sizeof(float));
98 if(radtra->sines==NULL) return -5;
99 //Put the values sin(view*pi/viewNr) for view=0:3*viewNr/2 - 1 in the table
100 for(i=0; i< 3*viewNr/2; i++) {
101 radtra->sines[i]=(float)sin((M_PI/(double)viewNr) * (double)i);
102 }
103 radtra->status=RADON_STATUS_INITIALIZED;
104
105 if( RADON_VERBOSE ){
106 printf("RADON: radonSet() done.\n");
107 fflush(stdout);
108 }
109 return 0;
110}

◆ radonSetBases()

int radonSetBases ( RADON * radtra,
ELLIPSE * elli,
PRMAT * mat )
extern

Sets the coordinates and factors for intersected pixels according to given special Radon transform operator for every coincidence line in the BASE set. Base set includes coincidence lines in range [0,pi/4].

Precondition
radtra is a radon transform operator && elli defines a field of view && mat is initialized.
Postcondition
coordinates and factors for pixels contributing to coincidence lines in the base set.
Parameters
radtraspecial Radon transform operator.
ellifield of view.
matpointer to the datastructure where coordinates and values are to be stored.
Returns
0 if ok.

Definition at line 2602 of file radon.c.

2604 {
2605 // temporary pointers for storing the coordinates and factors
2606 unsigned short int **coords, *factors, **coptr, *facptr;
2607 // pointers for the values of LOR in integer points
2608 float *Y, *X, *Xptr, *Yptr;
2609 double sinus, cosinus, tanus; // sin, cosine and tangent
2610 double shift_x, shift_y; // shift for LOR
2611 int xp, xn, yp, yn, z; //integer points
2612 int x_left, x_right, y_top, y_bottom; // limits for fast search
2613 int col, row, view, bin, pix; //counters
2614 int binNr, viewNr, imgDim, views, rows, mode, half; // properties
2615 float diam, sdist;
2616 float scale, sum=0, sqr_sum=0, min=0, max=0;
2617 float dx, dy , loi = 1; // delta x and y and length of intersection
2618
2619 // Check that the data for this radon transform is initialized.
2620 if(radtra->status != RADON_STATUS_INITIALIZED) return -1;
2621
2622 // Retrieve the data from given radon transform object.
2623 mode=radonGetMO(radtra);
2624 imgDim=radonGetID(radtra);
2625 binNr=radonGetNB(radtra);
2626 viewNr=radonGetNV(radtra);
2627 sdist=radonGetSD(radtra);
2628 half=radonGetHI(radtra);
2629
2630 // Set information in the projection matrix data stucture.
2631 if(binNr == 192) {
2632 mat->type=PRMAT_TYPE_ECAT931;
2633 } else if(binNr == 281){
2634 mat->type=PRMAT_TYPE_GE;
2635 } else
2636 mat->type=PRMAT_TYPE_NA;
2637
2638 mat->viewNr=viewNr;
2639 mat->binNr=binNr;
2640 mat->imgDim=imgDim;
2641
2642 mat->mode = mode;
2643 // Allocate memory in PRMAT struct and set fov.
2644 mat->prmatfov = (int*)calloc(2,sizeof(int));
2645 mat->prmatfov[0] = ellipseGetMajor(elli);
2646 mat->prmatfov[1] = ellipseGetMinor(elli);
2647
2648 // rows := number of lines in the base set = (views*half)
2649 views = viewNr/4 + 1;
2650 rows = views*half;
2651
2652 mat->factor_sqr_sum=calloc(rows,sizeof(float));
2653 mat->dimr=rows;
2654 //entries in one line
2655 mat->dime=calloc(rows,sizeof(int));
2656 mat->_factdata=(unsigned short int***)calloc(rows,sizeof(unsigned short int**));
2657 //if not enough memory
2658 if(!mat->_factdata || !mat->dime) return(4);
2659
2660 // Compute scaling factor, assuming that maximum value is 1.
2661 scale=65534./1;
2662 mat->scaling_factor=1./scale; //is the inverse of scale
2663
2664 /* Allocate (temporary) coordinate and factor arrays to maximum size
2665 (= 2*imgDim).
2666 Coords contains pairs (x,y), coordinates in cartesian coordinate system. */
2667 coords = (unsigned short int**)calloc(2*imgDim,sizeof(unsigned short int*));
2668 factors = (unsigned short int*)calloc(2*imgDim,sizeof(unsigned short int));
2669 if(!coords || !factors) return 5;
2670
2671 for(col=0; col<2*imgDim; col++){
2672 coords[col] = (unsigned short int*)calloc(2,sizeof(unsigned short int));
2673 if(!coords[col]) return -1;
2674 }
2675
2676 coptr = coords;
2677 facptr = factors;
2678
2680 // Set diameter of a pixel.
2681 diam = sqrt(2);
2682
2683 // Array for storing values A_x.
2684 X=(float*)calloc(imgDim+1,sizeof(float));
2685 // Array for storing values A_y.
2686 Y=(float*)calloc(imgDim+1,sizeof(float));
2687 if(X==NULL || Y==NULL){
2688 return -2;
2689 }
2690 Xptr=X;
2691 Yptr=Y;
2692
2694 // Find pixel coordinates of the contributing pixels for lines of response
2695 // belonging to first 1/4th of angles. From these pixel coordinates
2696 // others can be calculated via symmetries in projection space.
2697 // N.B. The line of response: a*x+b*y+c
2698 // => solve y: y=-x/tan(view) + s*(cos(theta)/tan(theta) + sin(theta))
2699 // solve x: x=-y*tan(theta) + s*(sin(theta)*tan(theta) + cos(theta))
2700
2701 for(view=0; view<views; view++){
2702 // Angle theta=0 -> sin(theta)=0.
2703 if(view==0){
2704
2705 //If the mode switch is on zero do the 0-1 model transform.
2706 if(mode == 0)
2707 loi = 1.;
2708 else
2709 loi=1/diam;
2710
2711 // Choose column according to sample distance for angle 0.
2712 col = 0;
2713 for(bin=0; bin<half; bin++){
2714 col = floor((float)(bin+.5*sdist)*sdist);
2715
2716 pix = 0; // length of list pixels (and factors)
2717 sqr_sum = 0;
2718
2719 // Iterate through the entries in the image matrix.
2720 // Set factors for pixels intersected by lines in the base set.
2721 for(row=0; row<imgDim; row++){
2722
2723 /* Check that pixel and pixels hit by symmetrical lines lay inside
2724 the FOV. */
2725 if(ellipseIsInside(elli,row,col) && ellipseIsInside(elli,row,imgDim -
2726 1 - col) && ellipseIsInside(elli,imgDim-1-col,row) &&
2727 ellipseIsInside(elli,col,row))
2728 {
2729 coptr[pix][0] = (unsigned short int)col;
2730 coptr[pix][1] = (unsigned short int)row;
2731 // Convert loi to unsigned short int.
2732 facptr[pix] = (unsigned short int)(scale*loi);
2733 // Look for minimal and maximal factor.
2734 if(min>loi) min=loi;
2735 if(max<loi) max=loi;
2736 // Compute square sums in every row.
2737 sqr_sum += loi*loi;
2738 sum += loi;
2739 pix++;
2740 }
2741 }
2742
2743 /* Allocate memory in factor pointer (dynamically according to number
2744 of pixels intersected). */
2745 if(pix){
2746 mat->_factdata[bin]=
2747 (unsigned short int**)calloc(pix,sizeof(unsigned short int*));
2748 if(!mat->_factdata[bin]) return -1;
2749 }
2750
2751 // Allocate leaves.
2752 for(col=0; col<pix; col++) {
2753 mat->_factdata[bin][col]=
2754 (unsigned short int*)calloc(3,sizeof(unsigned short int));
2755 if(!mat->_factdata[bin][col]) return -1;
2756 }
2757
2758 // Put now values in coordinates and factors array to result pointer.
2759 mat->fact = mat->_factdata;
2760 for(col=0; col<pix; col++) {
2761 mat->fact[bin][col][0] = coptr[col][0]; // x-coodinate
2762 mat->fact[bin][col][1] = coptr[col][1]; // y-coordinate
2763 mat->fact[bin][col][2] = facptr[col]; // factor
2764 }
2765
2766 //Set also the number of pixels belonging to each row and square sums.
2767 mat->dime[bin]=pix;
2768 mat->factor_sqr_sum[bin]=sqr_sum;
2769
2770 } // END OF BIN-LOOP FOR ANGLE 0.
2771 // End of view=0.
2772 } else {
2773
2774 // Set sine and cosine for this angle.
2775 sinus = (double)radonGetSin(radtra,view);
2776 cosinus = (double)radonGetSin(radtra,viewNr/2 + view);
2777 tanus = sinus/cosinus;
2778
2779 // Set shift from origin for the first line of response (-n/2,theta).
2780 // NOTE that image matrix is on cartesian coordinate system where origin
2781 // is in the middle and shift is in pixels.
2782 shift_y = -(imgDim/2 -.5*sdist)/sinus;
2783 shift_x = -(imgDim/2 -.5*sdist)/cosinus;
2784
2785 // Evaluate the function of the first LOR in integer points [-n/2,n/2].
2786 // NOTE that image matrix is on cartesian coordinate system where origin
2787 // is in the middle.
2788 z=-imgDim/2;
2789 for(col=0; col<imgDim+1; col++){
2790 Yptr[col]=(float)(shift_y - z/tanus);
2791 Xptr[col]=(float)(shift_x - z*tanus);
2792 z++;
2793 }
2794
2795 // Set shift from the first LOR.
2796 shift_y = (double)(sdist/sinus);
2797 shift_x = (double)(sdist/cosinus);
2798
2799 // Iterate through half the bins in this view,
2800 // and determine coordinates of pixels contributing to this LOR.
2801 // NOTE that shift is added according to 'bin' in every loop.
2802 // Calculate also the length of intersection.
2803 // Others are determined via symmetry in projection space.
2804
2805 for(bin=0; bin<half; bin++){
2806
2807 coptr = coords;
2808 facptr = factors;
2809 pix = 0;
2810 sqr_sum = 0;
2811
2812 // Limit (x-)indices for fast search.
2813 // Note that indices are non-negative integers.
2814
2815 x_left = floor((float)(Xptr[imgDim] + bin*shift_x + imgDim/2));
2816 if(x_left < 0) x_left = 0;
2817
2818 x_right = floor((float)(Xptr[0] + bin*shift_x + imgDim/2));
2819 if(x_right <= 0) x_right = 1;
2820 if(x_right > imgDim) x_right = imgDim - 1;
2821
2822 /* Iterate through the values in vector Y, in integer points
2823 [x_left,x_rigth]. */
2824 for(z=x_left; z <= x_right; z++) {
2825
2826 xp = z; //positive x-coordinate
2827 xn = imgDim - 1 - xp; //negative x-coordinate
2828
2829 // Look y from left.
2830 yp = imgDim/2 - floor(Yptr[xp + 1] + bin*shift_y) - 1;
2831 yn = imgDim - 1 - yp;
2832
2833 // If the y-value for this x (z) is inside the image grid.
2834 if(yp < imgDim && yp >= 0 && yn < imgDim && yn >= 0 && xp >= 0 &&
2835 xp < imgDim && xn < imgDim && xn >= 0) {
2836
2837 if(!mode) {
2838 loi = 1;
2839 } else {
2840 // Compute delta x and y.
2841 dx = (float)(xp + 1 - (imgDim/2 + Xptr[imgDim - yp] + bin*shift_x));
2842 dy = (float)(floor(Yptr[xp + 1] + bin*shift_y) + 1 -
2843 (Yptr[xp + 1] + bin*shift_y));
2844 if(dx > 1 || dx < 0) dx = 1;
2845 if(dy > 1 || dy < 0) dy = 1;
2846 loi = sqrt(dx*dx + dy*dy);
2847 loi=loi/diam;
2848 }
2849
2850 /* Check that pixel and pixels hit by symmetrical lines lay inside
2851 the FOV. */
2852 if(ellipseIsInside(elli,yp,xp) && ellipseIsInside(elli,yn,xn) &&
2853 ellipseIsInside(elli,yp,xn) && ellipseIsInside(elli,yn,xp) &&
2854 ellipseIsInside(elli,xn,yn) && ellipseIsInside(elli,xp,yp) &&
2855 ellipseIsInside(elli,xn,yp) && ellipseIsInside(elli,xp,yn)) {
2856
2857 // Put coordinates and factors in the list.
2858 coptr[pix][0] = xp;
2859 coptr[pix][1] = yp;
2860 facptr[pix] = (unsigned short int)(scale*loi);
2861
2862 // Look for minimal and maximal factor.
2863 if(min>loi) min=loi;
2864 if(max<loi) max=loi;
2865 sqr_sum += loi*loi;
2866 sum += loi;
2867 pix++;
2868 }
2869 }
2870 }
2871
2872 // Limit (y-)indices for fast search.
2873 // Note that indices are non-negative integers.
2874 y_bottom = floor((float)(Yptr[imgDim] + bin*shift_y + imgDim/2));
2875 if(y_bottom < 0) y_bottom = 0;
2876 if(y_bottom > imgDim) y_bottom = 0;
2877
2878 y_top = floor((float)(Yptr[0] + bin*shift_y + imgDim/2));
2879 if(y_top > imgDim) y_top = imgDim-1;
2880 if(y_top <= 0) y_top = 1;
2881
2882 /* Iterate through the values in vector X, in integer points
2883 [y_bottom,y_top]. */
2884 for(z=y_top; z >= y_bottom; z--) {
2885
2886 // Look y from this location.
2887 xp = floor(Xptr[z] + bin*shift_x) + imgDim/2;
2888 xn = imgDim - 1 - xp;
2889
2890 yp = imgDim - z - 1;
2891 yn = imgDim - yp - 1;
2892
2893 // If the x-value for this y (z) is inside the image grid.
2894 if(yp < imgDim && yp >= 0 && yn < imgDim && yn >= 0 && xp >= 0 &&
2895 xp < imgDim && xn < imgDim && xn >= 0) {
2896
2897 if(!mode){
2898 loi = 1;
2899 } else {
2900 dx = (float)(Xptr[z] + bin*shift_x + imgDim/2 - xp);
2901 dy = (float)(Yptr[xp] + bin*shift_y - z + imgDim/2);
2902 if(dy > 1 || dy < 0) {
2903 dx = dx - (float)(Xptr[z+1] + bin*shift_x + imgDim/2 - xp);
2904 dy = 1;
2905 }
2906 loi = sqrt(dx*dx + dy*dy)/diam;
2907 }
2908
2909 /* Check that pixel and pixels hit by symmetrical lines lay inside
2910 the FOV. */
2911 if(ellipseIsInside(elli,yp,xp) && ellipseIsInside(elli,yn,xn) &&
2912 ellipseIsInside(elli,yp,xn) && ellipseIsInside(elli,yn,xp) &&
2913 ellipseIsInside(elli,xn,yn) && ellipseIsInside(elli,xp,yp) &&
2914 ellipseIsInside(elli,xn,yp) && ellipseIsInside(elli,xp,yn)){
2915
2916 // Put coordinates and factors in the list.
2917 coptr[pix][0] = xp;
2918 coptr[pix][1] = yp;
2919 facptr[pix] = (unsigned short int)(scale*loi);
2920
2921 // Look for minimal and maximal factor.
2922 if(min>loi) min=loi;
2923 if(max<loi) max=loi;
2924 sqr_sum += loi*loi;
2925 sum += loi;
2926 pix++;
2927 }
2928 }
2929 }
2930 // Allocate memory in result pointer.
2931 if(pix){
2932 mat->_factdata[view*half + bin]=
2933 (unsigned short int**)calloc(pix,sizeof(unsigned short int*));
2934 if(!mat->_factdata[view*half + bin]) return -1;
2935 }
2936
2937 // Allocate leaves.
2938 for(col=0; col<pix; col++){
2939 mat->_factdata[view*half + bin][col]=
2940 (unsigned short int*)calloc(3,sizeof(unsigned short int));
2941 if(!mat->_factdata[view*half + bin][col]) return -1;
2942 }
2943
2944 // Put now values in coordinates and factors array to result pointer.
2945 mat->fact = mat->_factdata;
2946 for(col=0; col<pix; col++){
2947 mat->fact[view*half + bin][col][0] = coptr[col][0];
2948 mat->fact[view*half + bin][col][1] = coptr[col][1];
2949 mat->fact[view*half + bin][col][2] = facptr[col];
2950 }
2951
2952 // Update also lists mat->dime and mat->factor_sqr_sums
2953 mat->dime[view*half + bin]=pix;
2954
2955 mat->factor_sqr_sum[view*half + bin]=sqr_sum;
2956
2957 }// END of bin loop
2958
2959 }// End of view>0.
2960
2961 }// END OF VIEW LOOP
2962
2963 free(X);
2964 free(Y);
2965 free(coords);
2966 free(factors);
2967
2968 mat->min = min;
2969 mat->max = max;
2970 mat->factor_sum = sum;
2971 mat->status = PRMAT_STATUS_BS_OCCUPIED;
2972 return 0;
2973
2974} // END OF SETTING BASE LINES.
float ellipseGetMinor(ELLIPSE *ell)
Definition ellipse.c:265
float ellipseGetMajor(ELLIPSE *ell)
Definition ellipse.c:254
int ellipseIsInside(ELLIPSE *ell, int row, int col)
Definition ellipse.c:352

◆ radonSetBasesEA()

int radonSetBasesEA ( RADON * radtra,
ELLIPSE * elli,
PRMAT * mat )
extern

Same as 'radonSetBases()' but discretisation model in this function is 'exact area'.

Parameters
radtraspecial Radon transform operator.
ellifield of view.
matpointer to the datastructure where coordinates and values are to be stored.
Returns
0 if ok.

Definition at line 2984 of file radon.c.

2985{
2986 // temporary pointers for storing the coordinates and factors
2987 unsigned short int **coords, *factors, **coptr, *facptr;
2988 // pointers for the values of LOR in integer points
2989 float *Y, *X, *Xptr, *Yptr;
2990 double sinus, cosinus, tanus; // sin, cosine and tangent
2991 double shift_x, shift_y; // shift for LOR
2992 int xp, xn, yp, yn, z, xp2; //integer points
2993 int x_left, x_right, y_top, y_bottom; // limits for fast search
2994 int col, col1, col2, row, view, bin, pix, errors=0; //counters
2995 int binNr, viewNr, imgDim, mode, views, rows, half;
2996 float sdist;
2997 float a=0,b=0, c=0, d=0, g=0, h=0, A;
2998 // delta x and y and factors epsilon.
2999 float dx, dy , eps1 = 0, eps2 = 0, eps3 = 0;
3000 float min=0, max=0, sum=0, scale, sqr_sum=0;
3001
3002 // Check that the data for this radon transform is initialized.
3003 if(radtra->status != RADON_STATUS_INITIALIZED) return -1;
3004
3005 // Retrieve the data from given radon transform object.
3006 mode=radonGetMO(radtra); // Should be 2.
3007 imgDim=radonGetID(radtra);
3008 binNr=radonGetNB(radtra);
3009 viewNr=radonGetNV(radtra);
3010 sdist=radonGetSD(radtra);
3011 half=radonGetHI(radtra);
3012
3013 /*printf("radonSetBases(): m=%i, id=%i, b=%i, v=%i, sd=%f, h=%i.\n",
3014 mode,imgDim,binNr,viewNr,sdist,half);*/
3015
3016 // Set information in the projection matrix data stucture.
3017 if(binNr == 192){
3018 mat->type=PRMAT_TYPE_ECAT931;
3019 } else if(binNr == 281) {
3020 mat->type=PRMAT_TYPE_GE;
3021 } else
3022 mat->type=PRMAT_TYPE_NA;
3023
3024 mat->viewNr=viewNr;
3025 mat->binNr=binNr;
3026 mat->imgDim=imgDim;
3027
3028 mat->mode = mode;
3029 // Allocate memory in PRMAT struct and set fov.
3030 mat->prmatfov = (int*)calloc(2,sizeof(int));
3031 mat->prmatfov[0] = ellipseGetMajor(elli);
3032 mat->prmatfov[1] = ellipseGetMinor(elli);
3033
3034 // rows := number of lines in the base set = (views*half)
3035 views = viewNr/4 + 1;
3036 rows = views*half;
3037
3038 mat->factor_sqr_sum=calloc(rows,sizeof(float));
3039 mat->dimr=rows;
3040 //entries in one line
3041 mat->dime=calloc(rows,sizeof(int));
3042 mat->_factdata=(unsigned short int***)calloc(rows,sizeof(unsigned short int**));
3043 //if not enough memory
3044 if(!mat->_factdata || !mat->dime) return(4);
3045
3046 // Compute scaling factor, assuming that maximum value is 1.
3047 scale=65534./1;
3048 mat->scaling_factor=1.0/scale; //is the inverse of scale
3049
3050 /* Allocate (temporary) coordinate and factor arrays to maximum size
3051 (= 4*imgDim). Coords contains pairs (x,y), coordinates in cartesian
3052 coordinate system. */
3053 coords = (unsigned short int**)calloc(4*imgDim,sizeof(unsigned short int*));
3054 factors = (unsigned short int*)calloc(4*imgDim,sizeof(unsigned short int));
3055 if(!coords || !factors) return 5;
3056
3057 for(col=0; col<4*imgDim; col++){
3058 coords[col] = (unsigned short int*)calloc(2,sizeof(unsigned short int));
3059 if(!coords[col]) return -1;
3060 }
3061
3062 coptr = coords;
3063 facptr = factors;
3064
3065 // Array for storing values f_x.
3066 X=(float*)calloc(imgDim+1,sizeof(float));
3067 // Array for storing values f_y.
3068 Y=(float*)calloc(imgDim+1,sizeof(float));
3069 if(X==NULL || Y==NULL){
3070 return -2;
3071 }
3072 Xptr=X;
3073 Yptr=Y;
3074
3076 // Find pixel coordinates of the contributing pixels for tubes of response
3077 // belonging to first 1/4th of angles. From these pixel coordinates
3078 // others can be calculated via symmetries in projection space.
3079 // N.B. The line of response: a*x+b*y+c
3080 // => solve y: y=-x/tan(view) + s*(cos(theta)/tan(theta) + sin(theta))
3081 // solve x: x=-y*tan(theta) + s*(sin(theta)*tan(theta) + cos(theta))
3082 for(view=0; view<views; view++){
3083 // view=0 -> sin(theta)=0
3084 if(view==0){
3085
3086 // Choose column(s) according to sample distance for angles 0 and pi/2.
3087 col1 = 0;
3088 col2 = 0;
3089 for(bin = 0; bin < half; bin++){
3090
3091 pix = 0; // length of list pixels (and factors)
3092 sqr_sum = 0;
3093
3094 col1 = col2;
3095 col2 = floor((float)(bin + 1)*sdist);
3096
3097 // Determine factor epsilon.
3098 if(col1 == col2){
3099 eps1 = sdist;
3100 eps2 = 0;
3101 eps3 = 0;
3102 }
3103 if((col2-col1) == 1){
3104 eps1 = (float)(col2 - (bin)*sdist);
3105 eps2 = 0;
3106 eps3 = (float)((bin+1)*sdist - col2);
3107 }
3108 // If sdist > pixel size!
3109 if((col2-col1) > 1){
3110 eps1 = (float)(col1 + 1 - (bin)*sdist);
3111 eps2 = 1; // middle pixel.
3112 eps3 = (float)((bin+1)*sdist - col2);
3113 }
3114
3115 // Iterate through the entries in the image matrix.
3116 for(row=0; row<imgDim; row++){
3117
3118 /* Check that pixel and pixels hit by symmetrical lines lay inside
3119 the FOV. */
3120 if(ellipseIsInside(elli,row,col1) &&
3121 ellipseIsInside(elli,row,imgDim - 1 - col1) &&
3122 ellipseIsInside(elli,imgDim-1-col1,row) &&
3123 ellipseIsInside(elli,col1,row)) {
3124
3125 if(!eps3){
3126 coptr[pix][0] = (unsigned short int)col1;
3127 coptr[pix][1] = (unsigned short int)row;
3128 // Convert eps to unsigned short int.
3129 facptr[pix] = (unsigned short int)(scale*eps1);
3130 // Look for minimal and maximal factor.
3131 if(min>eps1) min=eps1;
3132 if(max<eps1) max=eps1;
3133 // Compute square sums in every row.
3134 sqr_sum += eps1*eps1;
3135 sum += eps1;
3136 pix++;
3137 }
3138
3139 if(eps3 && !eps2){
3140 coptr[pix][0] = (unsigned short int)col1;
3141 coptr[pix][1] = (unsigned short int)row;
3142 // Convert eps to unsigned short int.
3143 facptr[pix] = (unsigned short int)(scale*eps1);
3144 // Look for minimal and maximal factor.
3145 if(min>eps1) min=eps1;
3146 if(max<eps1) max=eps1;
3147 // Compute square sums in every row.
3148 sqr_sum += eps1*eps1;
3149 sum += eps1;
3150 pix++;
3151
3152 coptr[pix][0] = (unsigned short int)col2;
3153 coptr[pix][1] = (unsigned short int)row;
3154 // Convert eps to unsigned short int.
3155 facptr[pix] = (unsigned short int)(scale*eps3);
3156 // Look for minimal and maximal factor.
3157 if(min>eps3) min=eps3;
3158 if(max<eps3) max=eps3;
3159 // Compute square sums in every row.
3160 sqr_sum += eps3*eps3;
3161 sum += eps3;
3162 pix++;
3163 }
3164
3165 if(eps3 && eps2){
3166 for(col = col1; col<=col2; col++){
3167
3168 if(col == col1){
3169 coptr[pix][0] = (unsigned short int)col1;
3170 coptr[pix][1] = (unsigned short int)row;
3171 // Convert eps to unsigned short int.
3172 facptr[pix] = (unsigned short int)(scale*eps1);
3173 // Look for minimal and maximal factor.
3174 if(min>eps1) min=eps1;
3175 if(max<eps1) max=eps1;
3176 // Compute square sums in every row.
3177 sqr_sum += eps1*eps1;
3178 sum += eps1;
3179 pix++;
3180 }
3181
3182 if(col == col2){
3183 coptr[pix][0] = (unsigned short int)col2;
3184 coptr[pix][1] = (unsigned short int)row;
3185 // Convert eps to unsigned short int.
3186 facptr[pix] = (unsigned short int)(scale*eps3);
3187 // Look for minimal and maximal factor.
3188 if(min>eps3) min=eps3;
3189 if(max<eps3) max=eps3;
3190 // Compute square sums in every row.
3191 sqr_sum += eps3*eps3;
3192 sum += eps3;
3193 pix++;
3194 }
3195
3196 if(col != col1 && col != col2){
3197 coptr[pix][0] = (unsigned short int)col;
3198 coptr[pix][1] = (unsigned short int)row;
3199 // Convert eps to unsigned short int.
3200 facptr[pix] = (unsigned short int)(scale*eps2);
3201 // Look for minimal and maximal factor.
3202 if(min>eps2) min=eps2;
3203 if(max<eps2) max=eps2;
3204 // Compute square sums in every row.
3205 sqr_sum += eps2*eps2;
3206 sum += eps2;
3207 pix++;
3208 }
3209 }
3210 }
3211 }// Pixel is inside the fov
3212 }// END OF ROW-LOOP
3213
3214 /* Allocate memory in factor pointer (dynamically according to number
3215 of pixels intersected). */
3216 if(pix){
3217 mat->_factdata[bin]= // 0 angle
3218 (unsigned short int**)calloc(pix,sizeof(unsigned short int*));
3219 if(!mat->_factdata[bin]) return -1;
3220 }
3221 // Allocate leaves.
3222 for(col=0; col<pix; col++){
3223 mat->_factdata[bin][col]=
3224 (unsigned short int*)calloc(3,sizeof(unsigned short int));
3225 if(!mat->_factdata[bin][col]) return -1;
3226 }
3227
3228 // Put now values in coordinates and factors array to result pointer.
3229 mat->fact = mat->_factdata;
3230 for(col=0; col<pix; col++){
3231 mat->fact[bin][col][0] = coptr[col][0]; // x-coodinate
3232 mat->fact[bin][col][1] = coptr[col][1]; // y-coordinate
3233 mat->fact[bin][col][2] = facptr[col]; // factor
3234 }
3235
3236 //Set also the number of pixels belonging to each row and square sums.
3237 mat->dime[bin]=pix;
3238 mat->factor_sqr_sum[bin]=sqr_sum;
3239
3240 } // END OF BIN-LOOP FOR ANGLE 0
3241 // End of view==0 (handles angles 0,pi/4,pi/2,3pi/4).
3242 } else { // Angles in (0,pi)
3243
3244 // Set sine and cosine for this angle.
3245 sinus = (double)radonGetSin(radtra,view);
3246 cosinus = (double)radonGetSin(radtra,viewNr/2 + view);
3247 tanus = sinus/cosinus;
3248
3249 // Set shift from origin for the first line of response (-n/2,theta).
3250 // NOTE that image matrix is on cartesian coordinate system where origin
3251 // is in the middle and shift is in pixels.
3252 shift_y = -(imgDim/2)/sinus;
3253 shift_x = -(imgDim/2)/cosinus;
3254
3255 // Evaluate the function of the first LOR in integer points [-n/2,n/2].
3256 // NOTE that image matrix is on cartesian coordinate system where origin
3257 // is in the middle.
3258 z=-imgDim/2;
3259 for(col=0; col<imgDim+1; col++){
3260 Yptr[col]=(float)(-z/tanus + shift_y);
3261 Xptr[col]=(float)(-z*tanus + shift_x);
3262 z++;
3263 }
3264
3265 // Set shift from the first LOR.
3266 shift_y = (double)(sdist/sinus);
3267 shift_x = (double)(sdist/cosinus);
3268
3269 // Iterate through half the bins in this view,
3270 // and determine coordinates of pixels contributing to this LOR.
3271 // NOTE that shift is added according to 'bin' in every loop.
3272 // Calculate also the length of intersection.
3273 // Others are determined via symmetry in projection space.
3274
3275 for(bin=0; bin<half; bin++){
3276
3277 pix = 0;
3278 sqr_sum = 0;
3279
3280 // Limit (x-)indices for fast search.
3281 // Note that indices are non-negative integers.
3282
3283 x_left = floor((float)(Xptr[imgDim] + bin*shift_x + imgDim/2));
3284 if(x_left < 0) x_left = 0;
3285
3286 x_right = floor((float)(Xptr[0] + bin*shift_x + imgDim/2));
3287 if(x_right <= 0) x_right = 1;
3288 if(x_right > imgDim) x_right = imgDim - 1;
3289
3290 /* Iterate through the values in vector Y, in integer points
3291 [x_left,x_rigth]. */
3292 for(z=x_left; z <= x_right; z++) {
3293
3294 xp = z; //positive x-coordinate
3295 xn = imgDim - 1 - xp; //negative x-coordinate
3296
3297 // Look y from left.
3298 yp = imgDim/2 - floor(Yptr[xp + 1] + bin*shift_y) - 1;
3299 yn = imgDim - 1 - yp;
3300
3301 // If the y-value for this x (z) is inside the image grid.
3302 if(yp < imgDim && yp >= 0 && yn < imgDim && yn >= 0 && xp >= 0 &&
3303 xp < imgDim && xn < imgDim && xn >= 0) {
3304
3305 /* Check that pixel and pixels hit by symmetrical lines lay inside
3306 the FOV. */
3307 if(ellipseIsInside(elli,yp,xp) && ellipseIsInside(elli,yn,xn) &&
3308 ellipseIsInside(elli,yp,xn) && ellipseIsInside(elli,yn,xp) &&
3309 ellipseIsInside(elli,xn,yn) && ellipseIsInside(elli,xp,yp) &&
3310 ellipseIsInside(elli,xn,yp) && ellipseIsInside(elli,xp,yn)){
3311
3312 /* NOTE that pixels found in this part are always hit from right
3313 side. */
3314 // Compute a := |AF| and b := |FB|.
3315 a = (float)(xp + 1 - (imgDim/2 + Xptr[imgDim - yp] + bin*shift_x));
3316 b = (float)(floor(Yptr[xp + 1] + bin*shift_y) + 1 -
3317 (Yptr[xp + 1] + bin*shift_y));
3318
3319 // Calculate the area of lower triangle.
3320 A = a*b/2;
3321
3322 // c := |FC|
3323 c = (float)(xp + 1 - (imgDim/2 + Xptr[imgDim - yp] +
3324 (bin+1)*shift_x));
3325
3326 if(c > 0) {
3327
3328 // d := |FD|
3329 d = (float)(floor(Yptr[xp + 1] + (bin+1)*shift_y) + 1 -
3330 (Yptr[xp + 1] + (bin+1)*shift_y));
3331
3332 // Subtract the area of upper triangle.
3333 A = A - c*d/2;
3334 }
3335
3336 eps1 = A;
3337
3338 if(eps1 < 0 || eps1 > 1) errors++;
3339
3340 // Put coordinates and factors in the list.
3341 coptr[pix][0] = xp;
3342 coptr[pix][1] = yp;
3343 facptr[pix] = (unsigned short int)(scale*eps1);
3344
3345 // Look for minimal and maximal factor.
3346 if(min>eps1) min=eps1;
3347 if(max<eps1) max=eps1;
3348 sqr_sum += eps1*eps1;
3349 sum += eps1;
3350 pix++;
3351 }// Is inside the FOV.
3352 }
3353 }
3354
3355 // Limit (y-)indices for fast search.
3356 // Note that indices are non-negative integers.
3357 y_bottom = floor((float)(Yptr[imgDim] + bin*shift_y + imgDim/2));
3358 if(y_bottom < 0) y_bottom = 0;
3359 if(y_bottom > imgDim) y_bottom = 0;
3360
3361 y_top = floor((float)(Yptr[0] + bin*shift_y + imgDim/2));
3362 if(y_top > imgDim) y_top = imgDim;
3363 if(y_top <= 0) y_top = 1;
3364
3365 /* Iterate through the values in vector X, in integer points
3366 [y_bottom,y_top]. */
3367 for(z=y_top; z >= y_bottom; z--) {
3368
3369 // Look y from this location.
3370 xp = floor(Xptr[z] + bin*shift_x) + imgDim/2;
3371 xn = imgDim - 1 - xp;
3372
3373 yp = imgDim - z - 1;
3374 yn = imgDim - yp - 1;
3375
3376 // If the x-value for this y (z) is inside the image grid.
3377 if(yp < imgDim && yp >= 0 && yn < imgDim && yn >= 0 && xp >= 0 &&
3378 xp < imgDim && xn < imgDim && xn >= 0) {
3379
3380 /* Check that pixel and pixels hit by symmetrical lines lay inside
3381 the FOV. */
3382 if(ellipseIsInside(elli,yp,xp) && ellipseIsInside(elli,yn,xn) &&
3383 ellipseIsInside(elli,yp,xn) && ellipseIsInside(elli,yn,xp) &&
3384 ellipseIsInside(elli,xn,yn) && ellipseIsInside(elli,xp,yp) &&
3385 ellipseIsInside(elli,xn,yp) && ellipseIsInside(elli,xp,yn)){
3386
3387 eps1=eps2=eps3=0;
3388
3389 dx = (float)(Xptr[z] + bin*shift_x + imgDim/2 - xp);
3390 dy = (float)(Yptr[xp] + bin*shift_y - z + imgDim/2);
3391
3392 if(dy < 1){ // Cases 3,4,5 and 6.
3393
3394 // 1. PART
3395 // a := |HA|
3396 a = dy;
3397
3398 // b := |HB| (b < 1 for angles in [0,pi/4))
3399 b = dx;
3400
3401 // h := height of rectangle R.
3402 h = a + shift_y;
3403
3404 if(h > 1){ // Cases 3,4 and 5.
3405 h = 1;
3406 g = b + shift_x;
3407 if(g > 1){ // Cases 3 and 4.
3408 g = 1;
3409 xp2 =floor(Xptr[z+1] + (bin+1)*shift_x) + imgDim/2;
3410
3411 if(xp == xp2){ // Case 4.
3412 // c := |FC|
3413 c = (float)(xp + 1 - (imgDim/2 + Xptr[z+1] +
3414 (bin+1)*shift_x));
3415 // d := |FD|
3416 d = (float)(floor(Yptr[xp + 1] + (bin+1)*shift_y) + 1 -
3417 (Yptr[xp + 1] + (bin+1)*shift_y));
3418 eps1 = 1 - (a*b + c*d)/2;
3419 eps2 = 0;
3420 // Lower triangle on the next pixel (x+1,y).
3421 eps3 = (1 - d)*(b + shift_x - 1)/2;
3422 } else { // Case 3.
3423 // c=d=0.
3424 eps1 = 1 - a*b/2;
3425 // Calculate area on pixel in place (xp+1,yp-1).
3426 dy = (float)(Yptr[xp+1] + (bin+1)*shift_y - (z + 1) +
3427 imgDim/2);
3428 if(dy < 1){ // Case 11.
3429 // c := |HC|
3430 c = dy;
3431 // d := |HD|
3432 d = (float)(xp + 2 - (imgDim/2 + Xptr[z+1] +
3433 (bin+1)*shift_x));
3434 eps2 = c*d/2;
3435 } else{ // Cases 9 and 10.
3436 dx = (float)(xp + 2 - (imgDim/2 + Xptr[z+1] +
3437 (bin+1)*shift_x));
3438 if(dx < 1) { // Case 10.
3439 // g := length of rectangle Q.
3440 g = dx;
3441 // c := |CD| (on x-axis).
3442 c = dx - (float)(xp + 2 - (imgDim/2 + Xptr[z+2] +
3443 (bin+1)*shift_x));
3444 // Rectangle Q - triangle c*h (h = 1).
3445 eps2 = g - c/2;
3446 } else { // Case 9.
3447 // c := |FC|
3448 c = (float)(xp + 2 - (imgDim/2 + Xptr[z+2] +
3449 (bin+1)*shift_x));
3450 // d := |FD|
3451 d = (float)(floor(Yptr[xp + 2] + (bin+1)*shift_y) +
3452 2 - (Yptr[xp + 2] + (bin+1)*shift_y));
3453 // Rectangle Q - triangle CFD.
3454 eps2 = 1 - c*d/2;
3455 }
3456 }
3457
3458 // Calculate area on pixel in place (xp+1,yp).
3459 dx = (float)(xp + 2 - (imgDim/2 + Xptr[z] +
3460 (bin+1)*shift_x));
3461 if(dx < 1) { // Case 10.
3462 // g := length of rectangle Q.
3463 g = dx;
3464 // c := |CD| (on x-axis).
3465 c = dx - (float)(xp + 2 - (imgDim/2 + Xptr[z+1] +
3466 (bin+1)*shift_x));
3467 // Rectangle Q - triangle c*h (h = 1).
3468 eps3 = g - c/2;
3469 } else { // Case 9.
3470 // c := |FC|
3471 c = (float)(xp + 2 - (imgDim/2 + Xptr[z+1] +
3472 (bin+1)*shift_x));
3473 // d := |FD|
3474 d = (float)(floor(Yptr[xp + 2] + (bin+1)*shift_y) +
3475 1 - (Yptr[xp + 2] + (bin+1)*shift_y));
3476 // Rectangle Q - triangle CFD.
3477 eps3 = 1 - c*d/2;
3478 }
3479 }
3480 } else { // Case 5. (g < 1)
3481 // c := |DC|.
3482 c = g - (imgDim/2 + Xptr[z+1] + (bin+1)*shift_x - xp);
3483 // d := heigth
3484 d = 1;
3485
3486 eps1 = g*h - (a*b + c*d)/2;
3487 eps2 = 0;
3488 eps3 = 0;
3489 }
3490 } else { // Case 6 (h <= 1).
3491 // g := legth of rectangle R
3492 g = b + shift_x;
3493 if(g > 1) // Should always be < 1 for angles in [0,pi/4)
3494 g = 1;
3495
3496 eps1 = (g*h - a*b)/2;
3497 eps2 = 0;
3498 eps3 = 0;
3499 }
3500 } else { // 2. PART. Cases 2,7 and 8. (dy >= 1).
3501
3502 // a := |HA|
3503 a = 1;
3504
3505 // b := |HB| (>=1)
3506 b = dx - (float)(Xptr[z+1] + bin*shift_x + imgDim/2 - xp);
3507
3508 // h := heigth of rectangle R
3509 h = 1;
3510
3511 // g := length of rectangle R
3512 g = dx + shift_x;
3513
3514 if(g > 1){ // Cases 2 and 8.
3515 g = 1 - (float)(Xptr[z+1] + bin*shift_x + imgDim/2 - xp);
3516 xp2 = floor(Xptr[z+1] + (bin+1)*shift_x) + imgDim/2;
3517 if(xp == xp2){ // Case 8.
3518 // c := |FC|
3519 c = (float)(xp + 1 - (imgDim/2 + Xptr[z+1] +
3520 (bin+1)*shift_x));
3521 // d := |FD|
3522 d = (float)(floor(Yptr[xp + 1] + (bin+1)*shift_y) + 1 -
3523 (Yptr[xp + 1] + (bin+1)*shift_y));
3524 eps1 = g*h - (a*b + c*d)/2;
3525 eps2 = 0;
3526 // Lower triangle on the next pixel (x+1,y).
3527 eps3 = (1 - d)*((Xptr[z] + (bin+1)*shift_x + imgDim/2)
3528 - (xp+1))/2;
3529 } else { // Case 2.
3530 // c=d=0.
3531 eps1 = g*h - a*b/2;
3532 /* Pixel in place (xp+1,yp-1) should have been found in
3533 the previous step. */
3534 eps2 = 0;
3535
3536 // Calculate area on pixel in place (xp+1,yp).
3537 dx = (float)((imgDim/2 + Xptr[z] + (bin+1)*shift_x) - (xp+1));
3538 if(dx < 1){ // Case 10 (trapezium).
3539 // g := bottom of trapezium Q.
3540 g = dx;
3541 // c := top of trapezium Q.
3542 c = (float)((imgDim/2 + Xptr[z+1] + (bin+1)*shift_x) -
3543 (xp+1));
3544 // Area of trapezium Q. Heigth = 1.
3545 eps3 = (g + c)/2;
3546 } else { // Case 9.
3547 // c := |FC|
3548 c = (float)(xp + 2 - (imgDim/2 + Xptr[z+1] +
3549 (bin+1)*shift_x));
3550 // d := |FD|
3551 d = (float)(floor(Yptr[xp + 2] + (bin+1)*shift_y) + 1 -
3552 (Yptr[xp + 2] + (bin+1)*shift_y));
3553 // Rectangle Q - triangle CFD.
3554 eps3 = 1 - c*d/2;
3555 }
3556 }
3557 } else { // Case 7. (g < = 1)
3558 // Area of the parallelogram R.
3559 eps1 = sdist/cosinus;
3560 eps2 = 0;
3561 eps3 = 0;
3562 }
3563 }
3564 if(eps1 <= 0 || eps1 > 1) {
3565 errors++;
3566 printf("Error: eps1 = %f \n",eps1);
3567 eps1 = fabs(eps1);
3568 }
3569 if(eps2 < 0 || eps2 > 1){
3570 errors++;
3571 eps2 = fabs(eps2);
3572 }
3573 if(eps3 < 0 || eps3 > 1){
3574 errors++;
3575 eps1 = fabs(eps3);
3576 }
3577 if(!eps2 && !eps3){ // Cases 5,6 and 7.
3578 // Put coordinates and factors in the list.
3579 coptr[pix][0] = xp;
3580 coptr[pix][1] = yp;
3581 facptr[pix] = (unsigned short int)(scale*eps1);
3582 pix++;
3583 // Look for minimal and maximal factor.
3584 if(min>eps1) min=eps1;
3585 if(max<eps1) max=eps1;
3586 sqr_sum += eps1*eps1;
3587 sum += eps1;
3588 } else{
3589 if(!eps2){ // <=> eps3 != 0 & eps2 = 0 <=> Cases 3,4 and 8.
3590 if(xp + 1 < imgDim && xn - 1 >= 0){
3591 // Put coordinates and factors in the list.
3592 coptr[pix][0] = xp;
3593 coptr[pix][1] = yp;
3594 facptr[pix] = (unsigned short int)(scale*eps1);
3595
3596 // Look for minimal and maximal factor.
3597 if(min>eps1) min=eps1;
3598 if(max<eps1) max=eps1;
3599 sqr_sum += eps1*eps1;
3600 sum += eps1;
3601 pix++;
3602
3603 // Put coordinates and factors in the list.
3604 coptr[pix][0] = xp+1;
3605 coptr[pix][1] = yp;
3606 facptr[pix] = (unsigned short int)(scale*eps3);
3607
3608 // Look for minimal and maximal factor.
3609 if(min>eps3) min=eps3;
3610 if(max<eps3) max=eps3;
3611 sqr_sum += eps3*eps3;
3612 sum += eps3;
3613 pix++;
3614 }
3615 } else{ // <=> eps2!=0 && eps3!=0 <=> Case 3.
3616 if(xp+1 < imgDim && xn-1 >= 0 && yp-1 >= 0 && yn+1 < imgDim) {
3617 // Put coordinates and factors in the list.
3618 coptr[pix][0] = xp;
3619 coptr[pix][1] = yp;
3620 facptr[pix] = (unsigned short int)(scale*eps1);
3621
3622 // Look for minimal and maximal factor.
3623 if(min>eps1) min=eps1;
3624 if(max<eps1) max=eps1;
3625 sqr_sum += eps1*eps1;
3626 sum += eps1;
3627 pix++;
3628
3629 // Put coordinates and factors in the list.
3630 coptr[pix][0] = xp+1;
3631 coptr[pix][1] = yp;
3632 facptr[pix] = (unsigned short int)(scale*eps3);
3633
3634 // Look for minimal and maximal factor.
3635 if(min>eps3) min=eps3;
3636 if(max<eps3) max=eps3;
3637 sqr_sum += eps3*eps3;
3638 sum += eps3;
3639 pix++;
3640
3641 // Put coordinates and factors in the list.
3642 coptr[pix][0] = xp+1;
3643 coptr[pix][1] = yp-1;
3644 facptr[pix] = (unsigned short int)(scale*eps2);
3645
3646 // Look for minimal and maximal factor.
3647 if(min>eps2) min=eps2;
3648 if(max<eps2) max=eps2;
3649 sqr_sum += eps2*eps2;
3650 sum += eps2;
3651 pix++;
3652 }
3653 }
3654 }
3655
3656 }// Pixel is inside the FOV.
3657 }
3658 }
3659 /* Allocate memory in factor pointer (dynamically according to number
3660 of pixels intersected). */
3661 if(pix){
3662 mat->_factdata[half*view + bin]=
3663 (unsigned short int**)calloc(pix,sizeof(unsigned short int*));
3664 if(!mat->_factdata[half*view + bin]) return -1;
3665 }
3666
3667 // Allocate leaves.
3668 for(col=0; col<pix; col++){
3669 mat->_factdata[half*view + bin][col]=
3670 (unsigned short int*)calloc(3,sizeof(unsigned short int));
3671 if(!mat->_factdata[half*view + bin][col]) return -1;
3672 }
3673
3674 // Put now values in coordinates and factors array to result pointer.
3675 mat->fact = mat->_factdata;
3676 for(col=0; col<pix; col++){
3677 mat->fact[half*view + bin][col][0] = coptr[col][0]; // x-coodinate
3678 mat->fact[half*view + bin][col][1] = coptr[col][1]; // y-coordinate
3679 mat->fact[half*view + bin][col][2] = facptr[col]; // factor
3680 }
3681
3682 //Set also the number of pixels belonging to each row and square sums.
3683 mat->dime[half*view + bin]=pix;
3684 mat->factor_sqr_sum[half*view + bin]=sqr_sum;
3685
3686 }// END OF BIN-LOOP
3687
3688 }// End of view>0.
3689
3690 }// END OF VIEW LOOP
3691
3692 free(X);
3693 free(Y);
3694 free(coords);
3695 free(factors);
3696
3697 mat->min = min;
3698 mat->max = max;
3699 mat->factor_sum = sum;
3700 mat->status = PRMAT_STATUS_BS_OCCUPIED;
3701 return 0;
3702
3703}// END OF SETTING BASE LINES (EXACT AREA).

◆ radonSetLORS()

int radonSetLORS ( RADON * radtra,
ELLIPSE * elli,
PRMAT * mat )
extern

Sets the coordinates and factors for intersected pixels according to given special Radon transform operator for EVERY line of response.

Precondition
radtra is a radon transform operator && elli defines a field of view && mat is initialized.
Postcondition
coordinates and factors for pixels contributing to all lines of response are set.
Parameters
radtraspecial Radon transform operator.
ellifield of view.
matpointer to the datastructure where coordinates and values are stored for the base lines.
Returns
0 if ok.

Definition at line 3925 of file radon.c.

3926{
3927 unsigned int *coords, *iptr;
3928 unsigned int imgDim=128, binNr=256, viewNr=192, view, bin, pixNr=0;
3929 unsigned int row, col, rows, half, centerbin, p;
3930 int ret=0;
3931 int xp, xn, yp, yn;
3932 float fact, sqr_sum;
3933 PRMAT ext_mat; // temporary extented projection matrix
3934
3935 if(elli) {} // to prevent compiler warning about not being used.
3936
3937 printf("radonSetLors() started. \n");
3938
3939 //Retrieve data from given radon transform object
3940 imgDim=radonGetID(radtra);
3941 binNr=radonGetNB(radtra);
3942 viewNr=radonGetNV(radtra);
3943
3944 // Calculate and set center bin for the current geometrics.
3945 if((binNr%2) != 0){
3946 half = (binNr - 1)/2 + 1;
3947 centerbin = half - 1;
3948 }
3949 else{
3950 half = binNr/2;
3951 // In the case binNr is even there is no center bin.
3952 centerbin = -1;
3953 }
3954
3955 // Initiate extented projection matrix.
3956 prmatInit(&ext_mat);
3957
3958 // Prepare to allocate extented projection matrix.
3959 rows = viewNr*binNr;
3960 coords = (unsigned int*)calloc(rows,sizeof(int));
3961 iptr = coords;
3962 // Determine the number of hit pixels for EVERY row.
3963 p = viewNr/4;
3964 // Extend the projection matrix according to given base set.
3965 for(view=0; view<p + 1; view++){
3966 for(bin=0; bin<half; bin++){
3967 row = view*half + bin;
3968 pixNr = prmatGetPixels(mat,row);
3969 // Line in the base set.
3970 iptr[view*binNr + bin] = pixNr;
3971 // Symmetrical lines.
3972 if(bin != centerbin)
3973 iptr[view*binNr + binNr - 1 - bin] = pixNr;
3974
3975 if(view != 0 && view != viewNr/4){
3976 // Mirror the original LOR on y-axis, i.e. x->-x
3977 // Case: pi-theta.
3978 iptr[(viewNr - view)*binNr + bin] = pixNr;
3979 if(bin != centerbin)
3980 iptr[(viewNr-view)*binNr + binNr - 1 - bin] = pixNr;
3981
3982 // Mirror the LOR on line x=y, i.e. x->y.
3983 // Case: pi/2-theta
3984 iptr[(viewNr/2 - view)*binNr + bin] = pixNr;
3985 if(bin != centerbin)
3986 iptr[(viewNr/2 - view)*binNr + binNr - 1 - bin] = pixNr;
3987 }
3988
3989 // Mirror the LOR on line x=y, and on y-axis i.e x->y and y->-y.
3990 // Case: pi/2+theta
3991 iptr[(viewNr/2 + view)*binNr + bin] = pixNr;
3992 if(bin != centerbin)
3993 iptr[(viewNr/2 + view)*binNr + binNr - 1 - bin] = pixNr;
3994
3995 }
3996 }
3997
3998 // Allocate the extented projection matrix.
3999 ret = prmatAllocate(&ext_mat,1,rows,coords);
4000 if(ret){
4001 free(coords);
4002 return(ret);
4003 }
4004 printf("Allocation done \n");
4005
4006 // Extend the projection matrix according to given base set.
4007 for(view=0; view<p + 1; view++){
4008 for(bin=0; bin<half; bin++){
4009 row = view*half + bin;
4010 for(col=0; col<prmatGetPixels(mat,row); col++){
4011
4012 sqr_sum = prmatGetFactorSqrSum(mat,row);
4013 // Notice that we want the factor in unsigned short int.
4014 fact = mat->fact[row][col][2];
4015 xp = prmatGetXCoord(mat,row,col);
4016 xn = imgDim - 1 - xp;
4017 yp = prmatGetYCoord(mat,row,col);
4018 yn = imgDim - 1 - yp;
4019
4020 // Line in the base set.
4021 ext_mat.fact[view*binNr + bin][col][0] = xp;
4022 ext_mat.fact[view*binNr + bin][col][1] = yp;
4023 ext_mat.fact[view*binNr + bin][col][2] = fact;
4024 ext_mat.factor_sqr_sum[view*binNr + bin] = sqr_sum;
4025
4026 // Then symmetrical lines.
4027 if(bin != centerbin){
4028 ext_mat.fact[view*binNr + binNr - 1 - bin][col][0] = xn;
4029 ext_mat.fact[view*binNr + binNr - 1 - bin][col][1] = yn;
4030 ext_mat.fact[view*binNr + binNr - 1 - bin][col][2] = fact;
4031 ext_mat.factor_sqr_sum[view*binNr + binNr - 1 - bin] = sqr_sum;
4032 }
4033
4034 if(view != 0 && view != viewNr/4){
4035 // Mirror the original LOR on y-axis, i.e. x->-x
4036 // Case: pi-theta.
4037 ext_mat.fact[(viewNr - view)*binNr + bin][col][0] = xn;
4038 ext_mat.fact[(viewNr - view)*binNr + bin][col][1] = yp;
4039 ext_mat.fact[(viewNr - view)*binNr + bin][col][2] = fact;
4040 ext_mat.factor_sqr_sum[(viewNr - view)*binNr + bin] = sqr_sum;
4041
4042 if(bin != centerbin){
4043
4044 ext_mat.fact[(viewNr - view)*binNr +binNr - 1 - bin][col][0] = xp;
4045 ext_mat.fact[(viewNr - view)*binNr +binNr - 1 - bin][col][1] = yn;
4046 ext_mat.fact[(viewNr - view)*binNr +binNr - 1 - bin][col][2] = fact;
4047 ext_mat.factor_sqr_sum[(viewNr - view)*binNr +binNr - 1 - bin] =
4048 sqr_sum;
4049 }
4050
4051 // Mirror the LOR on line x=y, i.e. x->y.
4052 // Case: pi/2-theta
4053 ext_mat.fact[(viewNr/2 - view)*binNr + bin][col][0] = yn;
4054 ext_mat.fact[(viewNr/2 - view)*binNr + bin][col][1] = xn;
4055 ext_mat.fact[(viewNr/2 - view)*binNr + bin][col][2] = fact;
4056 ext_mat.factor_sqr_sum[(viewNr/2 - view)*binNr + bin] = sqr_sum;
4057
4058 if(bin != centerbin){
4059 ext_mat.fact[(viewNr/2 - view)*binNr +binNr-1-bin][col][0] = yp;
4060 ext_mat.fact[(viewNr/2 - view)*binNr +binNr-1-bin][col][1] = xp;
4061 ext_mat.fact[(viewNr/2 - view)*binNr +binNr-1-bin][col][2] = fact;
4062 ext_mat.factor_sqr_sum[(viewNr/2-view)*binNr+binNr-1-bin] = sqr_sum;
4063 }
4064 }
4065
4066 // Mirror the LOR on line x=y, and on y-axis i.e x->y and y->-y.
4067 // Case: pi/2+theta
4068 ext_mat.fact[(viewNr/2 + view)*binNr + bin][col][0] = yp;
4069 ext_mat.fact[(viewNr/2 + view)*binNr + bin][col][1] = xn;
4070 ext_mat.fact[(viewNr/2 + view)*binNr + bin][col][2] = fact;
4071 ext_mat.factor_sqr_sum[(viewNr/2 + view)*binNr + bin] = sqr_sum;
4072
4073 // Add img(y,-x)*k to the raysum of LOR (viewNr/2+view,binNr-bin)
4074 if(bin != centerbin){
4075 ext_mat.fact[(viewNr/2 + view)*binNr + binNr-1-bin][col][0] = yn;
4076 ext_mat.fact[(viewNr/2 + view)*binNr + binNr-1-bin][col][1] = xp;
4077 ext_mat.fact[(viewNr/2 + view)*binNr + binNr-1-bin][col][2] = fact;
4078 ext_mat.factor_sqr_sum[(viewNr/2 +view)*binNr +binNr-1-bin] = sqr_sum;
4079 }
4080 }
4081 }
4082 }
4083
4084
4085 // Empty old data from the given projection matrix.
4086 free((float*)mat->factor_sqr_sum);
4087
4088 for(row=0; row<mat->dimr; row++){ //every row
4089 for(col=0; col<mat->dime[row]; col++){ //every factor
4090 free((unsigned short int*)mat->_factdata[row][col]);
4091 }
4092 }
4093
4094 free((int*)mat->dime);
4095
4096 if(mat->dimr>0) free(mat->_factdata);
4097 mat->dimr=0;
4098
4099 // Allocate memory in mat structure for new extented matrix.
4100 ret = prmatAllocate(mat, 1, rows, coords);
4101 if(ret){
4102 free(coords);
4103 prmatEmpty(&ext_mat);
4104 return(ret);
4105 }
4106 printf("Allocation done \n");
4107
4108 // Copy the matrix from the temporary projection matrix.
4109 for(row=0; row<prmatGetRows(&ext_mat); row++){
4110 // Square sums.
4111 mat->factor_sqr_sum[row] = prmatGetFactorSqrSum(&ext_mat,row);
4112 for(col=0; col<prmatGetPixels(&ext_mat,row); col++){
4113 // Coordinates and factors.
4114 mat->fact[row][col][0] = prmatGetXCoord(&ext_mat,row,col);
4115 mat->fact[row][col][1] = prmatGetYCoord(&ext_mat,row,col);
4116 mat->fact[row][col][2] = ext_mat.fact[row][col][2];
4117 }
4118 }
4119
4120 // Release the temporary projection matrix.
4121 prmatEmpty(&ext_mat);
4122 free(coords);
4123
4124 return 0;
4125
4126
4127}//END OF radonSetLORS
unsigned int prmatGetRows(PRMAT *mat)
Definition prmat.c:267
void prmatEmpty(PRMAT *mat)
Definition prmat.c:56
void prmatInit(PRMAT *mat)
Definition prmat.c:22
float prmatGetFactorSqrSum(PRMAT *mat, int row)
Definition prmat.c:409
int prmatAllocate(PRMAT *mat, int set, unsigned int rows, unsigned int *coords)
Definition prmat.c:105

◆ radonSetLUT()

int radonSetLUT ( RADON * radtra,
ELLIPSE * elli,
PRMAT * mat )
extern

Sets a look-up table containing coordinates of lines of response intersecting pixels inside a field of view. Lines of response contributing to a pixel are searched from already set projection matrix.

Precondition
radtra is a radon transform operator && elli defines a field of view && projections are set in structure mat.
Postcondition
coordinates of lines response intersecting a pixel are set in a table.
Parameters
radtraspecial Radon transform operator.
ellifield of view.
matpointer to the datastructure where coordinates and values are to be stored.
Returns
0 if ok.

Definition at line 3719 of file radon.c.

3720{
3721 unsigned int **tmpData, **tmpptr; // coordinates of lines response.
3722 unsigned int *coords, *iptr;
3723 unsigned int col, row, pix=0, p=0, lors=0, view, bin; //counters
3724 unsigned int binNr, viewNr, imgDim, views, half, center;
3725 int ret=0;
3726 int xp, xn, yp, yn;
3727 float diam, sampledist;
3728
3729 //Check that projections are set.
3730 if(mat->status < PRMAT_STATUS_BS_OCCUPIED) return -1;
3731
3732 //Retrieve data from given radon transform object
3733 imgDim=radonGetID(radtra);
3734 binNr=radonGetNB(radtra);
3735 viewNr=radonGetNV(radtra);
3736 sampledist=radonGetSD(radtra);
3737 half=radonGetHI(radtra);
3738 center=radonGetCB(radtra);
3739 diam=sqrt(2);
3740
3741 /* Allocate memory for temporary list where we store coordinates of lines of
3742 response. Maximum number of lines (in one angle) hitting a pixel is
3743 [diameter of a pixel]/[sample distance]. */
3744 lors = ceil(diam/sampledist) + 1;
3745 tmpData = (unsigned int**)calloc(imgDim*imgDim,sizeof(unsigned int*));
3746 for(p=0; p<imgDim*imgDim; p++){
3747 tmpData[p]=(unsigned int*)calloc(lors*viewNr,sizeof(unsigned int));
3748 if(!tmpData[p]){
3749 fprintf(stderr, "Error: not enough memory.\n");
3750 return(4);
3751 }
3752 }
3753 tmpptr = tmpData;
3754
3755 /* Initialize the first entry in the list, to keep the number of entries
3756 in each row. And then fill the list from second entry. */
3757 for(p=0; p<imgDim*imgDim; p++) tmpptr[p][0]=0;
3758 views = viewNr/4;
3759 // Analyse the given projection matrix.
3760 for(view=0; view<views + 1; view++){
3761 for(bin=0; bin<half; bin++){
3762 row = view*half + bin;
3763 for(col=0; col<prmatGetPixels(mat,row); col++){
3764
3765 xp = prmatGetXCoord(mat,row,col);
3766 xn = imgDim - 1 - xp;
3767 yp = prmatGetYCoord(mat,row,col);
3768 yn = imgDim - 1 - yp;
3769
3770 if(xp != 0 || yp != 0){
3771 if(view == 0){
3772 /* Put coordinates of coincidence line in the next free place and
3773 increase the counter. */
3774 tmpptr[yp*imgDim + xp][++tmpptr[yp*imgDim + xp][0]] = bin;
3775 if(bin != center)
3776 tmpptr[yp*imgDim+(imgDim-1-xp)][++tmpptr[yp*imgDim+(imgDim-1-xp)][0]]=
3777 binNr-bin-1;
3778 tmpptr[(imgDim-1-xp)*imgDim+yp][++tmpptr[(imgDim-1-xp)*imgDim+yp][0]]=
3779 binNr*(viewNr/2) + bin;
3780 if(bin != center)
3781 tmpptr[xp*imgDim+yp][++tmpptr[xp*imgDim+yp][0]] =
3782 binNr*(viewNr/2) + (binNr-bin-1);
3783 }
3784
3785 if(view == viewNr/4) {
3786
3787 // Add img(x,y)*k to the raysum of LOR (view,bin)
3788 tmpptr[yp*imgDim + xp][++tmpptr[yp*imgDim + xp][0]] =
3789 (viewNr/4)*binNr + bin;
3790 // Add img(-x,-y)*k to the raysum of LOR (view,binNr-bin)
3791 if(bin != center)
3792 tmpptr[yn*imgDim + xn][++tmpptr[yn*imgDim + xn][0]] =
3793 (viewNr/4)*binNr + binNr - 1 - bin;
3794
3795 // Rotate the LOR 90 degrees, i.e. x->-x.
3796 // Case: pi/2 + theta = 3pi/4.
3797 // Add img(-y,x)*k to the raysum of LOR (viewNr/2+view,bin)
3798 tmpptr[xn*imgDim + yp][++tmpptr[xn*imgDim + yp][0]] =
3799 (viewNr/2 + viewNr/4)*binNr + bin;
3800 // Add img(y,-x)*k to the raysum of LOR (viewNr/2+view,binNr-bin)
3801 if(bin != center)
3802 tmpptr[xp*imgDim + yn][++tmpptr[xp*imgDim + yn][0]] =
3803 (viewNr/2 + viewNr/4)*binNr + binNr - 1 - bin;
3804 }
3805
3806 if(view != 0 && view != viewNr/4) {
3807
3808 // Add img(x,y)*k to the raysum of LOR (view,bin)
3809 tmpptr[yp*imgDim + xp][++tmpptr[yp*imgDim + xp][0]] =
3810 view*binNr + bin;
3811 if(bin != center)
3812 // Add img(-x,-y)*k to the raysum of LOR (view,binNr-bin)
3813 tmpptr[yn*imgDim + xn][++tmpptr[yn*imgDim + xn][0]] =
3814 view*binNr + binNr - 1 - bin;
3815
3816 // Mirror the LOR on line x=y, and on y-axis i.e x->y and y->-y.
3817 // Case: pi/2+theta
3818 // Add img(y,-x)*k to the raysum of LOR (viewNr/2+view,bin)
3819 tmpptr[xn*imgDim + yp][++tmpptr[xn*imgDim + yp][0]] =
3820 (viewNr/2 + view)*binNr + bin;
3821 // Add img(y,-x)*k to the raysum of LOR (viewNr/2+view,binNr-bin)
3822 if(bin != center)
3823 tmpptr[xp*imgDim + yn][++tmpptr[xp*imgDim + yn][0]] =
3824 (viewNr/2 + view)*binNr + binNr - 1 - bin;
3825
3826 // Mirror the original LOR on y-axis, i.e. x->-x
3827 // Case: pi-theta.
3828 // Add img(-x,y)*k to the raysum of LOR (viewNr-view,bin)
3829 tmpptr[yp*imgDim + xn][++tmpptr[yp*imgDim + xn][0]] =
3830 (viewNr - view)*binNr + bin;
3831 // Add img(x,-y)*k to the raysum of LOR (viewNr-view,binNr-bin)
3832 if(bin != center)
3833 tmpptr[yn*imgDim + xp][++tmpptr[yn*imgDim + xp][0]] =
3834 (viewNr-view)*binNr + binNr - 1 - bin;
3835
3836 // Mirror the LOR on line x=y, i.e. x->y.
3837 // Case: pi/2-theta
3838 // Add img(-y,-x)*k to the raysum of LOR (viewNr/2-view,bin)
3839 tmpptr[xn*imgDim + yn][++tmpptr[xn*imgDim + yn][0]] =
3840 (viewNr/2 - view)*binNr + bin;
3841 // Add img(y,x)*k to the raysum of LOR (viewNr/2-view,binNr-bin)
3842 if(bin != center)
3843 tmpptr[xp*imgDim + yp][++tmpptr[xp*imgDim + yp][0]] =
3844 (viewNr/2 - view)*binNr + binNr - 1 - bin;
3845 }
3846 }
3847 }
3848 }
3849 }
3850
3851 pix = 0;
3852 // Get the number of pixels inside the FOV.
3853 for(row = 0; row < imgDim; row++){
3854 for(col = 0; col < imgDim; col++){
3855 if(ellipseIsInside(elli,row,col))
3856 pix++;
3857 }
3858 }
3859
3860 // Analyse the tmp data array.
3861 p = 0; // index of a pixel inside the FOV
3862 coords = (unsigned int*)calloc(pix,sizeof(int));
3863 iptr = coords;
3864 for(row = 0; row < imgDim; row++){
3865 for(col = 0; col < imgDim; col++){
3866 if(ellipseIsInside(elli,row,col)){
3867 // Put the number of coincidence lines hitting this pixel into the list.
3868 iptr[p] = tmpptr[row*imgDim + col][0];
3869 p++; // increase pixel counter
3870 }
3871 }
3872 }
3873
3874 // Allocate memory for the look-up table.
3875 ret = prmatAllocate(mat,0,pix,coords);
3876 if(ret){
3877 free((unsigned int**)tmpData);
3878 free((int*)coords);
3879 return(ret);
3880 }
3881
3882 /* Put pixel coordinates, number of lines and the coordinates of
3883 the coincidence lines in the structure. */
3884 p = 0;
3885 tmpptr = tmpData;
3886 iptr = coords;
3887 for(row = 0; row < imgDim; row++) {
3888 for(col = 0; col < imgDim; col++) {
3889 if(ellipseIsInside(elli,row,col)) {
3890 // Put pixel coordinates in the list.
3891 mat -> lines[p][0] = row*imgDim + col;
3892 // Put the number of lines hitting this pixel in the list.
3893 mat -> lines[p][1] = iptr[p];
3894 // Put the coordinates of the coincidence lines in the list.
3895 for(lors = 0; lors < iptr[p]; lors++)
3896 mat -> lines[p][lors + 2] = tmpptr[row*imgDim + col][lors+1];
3897
3898 p++; // increase pixel counter
3899 }
3900 }
3901 }
3902
3903 printf("\n");
3904 mat->status = PRMAT_STATUS_LU_OCCUPIED;
3905
3906 free((unsigned int**)tmpData);
3907 free((int*)coords);
3908
3909 return 0;
3910}// END OF SETTING LOOK-UP TABLE.

◆ recGetStatistics()

int recGetStatistics ( float * buf,
int n,
float * osum,
float * omin,
float * omax,
int skip_zero_mins )
extern

Get the sum and minimum and maximum values from a list of floats, optionally ignoring zero values from the minimum.

Returns
Returns the number of non-zero values.
Parameters
bufPointer to the float array of length n.
nArray size.
osumSum of array values is returned here; enter NULL if not needed.
ominMinimum value is returned here; enter NULL if not needed.
omaxMaximum value is returned here; enter NULL if not needed.
skip_zero_minsSkip zero values when determining the minimum; 1 or 0.

Definition at line 154 of file recutil.c.

167 {
168 int i, nonzeroes=0;
169 float sum, min, max;
170
171 if(osum!=NULL) *osum=nanf("");
172 if(omin!=NULL) *omin=nanf("");
173 if(omax!=NULL) *omax=nanf("");
174
175 i=0; while(i<n && !isfinite(buf[i])) i++;
176 if(i==n) return(0);
177
178 sum=0.0; max=buf[i]; min=nanf("");
179 if(!skip_zero_mins || min!=0.0) min=buf[i];
180 for(; i<n; i++) {
181 if(!isfinite(buf[i])) continue;
182 sum+=buf[i];
183 if(buf[i]>max) max=buf[i];
184 if(buf[i]==0.0) {
185 if(skip_zero_mins) continue;
186 } else {
187 nonzeroes++;
188 }
189 if(isnan(min) || buf[i]<min) min=buf[i];
190 }
191 if(osum!=NULL) *osum=sum;
192 if(omin!=NULL) *omin=min;
193 if(omax!=NULL) *omax=max;
194
195 return(nonzeroes);
196}

Referenced by mrp().

◆ recInterpolateSinogram()

void recInterpolateSinogram ( float * srcsino,
float * newsino,
int srcrays,
int newrays,
int views )
extern

Interpolate sinogram so that the sinogram bin width is the same as the image pixel width.

Parameters
srcsinoSource sinogram data, size of srcrays*views.
newsinoNew interpolated sinogram data calculated here; must be allocated with size newrays*views.
srcraysNumber of rays (bins, columns) in the original sinogram.
newraysNumber of rays (bin, columns) in the new interpolated sinogram.
viewsNumber of projection views (angles, rows) in both sinograms.

Definition at line 37 of file recutil.c.

48 {
49 if(srcrays==newrays) {
50 /* no interpolation needed; just copy and return */
51 for(int i=0; i<views*newrays; i++) newsino[i]=srcsino[i];
52 return;
53 }
54
55 float diff, *sp, *np, oposition, weight;
56 np=newsino;
57 for(int j=0; j<views; j++) {
58 sp=srcsino + j*srcrays;
59 for(int i=0; i<newrays; i++) {
60 oposition=(float)(i*srcrays)/(float)newrays;
61 weight = oposition - (float)(int)oposition;
62 sp=srcsino + j*srcrays + (int)oposition;
63 diff = *(sp+1) - *sp;
64 *np++ = *sp + diff*weight;
65 }
66 }
67 np--; *np=srcsino[srcrays*views - 1];
68 return;
69}

Referenced by mrp(), and trmrp().

◆ recSinTables()

void recSinTables ( int views,
float * sinB,
float * sinBrot,
float rotation )
extern

Pre-compute the sine tables for back-projection.

Parameters
viewsNumber of views (sinogram rows).
sinBArray of sine values, length 3*views/2
sinBrotArray of sine values with rotation, length 3*views/2; enter NULL if not needed.
rotationRotation (degrees).

Definition at line 12 of file recutil.c.

21 {
22 int i, n;
23 n=3*views/2;
24 for(i=0; i<n; i++)
25 sinB[i]=(float)sin((double)i*(M_PI/(double)views));
26 if(sinBrot==NULL) return;
27 double rot=M_PI*rotation/180.0;
28 for(i=0; i<n; i++)
29 sinBrot[i]=(float)sin((double)i*(M_PI/(double)views) + rot);
30}

Referenced by fbp(), imgFBP(), imgMRP(), imgReprojection(), mrp(), reprojection(), and trmrp().

◆ reprojection()

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

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 )
extern

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 )
extern

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 )
extern

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}

◆ set_os_set()

void set_os_set ( int os_sets,
int * set_seq )
extern

Make the Ordered Subset process order (bit-reversed sequence).

Parameters
os_setsNr of OS sets.
set_seqArray of length os_sets to be filled here.

Definition at line 113 of file recutil.c.

118 {
119 if(os_sets==0) {
120 return;
121 } else if(os_sets==1) {
122 set_seq[0]=0;
123 } else if(os_sets==2) {
124 set_seq[0]=0;
125 set_seq[1]=1;
126 } else if(os_sets==4) {
127 int i=0;
128 set_seq[i++]=0; set_seq[i++]=2; set_seq[i++]=1; set_seq[i++]=3;
129 return;
130 } if(os_sets==8) {
131 int i=0;
132 set_seq[i++]=0; set_seq[i++]=4; set_seq[i++]=2; set_seq[i++]=6;
133 set_seq[i++]=1; set_seq[i++]=5; set_seq[i++]=3; set_seq[i++]=7;
134 return;
135 } else if(os_sets==16) {
136 int i=0;
137 set_seq[i++]=0; set_seq[i++]=8; set_seq[i++]=4; set_seq[i++]=12;
138 set_seq[i++]=2; set_seq[i++]=10; set_seq[i++]=6; set_seq[i++]=14;
139 set_seq[i++]=1; set_seq[i++]=9; set_seq[i++]=5; set_seq[i++]=13;
140 set_seq[i++]=3; set_seq[i++]=11; set_seq[i++]=7; set_seq[i++]=15;
141 return;
142 } else {
143 set_seq[0]=0; set_seq[1]=1;
144 for(int i=1; i<os_sets; i++) set_seq[i]=bit_rev_int(i, os_sets);
145 }
146}
int bit_rev_int(int x, int n)
Definition recutil.c:77

Referenced by mrp(), and trmrp().

◆ trmrp()

int trmrp ( float * bla,
float * tra,
int dim,
float * image,
int iter,
int os_sets,
int rays,
int views,
int maskdim,
float zoom,
float beta,
float axial_fov,
float sample_distance,
int skip_prior,
int osl,
float shiftX,
float shiftY,
float rotation,
int verbose )
extern

Median Root Prior (MRP) reconstruction of one 2D data matrix given as an array of floats.

See also
fbp, reprojection
Returns
Returns 0 if ok.
Parameters
blaFloat array containing rays*views blank sinogram values. Data must be normalization-corrected.
traFloat array containing rays*views transmission sinogram values. Data must be normalization-corrected.
dimImage x and y dimensions.
imagePointer to pre-allocated image data; size must be at least dim*dim; log-transformed attenuation correction factors will be written in here.
iterNr of iterations.
os_setsLength of ordered subset process order array; 1, 2, 4, ... 128.
raysNr of rays (bins or columns) in sinogram data.
viewsNr of views (rows) in sinogram data.
maskdimMask dimension; 3 or 5 (9 or 21 pixels).
zoomReconstruction zoom.
betaBeta.
axial_fovAxial field-of-view in mm (found in transmission mainheader in cm).
sample_distanceSample distance in mm (found in transmission subheader in cm).
skip_priorNumber of iteration before prior; usually 1.
oslUse OSL-type (0 or 1).
shiftXPossible shifting in x dimension (mm).
shiftYPossible shifting in y dimension (mm).
rotationPossible image rotation, -180 - +180 (in degrees).
verboseVerbose level; if zero, then nothing is printed to stderr or stdout.

Definition at line 21 of file trmrp.c.

63 {
64 if(verbose>0) printf("trmrp()\n");
65
66 if(bla==NULL || tra==NULL || image==NULL) return(1);
67 if(rays<2 || views<2 || dim<2 || iter<1 || os_sets<1) return(1);
68 if(maskdim!=3 && maskdim!=5) return(1);
69 if(zoom<0.05) return(1);
70 //if(dim%2) return(2);
71
72
73 /* Set scale */
74 int recrays;
75 float scale, bp_zoom;
76 recrays=(int)((float)dim*zoom);
77 bp_zoom=zoom*(float)dim/(float)recrays;
78 scale=((float)recrays/(float)rays)*bp_zoom*bp_zoom/(float)views;
79 if(verbose>1) {
80 printf(" recrays := %d\n", recrays);
81 printf(" bp_zoom := %g\n", bp_zoom);
82 printf(" scale := %g\n", scale);
83 }
84
85 int views_in_set;
86 views_in_set=views/os_sets;
87 if(verbose>1) printf(" views_in_set := %d\n", views_in_set);
88
89 /* Make the Ordered Subset process order (bit-reversed sequence) */
90 int seq[os_sets]; set_os_set(os_sets, seq);
91 if(verbose>2) {
92 printf("os_sets :=");
93 for(int i=0; i<os_sets; i++) printf(" %d", seq[i]);
94 printf("\n");
95 }
96 /* Arrange transmission and blank sinograms, and interpolate so that
97 bin width equals pixel width */
98 float recbla[recrays*views], rectra[recrays*views];
99 {
100 float blaset[rays*views], traset[rays*views];
101 /* arrange */
102 for(int s=0; s<os_sets; s++) {
103 for(int j=0; j<views_in_set; j++) {
104 memcpy((char*)(blaset + s*rays*views_in_set + j*rays),
105 (char*)(bla + j*rays*os_sets + s*rays), rays*sizeof(float));
106 memcpy((char*)(traset + s*rays*views_in_set + j*rays),
107 (char*)(tra + j*rays*os_sets + s*rays), rays*sizeof(float));
108 }
109 }
110 /* interpolate */
111 recInterpolateSinogram(blaset, recbla, rays, recrays, views);
112 recInterpolateSinogram(traset, rectra, rays, recrays, views);
113 }
114
115
116 /* Sum of blank and transmission */
117 float bsum=0.0, tsum=0.0;
118 for(int i=0; i<recrays*views_in_set; i++) bsum+=recbla[i];
119 for(int i=0; i<recrays*views_in_set; i++) tsum+=rectra[i];
120 if(verbose>2) {
121 printf(" blank_sum := %g\n", bsum);
122 printf(" transmission_sum := %g\n", tsum);
123 }
124
125 /* Make an initial image: an uniform disk enclosed by rays with a value
126 matching the total count */
127 if(verbose>1) printf("creating initial %dx%d image\n", dim, dim);
128 int imgsize=dim*dim;
129 float current_img[imgsize];
130 for(int i=0; i<imgsize; i++) image[i]=0.0;
131 float init;
132 init=-logf(tsum/bsum)*sample_distance/axial_fov;
133 if(verbose>2) printf(" init := %g\n", init);
134
135 for(int k=0; k<imgsize; k++) current_img[k]=0.0;
136 {
137 int j, k=0;
138 for(j=dim/2-1; j>=-dim/2; j--) {
139 for(int i=-dim/2; i<dim/2; i++) {
140 if((int)hypot((double)i, (double)j) < dim/2-1) current_img[k]=init;
141 k++;
142 }
143 }
144 }
145
146 /* Pre-compute the sine tables for back-projection */
147 if(verbose>1) printf("computing sine table\n");
148 float sinB[3*views/2], sinBrot[3*views/2];
149 recSinTables(views, sinB, sinBrot, rotation);
150 for(int i=0; i<3*views/2; i++) sinB[i]/=bp_zoom;
151 for(int i=0; i<3*views/2; i++) sinBrot[i]/=bp_zoom;
152
153 /* Calculate pixel size */
154 float pixsize;
155 pixsize=sample_distance*(float)rays/(zoom*(float)dim);
156 if(verbose>2) printf(" pixsize := %g\n", pixsize);
157 /* ... and convert shifts from mm to pixels */
158 shiftX/=pixsize;
159 shiftY/=pixsize;
160
161
162 /* Iterations */
163 if(verbose>1) {printf("iterations\n"); fflush(stdout);}
164 float muproj[recrays*views_in_set+1];
165 float atnproj[recrays*views_in_set];
166 float projdiff[recrays*views_in_set];
167 float numerator[imgsize], denominator[imgsize];
168 float med_img[imgsize], oslcoefs[imgsize];
169 int itercount=1;
170 do {
171 if(verbose>3) {printf(" iteration %d\n", itercount); fflush(stdout);}
172
173 if(verbose>1) {
174 float mi, ma;
175 fMinMaxFin(current_img, imgsize, &mi, &ma);
176 printf(" min=%g max=%g iter=%i\n", mi, ma, itercount);
177 for(int i=0; i<imgsize; i++)
178 if(!isfinite(current_img[i])) {
179 printf(" inf in current image! index=%d, iter=%d\n", i, itercount);
180 break;
181 }
182 }
183
184 for(int s=0; s<os_sets; s++) {
185 if(verbose>4) {printf(" os_set %d; seq=%d\n", 1+s, seq[s]); fflush(stdout);}
186 /* Image reprojection */
187 for(int i=0; i<recrays*views_in_set; i++) muproj[i]=0.0;
188#pragma omp parallel for
189 for(int i=0; i<views_in_set; i++) {
190 int view=seq[s]+i*os_sets;
191 if(verbose>8 && (i==0 || i==views_in_set-1)) printf(" reprojecting view %d\n", view);
192 viewReprojection(current_img, muproj+i*recrays, view, dim,
193 views, recrays, sinB, sinBrot, shiftX, shiftY, bp_zoom);
194 //re_proj(current_img, muproj+i*recrays, seq[s]+i*sets, dim, views);
195 }
196
197 /* Calculate correction = measured / re-projected */
198#pragma omp parallel for
199 for(int i=0; i<recrays*views_in_set; i++) {
200 float mup=muproj[i]*scale;
201 float est_count=expf(-mup)*recbla[i];
202 atnproj[i]=est_count*mup;
203 projdiff[i]=est_count - rectra[i];
204 }
205 /* Make numerator and denominator images */
206 for(int i=0; i<imgsize; i++) numerator[i]=0.0;
207 for(int i=0; i<imgsize; i++) denominator[i]=0.0;
208#pragma omp parallel for
209 for(int i=0; i<views_in_set; i++) {
210 int view=seq[s]+i*os_sets;
211 viewBackprojection(projdiff+i*recrays, numerator, dim,
212 view, views, recrays, sinB, sinBrot, shiftX, shiftY, bp_zoom);
213 viewBackprojection(atnproj+i*recrays, denominator, dim,
214 view, views, recrays, sinB, sinBrot, shiftX, shiftY, bp_zoom);
215 }
216 if(verbose>4) {
217 float mi, ma;
218 fMinMaxFin(numerator, imgsize, &mi, &ma);
219 printf(" numerator_range := %g - %g\n", mi, ma);
220 fMinMaxFin(denominator, imgsize, &mi, &ma);
221 printf(" denominator_range := %g - %g\n", mi, ma);
222 }
223
224 /* Apply the prior */
225 if(skip_prior<=0 && beta>0.0) {
226 if(verbose>3) {printf(" applying prior\n"); fflush(stdout);}
227 if(osl) {
228 float maxv, maxm;
229 fMinMaxFin(current_img, imgsize, NULL, &maxv);
230 do_prior(current_img, beta, oslcoefs, dim, 1.0E-08*maxv, maskdim, &maxm);
231 if(verbose>6) {
232 printf(" max value in current image := %g\n", maxv);
233 printf(" max median coefficient := %g\n", maxm);
234 }
235 } else {
236 float *iptr, *mptr;
237 if(maskdim==3) {
238 iptr=current_img+dim+1;
239 mptr=med_img+dim+1;
240 for(int i=2*(dim+1); i<imgsize; i++) *mptr++=med9(iptr++, dim);
241 } else if(maskdim==5) {
242 iptr=current_img+2*dim+2;
243 mptr=med_img+2*dim+2;
244 for(int i=2*(2*dim+2); i<imgsize; i++) *mptr++=med21(iptr++, dim);
245 }
246 for(int i=0; i<imgsize; i++) numerator[i]*=med_img[i];
247 for(int i=0; i<imgsize; i++) numerator[i]-=beta*(current_img[i]-med_img[i]);
248 for(int i=0; i<imgsize; i++) denominator[i]*=med_img[i];
249 for(int i=0; i<imgsize; i++) denominator[i]+=beta*current_img[i];
250 }
251 }
252 /* Calculate the next image */
253 if(verbose>3) {printf(" calculating next image\n"); fflush(stdout);}
254 if(osl && skip_prior<=0 && beta>0.0) { /* convex-OSL */
255 if(verbose>4) printf(" convex-OSL\n");
256 for(int i=0; i<imgsize; i++) {
257 float f=fmaf(numerator[i], 1.0/denominator[i], 1.0);
258 f*=oslcoefs[i];
259 f*=current_img[i];
260 if(isfinite(f)) current_img[i]=f;
261 }
262 } else { /* convex */
263 if(verbose>4) printf(" convex\n");
264 for(int i=0; i<imgsize; i++) {
265 float f=fmaf(numerator[i], 1.0/denominator[i], 1.0);
266 f*=current_img[i];
267 if(isfinite(f)) current_img[i]=f;
268 }
269 }
270 if(verbose>4) {printf(" -> next os_set maybe\n"); fflush(stdout);}
271 } // next set
272 itercount++; skip_prior--;
273 if(verbose>3) {printf(" -> next iteration maybe\n"); fflush(stdout);}
274 } while(itercount<iter);
275 if(verbose>2) {printf(" iterations done.\n"); fflush(stdout);}
276
277 for(int i=0; i<imgsize; i++) image[i]=current_img[i]*=scale;
278
279 if(verbose>1) {printf("trmrp() done.\n"); fflush(stdout);}
280 return(0);
281}
float med21(float *inp, int dim)
Definition mrprior.c:49
float med9(float *inp, int dim)
Definition mrprior.c:15

Referenced by atnMake().

◆ 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 )
extern

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 )
extern

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().

Variable Documentation

◆ ELLIPSE_TEST

int ELLIPSE_TEST
extern

Drive in test mode if not 0.

Definition at line 8 of file ellipse.c.

◆ ELLIPSE_VERBOSE

◆ PRMAT_TEST

int PRMAT_TEST
extern

If not 0 drive in test mode.

Definition at line 8 of file prmat.c.

◆ PRMAT_VERBOSE

int PRMAT_VERBOSE
extern

If not 0 drive in verbose mode.

Definition at line 9 of file prmat.c.

Referenced by prmatAllocate(), prmatEmpty(), prmatInit(), prmatReadMatrix(), and prmatSaveMatrix().

◆ RADON_TEST

int RADON_TEST
extern

Drive in test mode if not 0.

Definition at line 12 of file radon.c.

◆ RADON_VERBOSE

int RADON_VERBOSE
extern

Drive in verbose mode if not 0.

Definition at line 13 of file radon.c.

Referenced by radonBackTransformEA(), radonEmpty(), radonFwdTransform(), radonFwdTransformEA(), and radonSet().