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 bit_rev_int(), and 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 do_prior(), 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 ellipseAllocate(), and 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 ellipseEmpty(), and 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}

Referenced by ellipseGetArray().

◆ 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}

Referenced by ellipseGetCenterX().

◆ 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}

Referenced by ellipseGetCenterY().

◆ 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}

Referenced by ellipseGetImgSize().

◆ 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}

Referenced by ellipseGetInclination().

◆ 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 ellipseGetMajor(), 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 ellipseGetMinor(), 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}

Referenced by ellipseGetValue().

◆ 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}

Referenced by ellipseInfo().

◆ 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

Referenced by ellipseInit().

◆ 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 ellipseIsInside(), 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

Referenced by ellipseReadEllipse().

◆ 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}

Referenced by ellipseSaveEllipse().

◆ 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(), and ellipseSetFromParams().

◆ 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

Referenced by fbp().

◆ 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 fbp_back_proj(), and 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(), fbp_back_proj_round(), 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(), fbp_fft_bidir_complex_radix2(), 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(), fbpMakeFilter(), 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

Referenced by imgFBP().

◆ 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 18 of file mrp.c.

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

Referenced by imgMRP().

◆ 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

Referenced by imgReprojection().

◆ 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(), med21(), 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(), med9(), 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 259 of file mrp.c.

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

Referenced by imgMRP(), and mrp().

◆ 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 226 of file mrp.c.

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

Referenced by mrp(), and mrpProjectionCorrection().

◆ 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 198 of file mrp.c.

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

Referenced by mrp(), and mrpUpdate().

◆ 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 prmatAllocate(), 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 prmatEmpty(), 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 prmatGetBinView(), and 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

Referenced by prmatGetCoord().

◆ 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 prmatGetFactor(), 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 prmatGetFactorSqrSum(), 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

Referenced by prmatGetFactorSum().

◆ 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 prmatGetID(), 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

Referenced by prmatGetMajor().

◆ 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

Referenced by prmatGetMax().

◆ 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

Referenced by prmatGetMin().

◆ 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}

Referenced by prmatGetMinor().

◆ 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 prmatGetNB(), 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 prmatGetNV(), 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 prmatGetPIX(), 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 prmatGetPixCoord(), and 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 prmatGetPixels(), 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 prmatGetRays(), 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 prmatGetRows(), 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 prmatGetXCoord(), 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 prmatGetYCoord(), 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 prmatInit(), and 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

Referenced by prmatReadMatrix().

◆ 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

Referenced by prmatSaveMatrix().

◆ 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 1428 of file radon.c.

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

Referenced by radonBackTransform().

◆ 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 1695 of file radon.c.

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

Referenced by radonBackTransformEA().

◆ 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 2507 of file radon.c.

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

Referenced by radonBackTransformPRM().

◆ 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 2419 of file radon.c.

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

Referenced by radonBackTransformSA().

◆ 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

Referenced by radonEmpty().

◆ 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

Referenced by radonFwdTransform().

◆ 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 549 of file radon.c.

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

Referenced by radonFwdTransformEA().

◆ 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 1327 of file radon.c.

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

Referenced by radonFwdTransformPRM().

◆ 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 1237 of file radon.c.

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

Referenced by radonFwdTransformSA().

◆ 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(), radonGetCB(), 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(), radonGetHI(), 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(), radonGetID(), 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(), radonGetMO(), 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(), radonGetNB(), 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(), radonGetNV(), 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(), radonGetSD(), 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(), radonGetSin(), 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}

Referenced by radonSet().

◆ 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 2606 of file radon.c.

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

Referenced by radonSetBases().

◆ 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 2988 of file radon.c.

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

Referenced by radonSetBasesEA().

◆ 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 3934 of file radon.c.

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

Referenced by radonSetLORS().

◆ 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 3728 of file radon.c.

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

Referenced by radonSetLUT().

◆ 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(), and recGetStatistics().

◆ 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(), recInterpolateSinogram(), 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(), recSinTables(), 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(), and reprojection().

◆ 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(), reprojection(), and reprojectionAvg3().

◆ 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(), reprojection(), and reprojectionAvg5().

◆ 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}

Referenced by reprojectionMed3().

◆ 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(), set_os_set(), 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 17 of file trmrp.c.

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

Referenced by atnMake(), and trmrp().

◆ 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(), trmrp(), and viewBackprojection().

◆ 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(), trmrp(), and viewReprojection().

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(), radonSet(), and radonSetBasesEA().