TPCCLIB
Loading...
Searching...
No Matches
radon.c
Go to the documentation of this file.
1
11/*****************************************************************************/
14/*****************************************************************************/
15#include "libtpcrec.h"
16/*****************************************************************************/
17
18/*****************************************************************************/
19/* Initialization and memory handling for radon transform data. */
20/*****************************************************************************/
27void radonEmpty(RADON *radtra)
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}
50/*****************************************************************************/
62int radonSet(RADON *radtra,int mode,int imgDim,int viewNr,int binNr)
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}
111/*****************************************************************************/
112/* Get functions for Radon data */
113/*****************************************************************************/
119int radonGetMO(RADON *radtra)
120{
121 return radtra->mode;
122}
123/*****************************************************************************/
128int radonGetID(RADON *radtra)
129{
130 return radtra->imgDim;
131}
132/*****************************************************************************/
138int radonGetNV(RADON *radtra)
139{
140 return radtra->viewNr;
141}
142/*****************************************************************************/
148int radonGetNB(RADON *radtra)
149{
150 return radtra->binNr;
151}
152/*****************************************************************************/
159float radonGetSD(RADON *radtra)
160{
161 return radtra->sampleDist;
162}
163/*****************************************************************************/
169int radonGetHI(RADON *radtra)
170{
171 return radtra->half;
172}
173/*****************************************************************************/
180int radonGetCB(RADON *radtra)
181{
182 return radtra->centerBin;
183}
184/*****************************************************************************/
192float radonGetSin(RADON *radtra, int nr)
193{
194 return radtra->sines[nr];
195}
196/*****************************************************************************/
197/* THE ACTUAL TRANSFORM FUNCTIONS */
198/*****************************************************************************/
217 RADON *radtra, int set, int setNr, float *imgdata, float *scndata
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
540/*****************************************************************************/
551 RADON *radtra, int set, int setNr, float *imgdata, float *scndata)
552{
553 float *imgptr, *scnptr; // pointers for the image and sinogram data
554 float *Y, *X, *Xptr, *Yptr; // pointers for the values of LOR in integer points
555 double sinus, cosinus, tanus; // sin, cosine and tangent
556 double shift_x, shift_y; // shift for LOR
557 int xp, xn, yp, yn, z, xp2; //integer points
558 int x_left, x_right, y_top, y_bottom; // limits for fast search
559 int col, col1, col2, row, view, bin; //counters
560 int binNr, viewNr, imgDim, errors=0;
561 int half, center = -1;
562 float sdist;
563 float a=0,b=0, c=0, d=0, g=0, h=0, A;
564 float dx, dy , eps1 = 0, eps2 = 0, eps3 = 0; // delta x and y and factors.
565
566 if( RADON_VERBOSE ){
567 printf("RADON: radonFwdTransformEA() started.\n");
568 fflush(stdout);
569 }
570
571 // Check that the data for this radon transform is initialized.
572 if(radtra->status != RADON_STATUS_INITIALIZED) return -1;
573
574 // Retrieve the parameters from given radon transform object.
575 //mode=radonGetMO(radtra); // Should be 2.
576 imgDim=radonGetID(radtra);
577 binNr=radonGetNB(radtra);
578 viewNr=radonGetNV(radtra);
579 sdist=radonGetSD(radtra);
580 half=radonGetHI(radtra);
581 center=radonGetCB(radtra);
582
583 // Array for storing values f_x.
584 X=(float*)calloc(imgDim+1,sizeof(float));
585 // Array for storing values f_y.
586 Y=(float*)calloc(imgDim+1,sizeof(float));
587 if(X==NULL || Y==NULL){
588 return -2;
589 }
590 Xptr=X;
591 Yptr=Y;
592
593 imgptr=imgdata;
594 scnptr=scndata;
595
597 // Find pixel coordinates of the contributing pixels for tubes of response
598 // belonging to first 1/4th of angles. From these pixel coordinates
599 // others can be calculated via symmetries in projection space.
600 // N.B. The line of response: a*x+b*y+c
601 // => solve y: y = (s - x*cos(theta))/sin(theta)
602 // solve x: x = (s - y*sin(theta))/cos(theta)
603
604 for(view=set; view<=viewNr/4; view=view+setNr){
605 // Choose the type of the line of response according to view number.
606
607 // view=0 -> sin(theta)=0
608 if(view==0){
609
610 // Choose column(s) according to sample distance for angles 0 and pi/2.
611 col1 = 0;
612 col2 = 0;
613 for(bin = 0; bin < half; bin++){
614
615 col1 = col2;
616 col2 = floor((float)(bin + 1)*sdist);
617
618 // Determine factor epsilon.
619 if(col1 == col2){
620 eps1 = sdist;
621 eps2 = 0;
622 eps3 = 0;
623 }
624 if((col2-col1) == 1){
625 eps1 = (float)(col2 - (bin)*sdist);
626 eps2 = 0;
627 eps3 = (float)((bin+1)*sdist - col2);
628
629 }
630 // If sdist > pixel size!
631 if((col2-col1) > 1){
632 eps1 = (float)(col1 + 1 - (bin)*sdist);
633 eps2 = 1; // middle pixel.
634 eps3 = (float)((bin+1)*sdist - col2);
635
636 }
637
638 /* Iterate through the entries in the image matrix.
639 Calculate raysums for two LORs in the same distance from origin
640 (do halfturn). */
641 for(row=0; row<imgDim; row++) {
642
643 if(!eps3){
644 scnptr[bin] += eps1 * imgptr[row*imgDim + col1];
645 if(bin != center)
646 scnptr[binNr-bin-1] +=
647 eps1 * imgptr[row*imgDim + (imgDim - 1 - col1)];
648
649 scnptr[binNr*(viewNr/2) + bin] +=
650 eps1 * imgptr[(imgDim - 1 - col1)*imgDim + row];
651 if(bin != center)
652 scnptr[binNr*(viewNr/2) + (binNr-bin-1)] +=
653 eps1 * imgptr[col1*imgDim + row];
654 }
655
656 if(eps3 && !eps2){
657 scnptr[bin] += eps1 * imgptr[row*imgDim + col1] +
658 eps3 * imgptr[row*imgDim + col2];
659 if(bin != center)
660 scnptr[binNr-bin-1] +=
661 eps1 * imgptr[row*imgDim + (imgDim - 1 - col1)] +
662 eps3*imgptr[row*imgDim+(imgDim-1-col2)];
663
664 scnptr[binNr*(viewNr/2) + bin] +=
665 eps1*imgptr[(imgDim-1-col1)*imgDim+row] +
666 eps3*imgptr[(imgDim-1-col2)*imgDim+row];
667 if(bin != center)
668 scnptr[binNr*(viewNr/2) + (binNr-bin-1)] +=
669 eps1 * imgptr[col1*imgDim + row] +
670 eps3 * imgptr[col2*imgDim + row] ;
671 }
672
673 if(eps3 && eps2) {
674 for(col = col1; col<=col2; col++) {
675 if(col == col1){
676 scnptr[bin] += eps1 * imgptr[row*imgDim + col1];
677 if(bin != center)
678 scnptr[binNr-bin-1] += eps1 * imgptr[row*imgDim +
679 (imgDim - 1 - col1)];
680 scnptr[binNr*(viewNr/2) + bin] +=
681 eps1 * imgptr[(imgDim - 1 - col1)*imgDim + row];
682 if(bin != center)
683 scnptr[binNr*(viewNr/2) + (binNr-bin-1)] +=
684 eps1 * imgptr[col1*imgDim + row];
685 }
686 if(col == col2) {
687 scnptr[bin] += eps3 * imgptr[row*imgDim + col2];
688 if(bin != center)
689 scnptr[binNr-bin-1] += eps3 * imgptr[row*imgDim +
690 (imgDim - 1 - col2)];
691 scnptr[binNr*(viewNr/2) + bin] +=
692 eps3 * imgptr[(imgDim - 1 - col2)*imgDim + row];
693 if(bin != center)
694 scnptr[binNr*(viewNr/2) + (binNr-bin-1)] +=
695 eps3 * imgptr[col2*imgDim + row];
696 }
697 if(col != col1 && col != col2) {
698 scnptr[bin] += eps2 * imgptr[row*imgDim + col];
699 if(bin != center)
700 scnptr[binNr-bin-1] +=
701 eps2 * imgptr[row*imgDim + (imgDim - 1 - col)];
702 scnptr[binNr*(viewNr/2) + bin] +=
703 eps2 * imgptr[(imgDim - 1 - col)*imgDim + row];
704 if(bin != center)
705 scnptr[binNr*(viewNr/2) + (binNr-bin-1)] +=
706 eps2 * imgptr[col*imgDim + row];
707 }
708 }
709 }
710 }
711 }
712 // End of view==0 (handles angles 0 and pi/2).
713 } else {
714
715 // Set sine and cosine for this angle.
716 sinus = (double)radonGetSin(radtra,view);
717 cosinus = (double)radonGetSin(radtra,viewNr/2 + view);
718 tanus = sinus/cosinus;
719
720 // Set shift from origin for the first line of response (-n/2,theta).
721 // NOTE that image matrix is on cartesian coordinate system where origin
722 // is in the middle and shift is in pixels.
723 shift_y = -(imgDim/2)/sinus;
724 shift_x = -(imgDim/2)/cosinus;
725
726 // Evaluate the function of the first LOR in integer points [-n/2,n/2].
727 // NOTE that image matrix is on cartesian coordinate system where origin
728 // is in the middle.
729 z=-imgDim/2;
730 for(col=0; col<imgDim+1; col++){
731 Yptr[col]=(float)(-z/tanus + shift_y);
732 Xptr[col]=(float)(-z*tanus + shift_x);
733 z++;
734 }
735
736 // Set shift from the first TOR.
737 shift_y = (double)(sdist/sinus);
738 shift_x = (double)(sdist/cosinus);
739
740 // Iterate through half the bins in this view,
741 // and determine coordinates of pixels contributing to this TOR.
742 // NOTE that shift is added according to 'bin' in every loop.
743 // Others are determined via symmetry in projection space.
744
745 for(bin=0; bin<half; bin++){
746
747 // Limit (x-)indices for fast search.
748 // Note that indices are non-negative integers.
749
750 x_left = floor((float)(Xptr[imgDim] + bin*shift_x + imgDim/2));
751 if(x_left < 0) x_left = 0;
752
753 x_right = floor((float)(Xptr[0] + bin*shift_x + imgDim/2));
754 if(x_right <= 0) x_right = 1;
755 if(x_right > imgDim) x_right = imgDim - 1;
756
757 /* Iterate through the values in vector Y, in integer points
758 [x_left,x_rigth]. */
759 for(z=x_left; z <= x_right; z++) {
760
761 xp = z; //positive x-coordinate
762 xn = imgDim - 1 - xp; //negative x-coordinate
763
764 // Look y from left. yp=positive y-coordinate
765 yp = imgDim/2 - floor(Yptr[xp + 1] + bin*shift_y) - 1;
766 yn = imgDim - 1 - yp;
767
768 // If the y-value for this x (z) is inside the image grid.
769 if(yp < imgDim && yp >= 0 && yn < imgDim && yn >= 0 && xp >= 0 &&
770 xp < imgDim && xn < imgDim && xn >= 0)
771 {
772
773 /* NOTE that pixels found in this part are always hit from right
774 side. Compute a := |AF| and b := |FB|. */
775 a = (float)(xp + 1 - (imgDim/2 + Xptr[imgDim - yp] + bin*shift_x));
776 b = (float)(floor(Yptr[xp + 1] + bin*shift_y) + 1 - (Yptr[xp + 1] +
777 bin*shift_y));
778
779 // Calculate the area of lower triangle.
780 A = a*b/2;
781 // c := |FC|
782 c = (float)(xp + 1 - (imgDim/2 + Xptr[imgDim - yp] +
783 (bin+1)*shift_x));
784 if(c > 0){
785 // d := |FD|
786 d = (float)(floor(Yptr[xp + 1] + (bin+1)*shift_y) + 1 -
787 (Yptr[xp + 1] + (bin+1)*shift_y));
788 // Subtract the area of upper triangle.
789 A = A - c*d/2;
790 }
791
792 eps1 = A;
793 if( (eps1 < 0 || eps1 > 1) && RADON_VERBOSE){
794 printf("RADON: Error in factor: eps1=%.5f \n",eps1);
795 errors++;
796 }
797
798 // Case: theta.
799 // Add img(x,y)*k to the raysum of TOR (view,bin)
800 scnptr[view*binNr + bin] += eps1 * imgptr[yp*imgDim + xp];
801 // Add img(-x,-y)*k to the raysum of LOR (view,binNr-bin)
802 if(bin != center)
803 scnptr[view*binNr + binNr - 1 - bin] +=
804 eps1 * imgptr[yn*imgDim + xn];
805
806 if(view != viewNr/4){
807 // Mirror the original LOR on y-axis, i.e. x->-x
808 // Case: pi-theta.
809 // Add img(-x,y)*k to the raysum of LOR (viewNr-view,bin)
810 scnptr[(viewNr - view)*binNr + bin] +=
811 eps1 * imgptr[yp*imgDim + xn];
812 // Add img(x,-y)*k to the raysum of LOR (viewNr-view,binNr-bin)
813 if(bin != center)
814 scnptr[(viewNr-view)*binNr + binNr - 1 - bin] +=
815 eps1 * imgptr[yn*imgDim + xp];
816
817 // Mirror the LOR on line x=y, i.e. x->y.
818 // Case: pi/2-theta
819 // Add img(-y,-x)*k to the raysum of LOR (viewNr/2-view,bin)
820 scnptr[(viewNr/2 - view)*binNr + bin] +=
821 eps1 * imgptr[xn*imgDim + yn];
822 // Add img(y,x)*k to the raysum of LOR (viewNr/2-view,binNr-bin)
823 if(bin != center)
824 scnptr[(viewNr/2 - view)*binNr + binNr - 1 - bin] +=
825 eps1 * imgptr[xp*imgDim + yp];
826 }
827
828 // Mirror the LOR on line x=y, and on y-axis i.e x->y and y->-y.
829 // Case: pi/2+theta
830 // Add img(y,-x)*k to the raysum of LOR (viewNr/2+view,bin)
831 scnptr[(viewNr/2 + view)*binNr + bin] +=
832 eps1 * imgptr[xn*imgDim + yp];
833 // Add img(y,-x)*k to the raysum of LOR (viewNr/2+view,binNr-bin)
834 if(bin != center)
835 scnptr[(viewNr/2 + view)*binNr + binNr - 1 - bin] +=
836 eps1 * imgptr[xp*imgDim + yn];
837 }
838 }
839
840 // Limit (y-)indices for fast search.
841 // Note that indices are non-negative integers.
842 y_bottom = floor((float)(Yptr[imgDim] + bin*shift_y + imgDim/2));
843 if(y_bottom < 0) y_bottom = 0;
844 if(y_bottom > imgDim) y_bottom = 0;
845
846 y_top = floor((float)(Yptr[0] + bin*shift_y + imgDim/2));
847 if(y_top > imgDim) y_top = imgDim;
848 if(y_top <= 0) y_top = 1;
849
850 /* Iterate through the values in vector X, in integer points
851 [y_bottom,y_top]. */
852 for(z=y_top; z >= y_bottom; z--) {
853
854 // Look y from this location.
855 xp = floor(Xptr[z] + bin*shift_x) + imgDim/2;
856 xn = imgDim - 1 - xp;
857
858 yp = imgDim - z - 1;
859 yn = imgDim - yp - 1;
860
861 // If the x-value for this y (z) is inside the image grid.
862 if(yp < imgDim && yp >= 0 && yn < imgDim && yn >= 0 && xp >= 0 &&
863 xp < imgDim && xn < imgDim && xn >= 0)
864 {
865 eps1=eps2=eps3=0;
866 dx = (float)(Xptr[z] + bin*shift_x + imgDim/2 - xp);
867 dy = (float)(Yptr[xp] + bin*shift_y - z + imgDim/2);
868 if(dy < 1){ // Cases 3,4,5 and 6.
869 // 1. PART
870 // a := |HA|
871 a = dy;
872 // b := |HB| (b < 1 for angles in [0,pi/4))
873 b = dx;
874 // h := height of rectangle R.
875 h = a + shift_y;
876 if(h > 1){ // Cases 3,4 and 5.
877 h = 1;
878 g = b + shift_x;
879 if(g > 1){ // Cases 3 and 4.
880 g = 1;
881 xp2 =floor(Xptr[z+1] + (bin+1)*shift_x) + imgDim/2;
882 if(xp == xp2){ // Case 4.
883 // c := |FC|
884 c = (float)(xp + 1 - (imgDim/2 + Xptr[z+1] +
885 (bin+1)*shift_x));
886 // d := |FD|
887 d = (float)(floor(Yptr[xp + 1] + (bin+1)*shift_y) + 1 -
888 (Yptr[xp + 1] + (bin+1)*shift_y));
889 eps1 = 1 - (a*b + c*d)/2;
890 eps2 = 0;
891 // Lower triangle on the next pixel (x+1,y).
892 eps3 = (1 - d)*(b + shift_x - 1)/2;
893 if((eps1<0 || eps1>1 || eps2<0 || eps2>1 || eps3<0 || eps3>1)
894 && RADON_VERBOSE) printf(
895 "4: (%i,%i) eps1=%f | (%i,%i) eps2=%f | (%i,%i) eps3=%f\n",
896 xp,yp,eps1,xp+1,yp-1,eps2,xp+1,yp,eps3);
897 } else { // Case 3.
898 // c=d=0.
899 eps1 = 1 - a*b/2;
900
901 // Calculate area on pixel in place (xp+1,yp-1).
902 dy = (float)(Yptr[xp+1] + (bin+1)*shift_y - (z + 1) +
903 imgDim/2);
904 if(dy < 1){ // Case 11.
905 // c := |HC|
906 c = dy;
907 // d := |HD|
908 d = (float)(xp + 2 - (imgDim/2 + Xptr[z+1] +
909 (bin+1)*shift_x));
910 eps2 = c*d/2;
911 } else { // Cases 9 and 10.
912 dx = (float)(xp + 2 - (imgDim/2 + Xptr[z+1] +
913 (bin+1)*shift_x));
914 if(dx < 1) { // Case 10.
915 // g := length of rectangle Q.
916 g = dx;
917 // c := |CD| (on x-axis).
918 c = dx - (float)(xp + 2 - (imgDim/2 + Xptr[z+2] +
919 (bin+1)*shift_x));
920 // Rectangle Q - triangle c*h (h = 1).
921 eps2 = g - c/2;
922 } else { // Case 9.
923 // c := |FC|
924 c = (float)(xp + 2 - (imgDim/2 + Xptr[z+2] +
925 (bin+1)*shift_x));
926 // d := |FD|
927 d = (float)(floor(Yptr[xp + 2] + (bin+1)*shift_y) + 2 -
928 (Yptr[xp + 2] + (bin+1)*shift_y));
929 // Rectangle Q - triangle CFD.
930 eps2 = 1 - c*d/2;
931 }
932 }
933
934 // Calculate area on pixel in place (xp+1,yp).
935 dx = (float)(xp + 2 - (imgDim/2 + Xptr[z] + (bin+1)*shift_x));
936 if(dx < 1){ // Case 10.
937 // g := length of rectangle Q.
938 g = dx;
939 // c := |CD| (on x-axis).
940 c = dx - (float)(xp + 2 - (imgDim/2 + Xptr[z+1] +
941 (bin+1)*shift_x));
942 // Rectangle Q - triangle c*h (h = 1).
943 eps3 = g - c/2;
944 } else { // Case 9.
945 // c := |FC|
946 c = (float)(xp + 2 - (imgDim/2 + Xptr[z+1] +
947 (bin+1)*shift_x));
948 // d := |FD|
949 d = (float)(floor(Yptr[xp + 2] + (bin+1)*shift_y) + 1 -
950 (Yptr[xp + 2] + (bin+1)*shift_y));
951 // Rectangle Q - triangle CFD.
952 eps3 = 1 - c*d/2;
953 }
954 if((eps1<0 || eps1>1 || eps2<0 || eps2>1 || eps3<0 || eps3>1)
955 && RADON_VERBOSE) printf(
956 "3/v%i: (%i,%i) eps1=%f | (%i,%i) eps2=%f | (%i,%i) eps3=%f\n",
957 view,xp,yp,eps1,xp+1,yp-1,eps2,xp+1,yp,eps3);
958 }
959 } else { // Case 5. (g < 1)
960 // c := |DC|.
961 c = g - (imgDim/2 + Xptr[z+1] + (bin+1)*shift_x - xp);
962 // d := heigth
963 d = 1;
964 eps1 = g*h - (a*b + c*d)/2;
965 eps2 = 0;
966 eps3 = 0;
967 if((eps1<0 || eps1>1 || eps2<0 || eps2>1 || eps3<0 || eps3>1)
968 && RADON_VERBOSE) printf(
969 "5: (%i,%i) eps1=%f | (%i,%i) eps2=%f | (%i,%i) eps3=%f\n",
970 xp,yp,eps1,xp+1,yp-1,eps2,xp+1,yp,eps3);
971 }
972 } else{ // Case 6 (h <= 1).
973 // g := legth of rectangle R
974 g = b + shift_x;
975 if(g > 1) // Should always be < 1 for angles in [0,pi/4)
976 g = 1;
977 eps1 = (g*h - a*b)/2;
978 eps2 = 0;
979 eps3 = 0;
980 if((eps1<0 || eps1>1 || eps2<0 || eps2>1 || eps3<0 || eps3>1) &&
981 RADON_VERBOSE) printf(
982 "6: (%i,%i) eps1=%f | (%i,%i) eps2=%f | (%i,%i) eps3=%f\n",
983 xp,yp,eps1,xp+1,yp-1,eps2,xp+1,yp,eps3);
984 }
985 } else { // 2. PART
986 // Cases 2,7 and 8. (dy >= 1).
987 // a := |HA|
988 a = 1;
989 // b := |HB| (>=1)
990 b = dx - (float)(Xptr[z+1] + bin*shift_x + imgDim/2 - xp);
991 // h := heigth of rectangle R
992 h = 1;
993 // g := length of rectangle R
994 g = dx + shift_x;
995 if(g > 1){ // Cases 2 and 8.
996 g = 1 - (float)(Xptr[z+1] + bin*shift_x + imgDim/2 - xp);
997 // positive x-coordinate (bin+1)
998 xp2 = floor(Xptr[z+1] + (bin+1)*shift_x) + imgDim/2;
999 if(xp == xp2){ // Case 8.
1000 // c := |FC|
1001 c = (float)(xp + 1 - (imgDim/2 + Xptr[z+1] +
1002 (bin+1)*shift_x));
1003 // d := |FD|
1004 d = (float)(floor(Yptr[xp + 1] + (bin+1)*shift_y) + 1 -
1005 (Yptr[xp + 1] + (bin+1)*shift_y));
1006 eps1 = g*h - (a*b + c*d)/2;
1007 eps2 = 0;
1008 // Lower triangle on the next pixel (x+1,y).
1009 eps3 = (1 - d)*((Xptr[z] + (bin+1)*shift_x + imgDim/2) -
1010 (xp+1))/2;
1011 if((eps1<0 || eps1>1 || eps2<0 || eps2>1 || eps3<0 || eps3>1)
1012 && RADON_VERBOSE) printf(
1013 "8: (%i,%i) eps1=%f | (%i,%i) eps2=%f | (%i,%i) eps3=%f\n",
1014 xp,yp,eps1,xp+1,yp-1,eps2,xp+1,yp,eps3);
1015 } else{ // Case 2.
1016 // c=d=0.
1017 eps1 = g*h - a*b/2;
1018 /* Pixel in place (xp+1,yp-1) should have been found in
1019 the previous step. */
1020 eps2 = 0;
1021 // Calculate area on pixel in place (xp+1,yp).
1022 dx = (float)((imgDim/2 + Xptr[z] + (bin+1)*shift_x) - (xp+1));
1023 if(dx < 1){ // Case 10 (trapezium).
1024 // g := bottom of trapezium Q.
1025 g = dx;
1026 // c := top of trapezium Q.
1027 c = (float)((imgDim/2 + Xptr[z+1] + (bin+1)*shift_x) -
1028 (xp+1));
1029 // Area of trapezium Q. Heigth = 1.
1030 eps3 = (g + c)/2;
1031 if((eps1<0 || eps1>1 || eps2<0 || eps2>1 || eps3<0 ||
1032 eps3>1) && RADON_VERBOSE) printf(
1033 "2/10: (%i,%i) eps1=%f | (%i,%i) eps2=%f | (%i,%i) eps3=%f\n",
1034 xp,yp,eps1,xp+1,yp-1,eps2,xp+1,yp,eps3);
1035 } else { // Case 9.
1036 // c := |FC|
1037 c = (float)(xp + 2 - (imgDim/2 + Xptr[z+1] +
1038 (bin+1)*shift_x));
1039 // d := |FD|
1040 d = (float)(floor(Yptr[xp + 2] + (bin+1)*shift_y) + 1 -
1041 (Yptr[xp + 2] + (bin+1)*shift_y));
1042 // Rectangle Q - triangle CFD.
1043 eps3 = 1 - c*d/2;
1044 if((eps1<0 || eps1>1 || eps2<0 || eps2>1 || eps3<0 ||
1045 eps3>1) && RADON_VERBOSE) printf(
1046 "2/9: (%i,%i) eps1=%f | (%i,%i) eps2=%f | (%i,%i) eps3=%f\n",
1047 xp,yp,eps1,xp+1,yp-1,eps2,xp+1,yp,eps3);
1048 }
1049 }
1050 } else { // Case 7. (g < = 1)
1051 // Area of the parallelogram R.
1052 eps1 = sdist/cosinus;
1053 eps2 = 0;
1054 eps3 = 0;
1055 if((eps1<0 || eps1>1 || eps2<0 || eps2>1 || eps3<0 || eps3>1)
1056 && RADON_VERBOSE) printf(
1057 "7: (%i,%i) eps1=%f | (%i,%i) eps2=%f | (%i,%i) eps3=%f\n",
1058 xp,yp,eps1,xp+1,yp-1,eps2,xp+1,yp,eps3);
1059 }
1060 }
1061 if(!eps2 && !eps3){ // Cases 5,6 and 7.
1062 // Case: theta.
1063 // Add img(x,y)*k to the raysum of LOR (view,bin)
1064 scnptr[view*binNr + bin] += eps1 * imgptr[yp*imgDim + xp];
1065 // Add img(-x,-y)*k to the raysum of LOR (view,binNr-bin)
1066 if(bin != center)
1067 scnptr[view*binNr + binNr - 1 - bin] +=
1068 eps1 * imgptr[yn*imgDim + xn];
1069 if(view != viewNr/4){
1070 // Mirror the LOR on y-axis, i.e. x->-x
1071 // Case: pi-theta.
1072 // Add img(-x,y)*k to the raysum of LOR (viewNr-view,bin)
1073 scnptr[(viewNr - view)*binNr + bin] +=
1074 eps1 * imgptr[yp*imgDim + xn];
1075 // Add img(x,-y)*k to the raysum of LOR (viewNr-view,binNr-bin)
1076 if(bin != center)
1077 scnptr[(viewNr-view)*binNr + binNr - 1 - bin] +=
1078 eps1 * imgptr[yn*imgDim + xp];
1079
1080 // Mirror the LOR on line y=x, i.e. y->x.
1081 // Case: pi/2 - theta.
1082 // Add img(y,x)*k to the raysum of LOR (viewNr/2-view,bin).
1083 scnptr[(viewNr/2 - view)*binNr + bin] +=
1084 eps1 * imgptr[xn*imgDim + yn];
1085 // Add img(-y,-x)*k to the raysum of LOR (viewNr/2-view,binNr-bin)
1086 if(bin != center)
1087 scnptr[(viewNr/2 - view)*binNr + binNr - 1 - bin] +=
1088 eps1 * imgptr[xp*imgDim + yp];
1089 }
1090
1091 // Mirror the LOR on line x=y, and on y-axis i.e x->y and y->-y.
1092 // Case: pi/2 + theta.
1093 // Add img(y,-x)*k to the raysum of LOR (viewNr/2+view,bin)
1094 scnptr[(viewNr/2 + view)*binNr + bin] +=
1095 eps1 * imgptr[xn*imgDim + yp];
1096 // Add img(-y,x)*k to the raysum of LOR (viewNr-view,binNr-bin)
1097 if(bin != center)
1098 scnptr[(viewNr/2 + view)*binNr + binNr - 1 - bin] +=
1099 eps1 * imgptr[xp*imgDim + yn];
1100 } else {
1101 if(!eps2) { // <=> eps3 != 0 & eps2 = 0 <=> Cases 3,4 and 8.
1102 if(xp + 1 < imgDim && xn - 1 >= 0){
1103 // Case: theta.
1104 // Add img(x,y)*k to the raysum of LOR (view,bin)
1105 scnptr[view*binNr + bin] +=
1106 eps1 * imgptr[yp*imgDim + xp] +
1107 eps3 * imgptr[yp*imgDim + xp+1];
1108 // Add img(-x,-y)*k to the raysum of LOR (view,binNr-bin)
1109 if(bin != center)
1110 scnptr[view*binNr + binNr - 1 - bin] +=
1111 eps1 * imgptr[yn*imgDim + xn] +
1112 eps3 * imgptr[yn*imgDim + xn-1];
1113 if(view != viewNr/4) {
1114 // Mirror the LOR on y-axis, i.e. x->-x
1115 // Case: pi-theta.
1116 // Add img(-x,y)*k to the raysum of LOR (viewNr-view,bin)
1117 scnptr[(viewNr - view)*binNr + bin] +=
1118 eps1 * imgptr[yp*imgDim + xn] +
1119 eps3 * imgptr[yp*imgDim + xn-1];
1120 // Add img(x,-y)*k to the raysum of LOR (viewNr-view,binNr-bin)
1121 if(bin != center)
1122 scnptr[(viewNr-view)*binNr + binNr - 1 - bin] +=
1123 eps1 * imgptr[yn*imgDim + xp] +
1124 eps3 * imgptr[yn*imgDim + xp+1];
1125
1126 // Mirror the LOR on line y=x, i.e. y->x.
1127 // Case: pi/2 - theta.
1128 // Add img(y,x)*k to the raysum of LOR (viewNr/2-view,bin).
1129 scnptr[(viewNr/2 - view)*binNr + bin] +=
1130 eps1 * imgptr[xn*imgDim + yn] +
1131 eps3 * imgptr[(xn-1)*imgDim + yn];
1132 /* Add img(-y,-x)*k to the raysum of LOR
1133 (viewNr/2-view,binNr-bin) */
1134 if(bin != center)
1135 scnptr[(viewNr/2 - view)*binNr + binNr - 1 - bin] +=
1136 eps1 * imgptr[xp*imgDim + yp] +
1137 eps3*imgptr[(xp+1)*imgDim+yp];
1138 }
1139 // Mirror the LOR on line x=y, and on y-axis i.e x->y and y->-y.
1140 // Case: pi/2 + theta.
1141 // Add img(y,-x)*k to the raysum of LOR (viewNr/2+view,bin)
1142 scnptr[(viewNr/2 + view)*binNr + bin] +=
1143 eps1 * imgptr[xn*imgDim + yp] +
1144 eps3 * imgptr[(xn-1)*imgDim + yp];
1145 // Add img(-y,x)*k to the raysum of LOR (viewNr-view,binNr-bin)
1146 if(bin != center)
1147 scnptr[(viewNr/2 + view)*binNr + binNr - 1 - bin] +=
1148 eps1 * imgptr[xp*imgDim + yn] +
1149 eps3*imgptr[(xp+1)*imgDim+yn];
1150 }
1151 } else { // <=> eps2!=0 && eps3!=0 <=> Case 3.
1152 if(xp + 1 < imgDim && xn - 1 >= 0 && yp-1 >= 0 && yn+1 < imgDim) {
1153 // Case: theta.
1154 // Add img(x,y)*k to the raysum of LOR (view,bin)
1155 scnptr[view*binNr + bin] +=
1156 eps1 * imgptr[yp*imgDim + xp] +
1157 eps3 * imgptr[yp*imgDim + xp+1] +
1158 eps2 * imgptr[(yp-1)*imgDim + xp+1];
1159 // Add img(-x,-y)*k to the raysum of LOR (view,binNr-bin)
1160 if(bin != center)
1161 scnptr[view*binNr + binNr - 1 - bin] +=
1162 eps1 * imgptr[yn*imgDim + xn] +
1163 eps3 * imgptr[yn*imgDim + xn-1] +
1164 eps2 * imgptr[(yn+1)*imgDim + xn-1];
1165
1166 if(view != viewNr/4){
1167 // Mirror the LOR on y-axis, i.e. x->-x
1168 // Case: pi-theta.
1169 // Add img(-x,y)*k to the raysum of LOR (viewNr-view,bin)
1170 scnptr[(viewNr - view)*binNr + bin] +=
1171 eps1 * imgptr[yp*imgDim + xn] +
1172 eps3 * imgptr[yp*imgDim + xn-1] +
1173 eps2 * imgptr[(yp-1)*imgDim + xn-1];
1174 // Add img(x,-y)*k to the raysum of LOR (viewNr-view,binNr-bin)
1175 if(bin != center)
1176 scnptr[(viewNr-view)*binNr + binNr - 1 - bin] +=
1177 eps1 * imgptr[yn*imgDim + xp] +
1178 eps3 * imgptr[yn*imgDim + xp+1] +
1179 eps2 * imgptr[(yn+1)*imgDim + xp+1];
1180
1181 // Mirror the LOR on line y=x, i.e. y->x.
1182 // Case: pi/2 - theta.
1183 // Add img(y,x)*k to the raysum of LOR (viewNr/2-view,bin)
1184 scnptr[(viewNr/2 - view)*binNr + bin] +=
1185 eps1 * imgptr[xn*imgDim + yn] +
1186 eps3 * imgptr[xn*imgDim + yn-1] +
1187 eps2 * imgptr[(xn-1)*imgDim + (yn+1)];
1188 // Add img(-y,-x)*k to the raysum of LOR (viewNr/2-view,binNr-bin)
1189 if(bin != center)
1190 scnptr[(viewNr/2 - view)*binNr + binNr - 1 - bin] +=
1191 eps1 * imgptr[xp*imgDim + yp] +
1192 eps3*imgptr[(xp+1)*imgDim+yp] +
1193 eps2*imgptr[(xp+1)*imgDim+(yp-1)];
1194 }
1195
1196 // Mirror the LOR on line x=y, and on y-axis i.e x->y and y->-y.
1197 // Case: pi/2 + theta.
1198 // Add img(y,-x)*k to the raysum of LOR (viewNr/2+view,bin)
1199 scnptr[(viewNr/2 + view)*binNr + bin] +=
1200 eps1 * imgptr[xn*imgDim + yp] +
1201 eps3 * imgptr[(xn-1)*imgDim + yp] +
1202 eps2 * imgptr[(xn-1)*imgDim + (yp-1)];
1203 // Add img(-y,x)*k to the raysum of LOR (viewNr-view,binNr-bin)
1204 if(bin != center)
1205 scnptr[(viewNr/2 + view)*binNr + binNr - 1 - bin] +=
1206 eps1 * imgptr[xp*imgDim + yn] +
1207 eps3*imgptr[(xp+1)*imgDim+yn] +
1208 eps2*imgptr[(xp+1)*imgDim+yn+1];
1209 }
1210 }
1211 }
1212 }
1213 }
1214 }// END of X loop
1215 }// End of view>0.
1216 }// END OF VIEW LOOP
1217 free(X);
1218 free(Y);
1219 if( RADON_VERBOSE ){
1220 printf("RADON: radonFwdTransformEA() finished.\n");
1221 fflush(stdout);
1222 }
1223 return 0;
1224} // END OF EXACT AREA FORWARD TRANSFORM
1225/*****************************************************************************/
1239 RADON *radtra, int set, int setNr, float *imgdata, float *scndata
1240) {
1241 float *imgptr, *scnptr, *imgorigin;
1242 float sinus, cosinus;
1243 float t; // distance between projection ray and origo.
1244 int mode, imgDim, binNr, viewNr, halfImg, centerBin, view;
1245 int x, y, xright, ybottom;
1246 float fract, tpow2;
1247
1248 // Retrieve the data from given radon transform object.
1249 mode=radonGetMO(radtra); // Should be 3 or 4.
1250 imgDim=radonGetID(radtra);
1251 binNr=radonGetNB(radtra); // Should be equal to imgDim.
1252 viewNr=radonGetNV(radtra);
1253 // Set the center ray and the square of it.
1254 centerBin=binNr/2;
1255 tpow2 = centerBin*centerBin;
1256
1257 if(imgDim != binNr) return -1;
1258
1259 // Set half of the image dimension.
1260 halfImg = imgDim/2;
1261
1262 // Transform one angle at a time.
1263 for(view=set; view<viewNr; view+=setNr) {
1264
1265 imgorigin = imgdata + imgDim*(halfImg - 1) + halfImg;
1266
1267 sinus = radonGetSin(radtra,view);
1268 cosinus = radonGetSin(radtra,viewNr/2 + view);
1269
1270 y = halfImg - 2;
1271
1272 if((float)y > centerBin){
1273 y = (int)(centerBin);
1274 ybottom = -y;
1275 } else{
1276 ybottom = -halfImg + 1;
1277 }
1278
1279 for(; y >= ybottom; y--) {
1280 xright = (int)sqrt(/*fabs(*/tpow2 - ((float)y+0.5) *
1281 ((float)y+0.5)/*)*/) + 1;
1282 if(xright >= halfImg){
1283 xright = halfImg - 1;
1284 x = -halfImg;
1285 } else
1286 x = -xright;
1287
1289 // t = centerBin - (float)y * sinus + ((float)(x + 1)) * cosinus;
1290 t = centerBin + (float)y * sinus + ((float)(x + 1)) * cosinus;
1291
1292 imgptr = imgorigin - y*imgDim + x;
1293 scnptr = scndata + view*binNr;
1294 // for(; x <= xright; x++, t += cosinus){
1295 for(; x <= xright; x++, t += cosinus){
1296 if(mode == 3){ // If the linear interpolation is to be utilised.
1297 fract = t - (float)(int)t;
1298 *(scnptr+(int)t) += *imgptr * (1.0 - fract);
1299 *(scnptr+(int)t + 1) += *imgptr++ * fract;
1300 }
1301 else // If the nearest neighbour interpolation is to be utilised.
1302 *(scnptr+(int)(t + 0.5)) += *imgptr++;
1303 }
1304 }
1305 }
1306
1307 return 0;
1308}// END OF FORWARD TRANSFORM USING THE IMAGE ROTATION APPROACH
1309/*****************************************************************************/
1329 PRMAT *mat, int set, int setNr, float *imgdata, float *scndata
1330) {
1331 float *imgptr, *scnptr; // pointers for the image and sinogram data
1332 unsigned int imgDim=128, binNr=256, viewNr=192, view, bin, row, col;
1333 unsigned int half, center;
1334 int xp, xn, yp, yn;
1335 float fact;
1336
1337 // Retrieve the data from given projection matrix.
1338 imgDim=prmatGetID(mat);
1339 binNr=prmatGetNB(mat); // Should be equal to imgDim.
1340 viewNr=prmatGetNV(mat);
1341
1342 // Calculate and set the center bin.
1343 if((binNr%2) != 0){
1344 half = (binNr - 1)/2 + 1;
1345 center = half - 1;
1346 } else{
1347 half = binNr/2;
1348 // In the case binNr is even there is no center bin.
1349 center = -1;
1350 }
1351
1352 imgptr = imgdata;
1353 scnptr = scndata;
1354
1355 // Draw sinogram according to projection matrix.
1356 for(view=set; view<=viewNr/4; view=view+setNr){
1357 for(bin=0; bin<half; bin++){
1358 row = view*half + bin;
1359 for(col=0; col<prmatGetPixels(mat,row); col++){
1360
1361 fact = prmatGetFactor(mat,row,col);
1362 xp = prmatGetXCoord(mat,row,col);
1363 xn = imgDim - xp - 1;
1364
1365 yp = prmatGetYCoord(mat,row,col);
1366 yn = imgDim - yp - 1;
1367
1368 // Case: theta.
1369 // Add img(x,y)*k to the raysum of LOR (view,bin)
1370 scnptr[view*binNr + bin] += fact * imgptr[yp*imgDim + xp];
1371 // Add img(-x,-y)*k to the raysum of LOR (view,binNr-bin)
1372 if(bin != center)
1373 scnptr[view*binNr + binNr - 1 - bin] += fact * imgptr[yn*imgDim + xn];
1374
1375 if(view != 0 && view != viewNr/4){
1376 // Mirror the LOR on y-axis, i.e. x->-x
1377 // Case: pi-theta.
1378 // Add img(-x,y)*k to the raysum of LOR (viewNr-view,bin)
1379 scnptr[(viewNr - view)*binNr + bin] += fact * imgptr[yp*imgDim + xn];
1380 // Add img(x,-y)*k to the raysum of LOR (viewNr-view,binNr-bin)
1381 if(bin != center)
1382 scnptr[(viewNr-view)*binNr + binNr - 1 - bin] +=
1383 fact * imgptr[yn*imgDim + xp];
1384
1385 // Mirror the LOR on line y=x, i.e. y->x.
1386 // Case: pi/2 - theta.
1387 // Add img(y,x)*k to the raysum of LOR (viewNr/2-view,bin)
1388 scnptr[(viewNr/2 - view)*binNr + bin] += fact * imgptr[xn*imgDim + yn];
1389 // Add img(-y,-x)*k to the raysum of LOR (viewNr/2-view,binNr-bin)
1390 if(bin != center)
1391 scnptr[(viewNr/2 - view)*binNr + binNr - 1 - bin] +=
1392 fact * imgptr[xp*imgDim + yp];
1393 }
1394
1395 // Mirror the LOR on line x=y, and on y-axis i.e x->y and y->-y.
1396 // Case: pi/2 + theta.
1397 // Add img(y,-x)*k to the raysum of LOR (viewNr/2+view,bin)
1398 scnptr[(viewNr/2 + view)*binNr + bin] += fact * imgptr[xn*imgDim + yp];
1399 // Add img(-y,x)*k to the raysum of LOR (viewNr-view,binNr-bin)
1400 if(bin != center)
1401 scnptr[(viewNr/2 + view)*binNr + binNr - 1 - bin] +=
1402 fact * imgptr[xp*imgDim + yn];
1403 }
1404 }
1405 }
1406
1407 return 0;
1408
1409}// END OF FORWARD TRANSFORM WITH A PROJECTION MATRIX
1410/*****************************************************************************/
1411// BACK TRANSFORM METHODS
1412/*****************************************************************************/
1430 RADON *radtra, int set, int setNr, float *scndata, float *imgdata
1431) {
1432 float *imgptr, *scnptr; // pointers for the image and sinogram data
1433 float *Y, *X, *Xptr, *Yptr; // pointers for the values of LOR in integer points
1434 double sinus, cosinus, tanus; // sin, cosine and tangent
1435 double shift_x, shift_y; // shift for LOR
1436 int xp, xn, yp, yn, z; //integer points
1437 int x_left, x_right, y_top, y_bottom; // limits for fast search
1438 int col, row, view, bin; //counters
1439 int binNr, viewNr, imgDim;
1440 int half, center = -1, mode = 0;
1441 float sdist;
1442 float dx, dy , loi = 1; // delta x and y and length of intersection
1443
1444 //Check that the data for this radon transform is initialized
1445 if(radtra->status != RADON_STATUS_INITIALIZED) return -1;
1446
1447 //Retrieve the data from given radon transform object
1448 mode=radonGetMO(radtra);
1449 imgDim=radonGetID(radtra);
1450 binNr=radonGetNB(radtra);
1451 viewNr=radonGetNV(radtra);
1452 sdist=radonGetSD(radtra);
1453 half=radonGetHI(radtra);
1454 center=radonGetCB(radtra);
1455
1457 // Find pixel coordinates of the contributing pixels for lines of response
1458 // corresponding to first 1/4th of angles. From these pixel coordinates
1459 // others can be calculated via symmetries in projection space.
1460 // N.B. The line of response: a*x+b*y+c=cos(view)*x+sin(view)*y+k*bin=0
1461 // => solve y: y=-x*(cos(view)/sin(view)) - k*bin
1462 // solve x: x=-y*(sin(view)/cos(view))) - k*bin
1463
1464 X=(float*)calloc(imgDim+1,sizeof(float));
1465 Y=(float*)calloc(imgDim+1,sizeof(float));
1466 if(X==NULL || Y==NULL){
1467 return -2;
1468 }
1469 Xptr=X;
1470 Yptr=Y;
1471 imgptr=imgdata;
1472 scnptr=scndata;
1473 for(view=set; view<viewNr/4; view+=setNr){
1474 // Choose the type of the line of response according to view number
1475
1476 // Length of intersection is 1.
1477 loi = 1;
1478
1479 // 0. type: view=0 -> sin(view)=0
1480 if(view==0){
1481
1482 // Choose the pixels according to sample distance and pixel size,
1483 // for angles 0 and pi/2.
1484 for(bin=0; bin<binNr; bin++){
1485 col=floor((float)(bin+.5*sdist)*sdist);
1486 if(col==imgDim) col=imgDim-1;
1487
1488 // Iterate through the entries in the image matrix.
1489 // Calculate raysums for LORs in the same (absolute) distance from origin.
1490 for(row=0; row<imgDim; row++){
1491 imgptr[row*imgDim + col] += loi*scnptr[bin];
1492 imgptr[(imgDim - 1 - col)*imgDim + row] +=
1493 loi*scnptr[binNr*(viewNr/2) + bin];
1494 }
1495 }
1496 // End of view==0 (handles angles 0 and pi/2).
1497 } else {
1498 // Set sine and cosine for this angle.
1499 sinus=(double)radonGetSin(radtra,view);
1500 cosinus=(double)radonGetSin(radtra,viewNr/2 + view);
1501 tanus=sinus/cosinus;
1502
1504 // Set shift from origin for the first line of response (-n/2,theta).
1505 // NOTE that image matrix is on cartesian coordinate system where origin
1506 // is in the middle and shift is in pixels.
1507 shift_y = -(imgDim/2 -.5*sdist)/sinus;
1508 shift_x = -(imgDim/2 -.5*sdist)/cosinus;
1509
1510 // Evaluate the function of the first LOR in integer points [-n/2,n/2].
1511 // NOTE that image matrix is on cartesian coordinate system where origin
1512 // is in the middle.
1513 z=-imgDim/2;
1514 for(col=0; col<imgDim+1; col++){
1515 Yptr[col]=(float)(shift_y - z/tanus);
1516 Xptr[col]=(float)(shift_x - z*tanus);
1517 z++;
1518 }
1519
1520 // Set shift from the first LOR.
1521 shift_y = (double)(sdist/sinus);
1522 shift_x = (double)(sdist/cosinus);
1523
1524 // Iterate through half the bins in this view,
1525 // and determine coordinates of pixels contributing to this LOR.
1526 // NOTE that shift is added according to 'bin' in every loop.
1527 // Calculate also the length of intersection.
1528 // Others are determined via symmetry in projection space.
1529
1530 for(bin=0; bin<half; bin++){
1531
1532 // Limit (x-)indices for fast search.
1533 // Note that indices are non-negative integers.
1534
1535 x_left = floor((float)((Xptr[imgDim] + bin*shift_x) + imgDim/2));
1536 if(x_left < 0) x_left = 0;
1537 x_right = floor((float)((Xptr[0] + bin*shift_x) + imgDim/2));
1538 if(x_right <= 0) x_right = 1;
1539 if(x_right > imgDim) x_right = imgDim - 1;
1540
1541 /* Iterate through the values in vector Y, in integer points
1542 [x_left,x_rigth]. */
1543 for(z=x_left; z <= x_right; z++){
1544
1545 xp = z; //positive x-coordinate
1546 xn = imgDim - 1 - xp; //negative x-coordinate
1547
1548 // Look y from left.
1549 yp = imgDim/2 - floor(Yptr[xp + 1] + bin*shift_y) - 1;
1550 yn = imgDim - 1 - yp;
1551
1552 // If the y-value for this x (z) is inside the image grid.
1553 if(yp < imgDim && yp >= 0 && yn < imgDim && yn >= 0 && xp >= 0 &&
1554 xp < imgDim && xn < imgDim && xn >= 0)
1555 {
1556 if(!mode){
1557 loi = 1;
1558 } else {
1559 // Compute delta x and y from 'positive' coordinates.
1560 dx = 1 - (float)((Xptr[imgDim - yp] + bin*shift_x) + imgDim/2 - xp);
1561 dy = 1 - (float)(yp - (imgDim/2 - (Yptr[xp + 1] + bin*shift_y) - 1));
1562
1563 if(dx > 1 || dx < 0) dx = 1;
1564 if(dy > 1 || dy < 0) dy = 1;
1565 loi = sqrt(dx*dx + dy*dy);
1566 }
1567
1568 // Case: theta.
1569 // Add img(x,y)*k to the raysum of LOR (view,bin)
1570 imgptr[yp*imgDim + xp] += loi*scnptr[view*binNr + bin];
1571 // Add img(-x,-y)*k to the raysum of LOR (view,binNr-bin)
1572 if(bin != center)
1573 imgptr[yn*imgDim + xn] +=
1574 loi*scnptr[view*binNr + binNr - 1 - bin];
1575
1576 if(view != viewNr/4){
1577 // Mirror the original LOR on y-axis, i.e. x->-x
1578 // Case: pi-theta.
1579 // Add img(-x,y)*k to the raysum of LOR (viewNr-view,bin)
1580 imgptr[yp*imgDim + xn] += loi*scnptr[(viewNr - view)*binNr + bin];
1581 // Add img(x,-y)*k to the raysum of LOR (viewNr-view,binNr-bin)
1582 if(bin != center)
1583 imgptr[yn*imgDim + xp] +=
1584 loi*scnptr[(viewNr-view)*binNr + binNr - 1 - bin];
1585
1586 // Mirror the LOR on line x=y, i.e. x->y.
1587 // Case: pi/2-theta
1588 // Add img(-y,-x)*k to the raysum of LOR (viewNr/2-view,bin)
1589 imgptr[xn*imgDim + yn] += loi*scnptr[(viewNr/2 - view)*binNr + bin];
1590 // Add img(y,x)*k to the raysum of LOR (viewNr/2-view,binNr-bin)
1591 if(bin != center)
1592 imgptr[xp*imgDim + yp] +=
1593 loi*scnptr[(viewNr/2 - view)*binNr + binNr - 1 - bin];
1594 }
1595
1596 // Mirror the LOR on line x=y, and on y-axis i.e x->y and y->-y.
1597 // Case: pi/2+theta
1598 // Add img(y,-x)*k to the raysum of LOR (viewNr/2+view,bin)
1599 imgptr[xn*imgDim + yp] += loi*scnptr[(viewNr/2 + view)*binNr + bin];
1600 // Add img(y,-x)*k to the raysum of LOR (viewNr/2+view,binNr-bin)
1601 if(bin != center)
1602 imgptr[xp*imgDim + yn] +=
1603 loi*scnptr[(viewNr/2 + view)*binNr + binNr - 1 - bin];
1604
1605 }
1606 }
1607
1608 // Limit (y-)indices for fast search.
1609 // Note that indices are non-negative integers.
1610 y_bottom = floor((float)(Yptr[imgDim] + bin*shift_y + imgDim/2));
1611 if(y_bottom < 0) y_bottom = 0;
1612 if(y_bottom > imgDim) y_bottom = 0;
1613
1614 y_top = floor((float)(Yptr[0] + bin*shift_y + imgDim/2));
1615 if(y_top > imgDim) y_top = imgDim;
1616 if(y_top <= 0) y_top = 1;
1617
1618 /* Iterate through the values in vector X, in integer points
1619 [y_bottom,y_top]. */
1620 for(z=y_top; z >= y_bottom; z--) {
1621
1622 // Look y from this location.
1623 xp = floor(Xptr[z] + bin*shift_x) + imgDim/2;
1624 xn = imgDim - 1 - xp;
1625
1626 yp = imgDim - z - 1;
1627 yn = imgDim - yp - 1;
1628
1629 // If the x-value for this y (z) is inside the image grid.
1630 if(yp < imgDim && yp >= 0 && yn < imgDim && yn >= 0 && xp >= 0 &&
1631 xp < imgDim && xn < imgDim && xn >= 0)
1632 {
1633 if(!mode){
1634 loi = 1;
1635 } else{
1636 dx = (float)((Xptr[z] + bin*shift_x) + imgDim/2 - xp);
1637 dy = (float)(yp - (imgDim/2 - (Yptr[xp] + bin*shift_y) - 1));
1638 if(dy > 1 || dy < 0) dy = 1;
1639 loi = sqrt(dx*dx + dy*dy);
1640 }
1641 // Case: theta.
1642 // Add img(x,y)*k to the raysum of LOR (view,bin)
1643 imgptr[yp*imgDim + xp] += loi*scnptr[view*binNr + bin];
1644 // Add img(-x,-y)*k to the raysum of LOR (view,binNr-bin)
1645 if(bin != center)
1646 imgptr[yn*imgDim + xn] +=
1647 loi*scnptr[view*binNr + binNr - 1 - bin];
1648
1649 if(view != viewNr/4){
1650 // Mirror the LOR on y-axis, i.e. x->-x
1651 // Case: pi-theta.
1652 // Add img(-x,y)*k to the raysum of LOR (viewNr-view,bin)
1653 imgptr[yp*imgDim + xn] += loi*scnptr[(viewNr - view)*binNr + bin];
1654 // Add img(x,-y)*k to the raysum of LOR (viewNr-view,binNr-bin)
1655 if(bin != center)
1656 imgptr[yn*imgDim + xp] +=
1657 loi*scnptr[(viewNr-view)*binNr + binNr - 1 - bin];
1658
1659 // Mirror the LOR on line y=x, i.e. y->x.
1660 // Case: pi/2 - theta.
1661 // Add img(y,x)*k to the raysum of LOR (viewNr/2-view,bin)
1662 imgptr[xn*imgDim + yn] += loi*scnptr[(viewNr/2 - view)*binNr + bin];
1663 // Add img(-y,-x)*k to the raysum of LOR (viewNr/2-view,binNr-bin)
1664 if(bin != center)
1665 imgptr[xp*imgDim + yp] +=
1666 loi*scnptr[(viewNr/2 - view)*binNr + binNr - 1 - bin];
1667 }
1668
1669 // Mirror the LOR on line x=y, and on y-axis i.e x->y and y->-y.
1670 // Case: pi/2 + theta.
1671 // Add img(y,-x)*k to the raysum of LOR (viewNr/2+view,bin)
1672 imgptr[xn*imgDim + yp] += loi*scnptr[(viewNr/2 + view)*binNr + bin];
1673 // Add img(-y,x)*k to the raysum of LOR (viewNr-view,binNr-bin)
1674 if(bin != center)
1675 imgptr[xp*imgDim + yn] +=
1676 loi*scnptr[(viewNr/2 + view)*binNr + binNr - 1 - bin];
1677 }
1678 }
1679 } // END of X loop
1680 } // End of view>0.
1681 } // END OF VIEW LOOP
1682 free(X);
1683 free(Y);
1684 return 0;
1685} // END OF BACK (pro -> spa) TRANSFORM WITH 0/1 OR LOI-MODEL.
1686/*****************************************************************************/
1697 RADON *radtra, int set, int setNr, float *scndata, float *imgdata
1698) {
1699 float *imgptr, *scnptr; // pointers for the image and sinogram data
1700 float *Y, *X, *Xptr, *Yptr; // pointers for the values of LOR in integer points
1701 double sinus, cosinus, tanus; // sin, cosine and tangent
1702 double shift_x, shift_y; // shift for LOR
1703 int xp, xn, yp, yn, z, xp2; //integer points
1704 int x_left, x_right, y_top, y_bottom; // limits for fast search
1705 int col, col1, col2, row, view, bin; //counters
1706 int binNr, viewNr, imgDim, errors=0;
1707 int half, center = -1;
1708 float sdist;
1709 float a=0,b=0, c=0, d=0, g=0, h=0, A;
1710 float dx, dy , eps1 = 0, eps2 = 0, eps3 = 0; // delta x and y and factors.
1711
1712 // Check that the data for this radon transform is initialized.
1713 if(radtra->status != RADON_STATUS_INITIALIZED) return -1;
1714
1715 // Retrieve the data from given radon transform object.
1716 //mode=radonGetMO(radtra); // Should be 2.
1717 imgDim=radonGetID(radtra);
1718 binNr=radonGetNB(radtra);
1719 viewNr=radonGetNV(radtra);
1720 sdist=radonGetSD(radtra);
1721 half=radonGetHI(radtra);
1722 center=radonGetCB(radtra);
1723
1724 // Array for storing values f_x.
1725 X=(float*)calloc(imgDim+1,sizeof(float));
1726 // Array for storing values f_y.
1727 Y=(float*)calloc(imgDim+1,sizeof(float));
1728 if(X==NULL || Y==NULL){
1729 return -2;
1730 }
1731 Xptr=X;
1732 Yptr=Y;
1733
1734 imgptr=imgdata;
1735 scnptr=scndata;
1736
1738 // Find pixel coordinates of the contributing pixels for tubes of response
1739 // belonging to first 1/4th of angles. From these pixel coordinates
1740 // others can be calculated via symmetries in projection space.
1741 // N.B. The line of response: a*x+b*y+c
1742 // => solve y: y=-x/tan(view) + s*(cos(theta)/tan(theta) + sin(theta))
1743 // solve x: x=-y*tan(theta) + s*(sin(theta)*tan(theta) + cos(theta))
1744
1745 for(view=set; view<=viewNr/4; view+=setNr){
1746 // view=0 -> sin(theta)=0
1747 if(view==0){
1748
1749 // Choose column(s) according to sample distance for angles 0 and pi/2.
1750 col1 = 0;
1751 col2 = 0;
1752 for(bin = 0; bin < half; bin++){
1753
1754 col1 = col2;
1755 col2 = floor((float)(bin + 1)*sdist);
1756
1757 // Determine factor epsilon.
1758 if(col1 == col2){
1759 eps1 = sdist;
1760 eps2 = 0;
1761 eps3 = 0;
1762 }
1763 if((col2-col1) == 1){
1764 eps1 = (float)(col2 - (bin)*sdist);
1765 eps2 = 0;
1766 eps3 = (float)((bin+1)*sdist - col2);
1767
1768 }
1769 // If sdist > pixel size!
1770 if((col2-col1) > 1){
1771 eps1 = (float)(col1 + 1 - (bin)*sdist);
1772 eps2 = 1; // middle pixel.
1773 eps3 = (float)((bin+1)*sdist - col2);
1774
1775 }
1776
1777 /* Iterate through the entries in the image matrix.
1778 Calculate raysums for two LORs in the same distance from origin
1779 (do halfturn). */
1780 for(row=0; row<imgDim; row++){
1781 if(!eps3){
1782 imgptr[row*imgDim + col1] += eps1 * scnptr[bin];
1783 if(bin != center)
1784 imgptr[row*imgDim + (imgDim - 1 - col1)]+=
1785 eps1 * scnptr[binNr-bin-1] ;
1786 imgptr[(imgDim - 1 - col1)*imgDim + row] +=
1787 eps1 * scnptr[binNr*(viewNr/2) + bin];
1788 if(bin != center)
1789 imgptr[col1*imgDim + row]+=
1790 eps1 * scnptr[binNr*(viewNr/2) + (binNr-bin-1)];
1791 }
1792 if(eps3 && !eps2){
1793 imgptr[row*imgDim + col1] += eps1 * scnptr[bin];
1794 imgptr[row*imgDim + col2] += eps3 *scnptr[bin];
1795 if(bin != center){
1796 imgptr[row*imgDim + (imgDim - 1 - col1)] +=
1797 eps1 * scnptr[binNr-bin-1];
1798 imgptr[row*imgDim+(imgDim-1-col2)] +=
1799 eps3*scnptr[binNr-bin-1];
1800 }
1801
1802 imgptr[(imgDim-1-col1)*imgDim+row] +=
1803 eps1* scnptr[binNr*(viewNr/2) + bin];
1804 imgptr[(imgDim-1-col2)*imgDim+row] +=
1805 eps3*scnptr[binNr*(viewNr/2) + bin];
1806 if(bin != center){
1807 imgptr[col1*imgDim + row] +=
1808 eps1 * scnptr[binNr*(viewNr/2) + (binNr-bin-1)];
1809 imgptr[col2*imgDim + row] +=
1810 eps3 *scnptr[binNr*(viewNr/2) + (binNr-bin-1)];
1811 }
1812 }
1813 if(eps3 && eps2){
1814 for(col = col1; col<=col2; col++){
1815 if(col == col1){
1816 imgptr[row*imgDim + col1]+= eps1 * scnptr[bin];
1817 if(bin != center)
1818 imgptr[row*imgDim + (imgDim - 1 - col1)]+=
1819 eps1 * scnptr[binNr-bin-1] ;
1820 imgptr[(imgDim - 1 - col1)*imgDim + row]+=
1821 eps1 * scnptr[binNr*(viewNr/2) + bin];
1822 if(bin != center)
1823 imgptr[col1*imgDim + row]+=
1824 eps1 * scnptr[binNr*(viewNr/2) + (binNr-bin-1)];
1825 }
1826 if(col == col2){
1827 imgptr[row*imgDim + col2]+= eps3 * scnptr[bin];
1828 if(bin != center)
1829 imgptr[row*imgDim + (imgDim - 1 - col2)]+=
1830 eps3 * scnptr[binNr-bin-1];
1831 imgptr[(imgDim - 1 - col2)*imgDim + row]+=
1832 eps3 * scnptr[binNr*(viewNr/2) + bin];
1833 if(bin != center)
1834 imgptr[col2*imgDim + row]+=
1835 eps3 * scnptr[binNr*(viewNr/2) + (binNr-bin-1)];
1836 }
1837 if(col != col1 && col != col2){
1838 imgptr[row*imgDim + col]+= eps2 * scnptr[bin] ;
1839 if(bin != center)
1840 imgptr[row*imgDim + (imgDim - 1 - col)]+=
1841 eps2 * scnptr[binNr-bin-1];
1842 imgptr[(imgDim - 1 - col)*imgDim + row]+=
1843 eps2 * scnptr[binNr*(viewNr/2) + bin];
1844 if(bin != center)
1845 imgptr[col*imgDim + row]+=
1846 eps2 * scnptr[binNr*(viewNr/2) + (binNr-bin-1)];
1847 }
1848 }
1849 }
1850 }
1851 }
1852 // End of view==0 (handles angles 0 and pi/2).
1853 } else {
1854
1855 // Set sine and cosine for this angle.
1856 sinus = (double)radonGetSin(radtra,view);
1857 cosinus = (double)radonGetSin(radtra,viewNr/2 + view);
1858 tanus = sinus/cosinus;
1859
1860 // Set shift from origin for the first line of response (-n/2,theta).
1861 // NOTE that image matrix is on cartesian coordinate system where origin
1862 // is in the middle and shift is in pixels.
1863 shift_y = -(imgDim/2)/sinus;
1864 shift_x = -(imgDim/2)/cosinus;
1865
1866 // Evaluate the function of the first LOR in integer points [-n/2,n/2].
1867 // NOTE that image matrix is on cartesian coordinate system where origin
1868 // is in the middle.
1869 z=-imgDim/2;
1870 for(col=0; col<imgDim+1; col++){
1871 Yptr[col]=(float)(-z/tanus + shift_y);
1872 Xptr[col]=(float)(-z*tanus + shift_x);
1873 z++;
1874 }
1875
1876 // Set shift from the first LOR.
1877 shift_y = (double)(sdist/sinus);
1878 shift_x = (double)(sdist/cosinus);
1879
1880 // Iterate through half the bins in this view,
1881 // and determine coordinates of pixels contributing to this LOR.
1882 // NOTE that shift is added according to 'bin' in every loop.
1883 // Calculate also the length of intersection.
1884 // Others are determined via symmetry in projection space.
1885
1886 for(bin=0; bin<half; bin++){
1887
1888 // Limit (x-)indices for fast search.
1889 // Note that indices are non-negative integers.
1890
1891 x_left = floor((float)(Xptr[imgDim] + bin*shift_x + imgDim/2));
1892 if(x_left < 0) x_left = 0;
1893
1894 x_right = floor((float)(Xptr[0] + bin*shift_x + imgDim/2));
1895 if(x_right <= 0) x_right = 1;
1896 if(x_right > imgDim) x_right = imgDim - 1;
1897
1898 /* Iterate through the values in vector Y, in integer points
1899 [x_left,x_rigth]. */
1900 for(z=x_left; z <= x_right; z++) {
1901
1902 xp = z; //positive x-coordinate
1903 xn = imgDim - 1 - xp; //negative x-coordinate
1904
1905 // Look y from left.
1906 yp = imgDim/2 - floor(Yptr[xp + 1] + bin*shift_y) - 1;
1907 yn = imgDim - 1 - yp;
1908
1909 // If the y-value for this x (z) is inside the image grid.
1910 if(yp < imgDim && yp >= 0 && yn < imgDim && yn >= 0 && xp >= 0 &&
1911 xp < imgDim && xn < imgDim && xn >= 0)
1912 {
1913
1914 // NOTE that pixels found in this part are always hit from right side.
1915 // Compute a := |AF| and b := |FB|.
1916 a = (float)(xp + 1 - (imgDim/2 + Xptr[imgDim - yp] + bin*shift_x));
1917 b = (float)(floor(Yptr[xp + 1] + bin*shift_y) + 1 - (Yptr[xp + 1] +
1918 bin*shift_y));
1919
1920 // Calculate the area of lower triangle.
1921 A = a*b/2;
1922
1923 // c := |FC|
1924 c = (float)(xp + 1 - (imgDim/2 + Xptr[imgDim - yp] +
1925 (bin+1)*shift_x));
1926
1927 if(c > 0){
1928 // d := |FD|
1929 d = (float)(floor(Yptr[xp + 1] + (bin+1)*shift_y) + 1 -
1930 (Yptr[xp + 1] + (bin+1)*shift_y));
1931 // Subtract the area of upper triangle.
1932 A = A - c*d/2;
1933 }
1934
1935 eps1 = A;
1936 if((eps1 < 0 || eps1 > 1) && RADON_VERBOSE){
1937 printf("RADON: Error in factor: eps1=%.5f \n",eps1);
1938 errors++;
1939 }
1940
1941 // Case: theta.
1942 // Add img(x,y)*k to the raysum of TOR (view,bin)
1943 imgptr[yp*imgDim + xp]+= eps1 * scnptr[view*binNr + bin];
1944 // Add img(-x,-y)*k to the raysum of LOR (view,binNr-bin)
1945 if(bin != center)
1946 imgptr[yn*imgDim + xn]+=
1947 eps1 * scnptr[view*binNr + binNr - 1 - bin];
1948
1949 if(view != viewNr/4){
1950 // Mirror the original LOR on y-axis, i.e. x->-x
1951 // Case: pi-theta.
1952 // Add img(-x,y)*k to the raysum of LOR (viewNr-view,bin)
1953 imgptr[yp*imgDim + xn]+=
1954 eps1 * scnptr[(viewNr - view)*binNr + bin];
1955 // Add img(x,-y)*k to the raysum of LOR (viewNr-view,binNr-bin)
1956 if(bin != center)
1957 imgptr[yn*imgDim + xp]+=
1958 eps1 * scnptr[(viewNr-view)*binNr + binNr - 1 - bin];
1959
1960 // Mirror the LOR on line x=y, i.e. x->y.
1961 // Case: pi/2-theta
1962 // Add img(-y,-x)*k to the raysum of LOR (viewNr/2-view,bin)
1963 imgptr[xn*imgDim + yn]+=
1964 eps1 * scnptr[(viewNr/2 - view)*binNr + bin];
1965 // Add img(y,x)*k to the raysum of LOR (viewNr/2-view,binNr-bin)
1966 if(bin != center)
1967 imgptr[xp*imgDim + yp]+=
1968 eps1 * scnptr[(viewNr/2 - view)*binNr + binNr - 1 - bin];
1969 }
1970
1971 // Mirror the LOR on line x=y, and on y-axis i.e x->y and y->-y.
1972 // Case: pi/2+theta
1973 // Add img(y,-x)*k to the raysum of LOR (viewNr/2+view,bin)
1974 imgptr[xn*imgDim + yp]+= eps1 * scnptr[(viewNr/2 + view)*binNr + bin];
1975 // Add img(y,-x)*k to the raysum of LOR (viewNr/2+view,binNr-bin)
1976 if(bin != center)
1977 imgptr[xp*imgDim + yn]+=
1978 eps1 * scnptr[(viewNr/2 + view)*binNr + binNr - 1 - bin];
1979 }
1980 }
1981
1982 // Limit (y-)indices for fast search.
1983 // Note that indices are non-negative integers.
1984 y_bottom = floor((float)(Yptr[imgDim] + bin*shift_y + imgDim/2));
1985 if(y_bottom < 0) y_bottom = 0;
1986 if(y_bottom > imgDim) y_bottom = 0;
1987
1988 y_top = floor((float)(Yptr[0] + bin*shift_y + imgDim/2));
1989 if(y_top > imgDim) y_top = imgDim;
1990 if(y_top <= 0) y_top = 1;
1991
1992 // Iterate through the values in vector X, in integer points [y_bottom,y_top].
1993 for(z=y_top; z >= y_bottom; z--) {
1994
1995 // Look y from this location.
1996 xp = floor(Xptr[z] + bin*shift_x) + imgDim/2;
1997 xn = imgDim - 1 - xp;
1998
1999 yp = imgDim - z - 1;
2000 yn = imgDim - yp - 1;
2001
2002 // If the x-value for this y (z) is inside the image grid.
2003 if(yp < imgDim && yp >= 0 && yn < imgDim && yn >= 0 && xp >= 0
2004 && xp < imgDim && xn < imgDim && xn >= 0)
2005 {
2006 eps1=eps2=eps3=0;
2007
2008 dx = (float)(Xptr[z] + bin*shift_x + imgDim/2 - xp);
2009 dy = (float)(Yptr[xp] + bin*shift_y - z + imgDim/2);
2010
2011 if(dy < 1){ // Cases 3,4,5 and 6.
2012 // 1. PART
2013 // a := |HA|
2014 a = dy;
2015 // b := |HB| (b < 1 for angles in [0,pi/4))
2016 b = dx;
2017 // h := height of rectangle R.
2018 h = a + shift_y;
2019 if(h > 1){ // Cases 3,4 and 5.
2020 h = 1;
2021 g = b + shift_x;
2022 if(g > 1){ // Cases 3 and 4.
2023 g = 1;
2024 xp2 =floor(Xptr[z+1] + (bin+1)*shift_x) + imgDim/2;
2025 if(xp == xp2){ // Case 4.
2026 // c := |FC|
2027 c = (float)(xp + 1 - (imgDim/2 + Xptr[z+1] + (bin+1)*shift_x));
2028 // d := |FD|
2029 d = (float)(floor(Yptr[xp + 1] + (bin+1)*shift_y) + 1 -
2030 (Yptr[xp + 1] + (bin+1)*shift_y));
2031 eps1 = 1 - (a*b + c*d)/2;
2032 eps2 = 0;
2033 // Lower triangle on the next pixel (x+1,y).
2034 eps3 = (1 - d)*(b + shift_x - 1)/2;
2035 if((eps1<0 || eps1>1 || eps2<0 || eps2>1 || eps3<0 || eps3>1)
2036 && RADON_VERBOSE) printf(
2037 "4: (%i,%i) eps1=%f | (%i,%i) eps2=%f | (%i,%i) eps3=%f\n",
2038 xp,yp,eps1,xp+1,yp-1,eps2,xp+1,yp,eps3);
2039 } else{ // Case 3.
2040 // c=d=0.
2041 eps1 = 1 - a*b/2;
2042 // Calculate area on pixel in place (xp+1,yp-1).
2043 dy = (float)(Yptr[xp+1] + (bin+1)*shift_y - (z + 1) +
2044 imgDim/2);
2045 if(dy < 1){ // Case 11.
2046 // c := |HC|
2047 c = dy;
2048 // d := |HD|
2049 d = (float)(xp + 2 - (imgDim/2 + Xptr[z+1] +
2050 (bin+1)*shift_x));
2051 eps2 = c*d/2;
2052 } else { // Cases 9 and 10.
2053
2054 dx = (float)(xp + 2 - (imgDim/2 + Xptr[z+1] +
2055 (bin+1)*shift_x));
2056 if(dx < 1) { // Case 10.
2057 // g := length of rectangle Q.
2058 g = dx;
2059 // c := |CD| (on x-axis).
2060 c = dx - (float)(xp + 2 - (imgDim/2 + Xptr[z+2] +
2061 (bin+1)*shift_x));
2062 // Rectangle Q - triangle c*h (h = 1).
2063 eps2 = g - c/2;
2064 } else { // Case 9.
2065 // c := |FC|
2066 c = (float)(xp + 2 - (imgDim/2 + Xptr[z+2] +
2067 (bin+1)*shift_x));
2068 // d := |FD|
2069 d = (float)(floor(Yptr[xp + 2] + (bin+1)*shift_y) + 2 -
2070 (Yptr[xp + 2] + (bin+1)*shift_y));
2071 // Rectangle Q - triangle CFD.
2072 eps2 = 1 - c*d/2;
2073 }
2074 }
2075 // Calculate area on pixel in place (xp+1,yp).
2076 dx = (float)(xp + 2 - (imgDim/2 + Xptr[z] + (bin+1)*shift_x));
2077 if(dx < 1){ // Case 10.
2078 // g := length of rectangle Q.
2079 g = dx;
2080 // c := |CD| (on x-axis).
2081 c = dx - (float)(xp + 2 - (imgDim/2 + Xptr[z+1] +
2082 (bin+1)*shift_x));
2083 // Rectangle Q - triangle c*h (h = 1).
2084 eps3 = g - c/2;
2085 } else { // Case 9.
2086 // c := |FC|
2087 c = (float)(xp + 2 - (imgDim/2 + Xptr[z+1] +
2088 (bin+1)*shift_x));
2089 // d := |FD|
2090 d = (float)(floor(Yptr[xp + 2] + (bin+1)*shift_y) + 1 -
2091 (Yptr[xp + 2] + (bin+1)*shift_y));
2092 // Rectangle Q - triangle CFD.
2093 eps3 = 1 - c*d/2;
2094 }
2095 if((eps1<0 || eps1>1 || eps2<0 || eps2>1 || eps3<0 || eps3>1)
2096 && RADON_VERBOSE) printf(
2097 "3/v%i: (%i,%i) eps1=%f | (%i,%i) eps2=%f | (%i,%i) eps3=%f\n",
2098 view,xp,yp,eps1,xp+1,yp-1,eps2,xp+1,yp,eps3);
2099 }
2100 } else{ // Case 5. (g < 1)
2101 // c := |DC|.
2102 c = g - (imgDim/2 + Xptr[z+1] + (bin+1)*shift_x - xp);
2103 // d := heigth
2104 d = 1;
2105 eps1 = g*h - (a*b + c*d)/2;
2106 eps2 = 0;
2107 eps3 = 0;
2108 if((eps1<0 || eps1>1 || eps2<0 || eps2>1 || eps3<0 || eps3>1)
2109 && RADON_VERBOSE) printf(
2110 "5: (%i,%i) eps1=%f | (%i,%i) eps2=%f | (%i,%i) eps3=%f\n",
2111 xp,yp,eps1,xp+1,yp-1,eps2,xp+1,yp,eps3);
2112 }
2113 } else { // Case 6 (h <= 1).
2114 // g := legth of rectangle R
2115 g = b + shift_x;
2116 if(g > 1) // Should always be < 1 for angles in [0,pi/4)
2117 g = 1;
2118 eps1 = (g*h - a*b)/2;
2119 eps2 = 0;
2120 eps3 = 0;
2121 if((eps1<0 || eps1>1 || eps2<0 || eps2>1 || eps3<0 || eps3>1) &&
2122 RADON_VERBOSE) printf(
2123 "6: (%i,%i) eps1=%f | (%i,%i) eps2=%f | (%i,%i) eps3=%f\n",
2124 xp,yp,eps1,xp+1,yp-1,eps2,xp+1,yp,eps3);
2125 }
2126 } else { // 2. PART
2127 // Cases 2,7 and 8. (dy >= 1).
2128 // a := |HA|
2129 a = 1;
2130 // b := |HB| (>=1)
2131 b = dx - (float)(Xptr[z+1] + bin*shift_x + imgDim/2 - xp);
2132 // h := heigth of rectangle R
2133 h = 1;
2134 // g := length of rectangle R
2135 g = dx + shift_x;
2136 if(g > 1){ // Cases 2 and 8.
2137 g = 1 - (float)(Xptr[z+1] + bin*shift_x + imgDim/2 - xp);
2138 // positive x-coordinate (bin+1)
2139 xp2 = floor(Xptr[z+1] + (bin+1)*shift_x) + imgDim/2;
2140 if(xp == xp2){ // Case 8.
2141 // c := |FC|
2142 c = (float)(xp + 1 - (imgDim/2 + Xptr[z+1] + (bin+1)*shift_x));
2143 // d := |FD|
2144 d = (float)(floor(Yptr[xp + 1] + (bin+1)*shift_y) + 1 -
2145 (Yptr[xp + 1] + (bin+1)*shift_y));
2146
2147 eps1 = g*h - (a*b + c*d)/2;
2148 eps2 = 0;
2149 // Lower triangle on the next pixel (x+1,y).
2150 eps3 = (1 - d)*((Xptr[z] + (bin+1)*shift_x + imgDim/2) -
2151 (xp+1))/2;
2152 if((eps1<0 || eps1>1 || eps2<0 || eps2>1 || eps3<0 || eps3>1)
2153 && RADON_VERBOSE) printf(
2154 "8: (%i,%i) eps1=%f | (%i,%i) eps2=%f | (%i,%i) eps3=%f\n",
2155 xp,yp,eps1,xp+1,yp-1,eps2,xp+1,yp,eps3);
2156 } else { // Case 2.
2157 // c=d=0.
2158 eps1 = g*h - a*b/2;
2159
2160 /* Pixel in place (xp+1,yp-1) should have been found in
2161 the previous step. */
2162 eps2 = 0;
2163
2164 // Calculate area on pixel in place (xp+1,yp).
2165
2166 dx = (float)((imgDim/2 + Xptr[z] + (bin+1)*shift_x) - (xp+1));
2167 if(dx < 1){ // Case 10 (trapezium).
2168 // g := bottom of trapezium Q.
2169 g = dx;
2170 // c := top of trapezium Q.
2171 c = (float)((imgDim/2 + Xptr[z+1] + (bin+1)*shift_x) -
2172 (xp+1));
2173 // Area of trapezium Q. Heigth = 1.
2174 eps3 = (g + c)/2;
2175 if((eps1<0 || eps1>1 || eps2<0 || eps2>1 || eps3<0 ||
2176 eps3>1) && RADON_VERBOSE) printf(
2177 "2/10: (%i,%i) eps1=%f | (%i,%i) eps2=%f | (%i,%i) eps3=%f\n",
2178 xp,yp,eps1,xp+1,yp-1,eps2,xp+1,yp,eps3);
2179 } else { // Case 9.
2180 // c := |FC|
2181 c = (float)(xp + 2 - (imgDim/2 + Xptr[z+1] +
2182 (bin+1)*shift_x));
2183 // d := |FD|
2184 d = (float)(floor(Yptr[xp + 2] + (bin+1)*shift_y) + 1 -
2185 (Yptr[xp + 2] + (bin+1)*shift_y));
2186 // Rectangle Q - triangle CFD.
2187 eps3 = 1 - c*d/2;
2188 if((eps1<0 || eps1>1 || eps2<0 || eps2>1 || eps3<0 ||
2189 eps3>1) && RADON_VERBOSE) printf(
2190 "2/9: (%i,%i) eps1=%f | (%i,%i) eps2=%f | (%i,%i) eps3=%f\n",
2191 xp,yp,eps1,xp+1,yp-1,eps2,xp+1,yp,eps3);
2192 }
2193 }
2194 } else { // Case 7. (g < = 1)
2195
2196 // Area of the parallelogram R.
2197 eps1 = sdist/cosinus;
2198 eps2 = 0;
2199 eps3 = 0;
2200 if((eps1<0 || eps1>1 || eps2<0 || eps2>1 || eps3<0 || eps3>1) &&
2201 RADON_VERBOSE) printf(
2202 "7: (%i,%i) eps1=%f | (%i,%i) eps2=%f | (%i,%i) eps3=%f\n",
2203 xp,yp,eps1,xp+1,yp-1,eps2,xp+1,yp,eps3);
2204 }
2205 }
2206 if(!eps2 && !eps3) { // Cases 5,6 and 7.
2207 // Case: theta.
2208 // Add img(x,y)*k to the raysum of LOR (view,bin)
2209 imgptr[yp*imgDim + xp]+= eps1 * scnptr[view*binNr + bin];
2210 // Add img(-x,-y)*k to the raysum of LOR (view,binNr-bin)
2211 if(bin != center)
2212 imgptr[yn*imgDim + xn]+=
2213 eps1 * scnptr[view*binNr + binNr - 1 - bin];
2214
2215 if(view != viewNr/4) {
2216 // Mirror the LOR on y-axis, i.e. x->-x
2217 // Case: pi-theta.
2218 // Add img(-x,y)*k to the raysum of LOR (viewNr-view,bin)
2219 imgptr[yp*imgDim + xn]+=
2220 eps1 * scnptr[(viewNr - view)*binNr + bin];
2221 // Add img(x,-y)*k to the raysum of LOR (viewNr-view,binNr-bin)
2222 if(bin != center)
2223 imgptr[yn*imgDim + xp]+=
2224 eps1 * scnptr[(viewNr-view)*binNr + binNr - 1 - bin];
2225
2226 // Mirror the LOR on line y=x, i.e. y->x.
2227 // Case: pi/2 - theta.
2228 // Add img(y,x)*k to the raysum of LOR (viewNr/2-view,bin)
2229 imgptr[xn*imgDim + yn]+=
2230 eps1 * scnptr[(viewNr/2 - view)*binNr + bin];
2231 // Add img(-y,-x)*k to the raysum of LOR (viewNr/2-view,binNr-bin)
2232 if(bin != center)
2233 imgptr[xp*imgDim + yp]+=
2234 eps1 * scnptr[(viewNr/2 - view)*binNr + binNr - 1 - bin];
2235 }
2236
2237 // Mirror the LOR on line x=y, and on y-axis i.e x->y and y->-y.
2238 // Case: pi/2 + theta.
2239 // Add img(y,-x)*k to the raysum of LOR (viewNr/2+view,bin)
2240 imgptr[xn*imgDim + yp]+=
2241 eps1 * scnptr[(viewNr/2 + view)*binNr + bin];
2242 // Add img(-y,x)*k to the raysum of LOR (viewNr-view,binNr-bin)
2243 if(bin != center)
2244 imgptr[xp*imgDim + yn]+=
2245 eps1 * scnptr[(viewNr/2 + view)*binNr + binNr - 1 - bin];
2246
2247 } else {
2248 if(!eps2) { // <=> eps3 != 0 & eps2 = 0 <=> Cases 3,4 and 8.
2249 if(xp + 1 < imgDim && xn - 1 >= 0) {
2250 // Case: theta.
2251 // Add img(x,y)*k to the raysum of LOR (view,bin)
2252 imgptr[yp*imgDim + xp] += eps1 * scnptr[view*binNr + bin];
2253 imgptr[yp*imgDim + xp+1] += eps3 *scnptr[view*binNr + bin];
2254 // Add img(-x,-y)*k to the raysum of LOR (view,binNr-bin)
2255 if(bin != center){
2256 imgptr[yn*imgDim + xn] +=
2257 eps1 * scnptr[view*binNr + binNr - 1 - bin];
2258 imgptr[yn*imgDim + xn-1] +=
2259 eps3 * scnptr[view*binNr + binNr - 1 - bin];
2260 }
2261
2262 if(view != viewNr/4) {
2263 // Mirror the LOR on y-axis, i.e. x->-x
2264 // Case: pi-theta.
2265 // Add img(-x,y)*k to the raysum of LOR (viewNr-view,bin)
2266 imgptr[yp*imgDim + xn]+=
2267 eps1 * scnptr[(viewNr - view)*binNr + bin];
2268 imgptr[yp*imgDim + xn-1] +=
2269 eps3 * scnptr[(viewNr - view)*binNr + bin];
2270 /* Add img(x,-y)*k to the raysum of LOR
2271 (viewNr-view,binNr-bin) */
2272 if(bin != center) {
2273 imgptr[yn*imgDim + xp] +=
2274 eps1 * scnptr[(viewNr-view)*binNr + binNr - 1 - bin];
2275 imgptr[yn*imgDim + xp+1] +=
2276 eps3 *scnptr[(viewNr-view)*binNr + binNr - 1 - bin];
2277 }
2278 // Mirror the LOR on line y=x, i.e. y->x.
2279 // Case: pi/2 - theta.
2280 // Add img(y,x)*k to the raysum of LOR (viewNr/2-view,bin)
2281 imgptr[xn*imgDim + yn]+=
2282 eps1 * scnptr[(viewNr/2 - view)*binNr + bin];
2283 imgptr[(xn-1)*imgDim + yn] +=
2284 eps3 *scnptr[(viewNr/2 - view)*binNr + bin];
2285 /* Add img(-y,-x)*k to the raysum of LOR
2286 (viewNr/2-view,binNr-bin) */
2287 if(bin != center) {
2288 imgptr[xp*imgDim + yp]+=
2289 eps1 * scnptr[(viewNr/2 - view)*binNr + binNr - 1 - bin];
2290 imgptr[(xp+1)*imgDim+yp]+=
2291 eps3 * scnptr[(viewNr/2 - view)*binNr + binNr - 1 - bin];
2292 }
2293 }
2294
2295 // Mirror the LOR on line x=y, and on y-axis i.e x->y and y->-y.
2296 // Case: pi/2 + theta.
2297 // Add img(y,-x)*k to the raysum of LOR (viewNr/2+view,bin)
2298 imgptr[xn*imgDim + yp]+=
2299 eps1 * scnptr[(viewNr/2 + view)*binNr + bin];
2300 imgptr[(xn-1)*imgDim + yp] +=
2301 eps3 * scnptr[(viewNr/2 + view)*binNr + bin];
2302 // Add img(-y,x)*k to the raysum of LOR (viewNr-view,binNr-bin)
2303 if(bin != center){
2304 imgptr[xp*imgDim + yn]+=
2305 eps1 * scnptr[(viewNr/2 + view)*binNr + binNr - 1 - bin];
2306 imgptr[(xp+1)*imgDim+yn] +=
2307 eps3*scnptr[(viewNr/2 + view)*binNr + binNr - 1 - bin];
2308 }
2309 }
2310 } else { // <=> eps2!=0 && eps3!=0 <=> Case 3.
2311 if(xp+1 < imgDim && xn-1 >= 0 && yp-1 >= 0 && yn+1 < imgDim) {
2312
2313 // Case: theta.
2314 // Add img(x,y)*k to the raysum of LOR (view,bin)
2315 imgptr[yp*imgDim + xp] += eps1 * scnptr[view*binNr + bin];
2316 imgptr[yp*imgDim + xp+1] += eps3 *scnptr[view*binNr + bin];
2317 imgptr[(yp-1)*imgDim + xp+1] +=
2318 eps2 * scnptr[view*binNr + bin];
2319 // Add img(-x,-y)*k to the raysum of LOR (view,binNr-bin)
2320 if(bin != center){
2321 imgptr[yn*imgDim + xn] +=
2322 eps1 * scnptr[view*binNr + binNr - 1 - bin];
2323 imgptr[yn*imgDim + xn-1] +=
2324 eps3 * scnptr[view*binNr + binNr - 1 - bin];
2325 imgptr[(yn+1)*imgDim + xn-1] +=
2326 eps2 * scnptr[view*binNr + binNr - 1 - bin];
2327 }
2328 if(view != viewNr/4) {
2329 // Mirror the LOR on y-axis, i.e. x->-x
2330 // Case: pi-theta.
2331 // Add img(-x,y)*k to the raysum of LOR (viewNr-view,bin)
2332 imgptr[yp*imgDim + xn] +=
2333 eps1 * scnptr[(viewNr - view)*binNr + bin];
2334 imgptr[yp*imgDim + xn-1] +=
2335 eps3 *scnptr[(viewNr - view)*binNr + bin];
2336 imgptr[(yp-1)*imgDim + xn-1]+=
2337 eps2 * scnptr[(viewNr - view)*binNr + bin];
2338 /* Add img(x,-y)*k to the raysum of LOR
2339 (viewNr-view,binNr-bin) */
2340 if(bin != center) {
2341 imgptr[yn*imgDim + xp] +=
2342 eps1 * scnptr[(viewNr-view)*binNr + binNr - 1 - bin];
2343 imgptr[yn*imgDim + xp+1] +=
2344 eps3 * scnptr[(viewNr-view)*binNr + binNr - 1 - bin];
2345 imgptr[(yn+1)*imgDim + xp+1] +=
2346 eps2 * scnptr[(viewNr-view)*binNr + binNr - 1 - bin];
2347 }
2348
2349 // Mirror the LOR on line y=x, i.e. y->x.
2350 // Case: pi/2 - theta.
2351 // Add img(y,x)*k to the raysum of LOR (viewNr/2-view,bin)
2352 imgptr[xn*imgDim + yn]+=
2353 eps1 * scnptr[(viewNr/2 - view)*binNr + bin];
2354 imgptr[xn*imgDim + yn-1] +=
2355 eps3 *scnptr[(viewNr/2 - view)*binNr + bin];
2356 imgptr[(xn-1)*imgDim + (yn+1)] +=
2357 eps2 * scnptr[(viewNr/2 - view)*binNr + bin];
2358 /* Add img(-y,-x)*k to the raysum of LOR
2359 (viewNr/2-view,binNr-bin) */
2360 if(bin != center) {
2361 imgptr[xp*imgDim + yp]+=
2362 eps1 * scnptr[(viewNr/2 - view)*binNr + binNr - 1 - bin];
2363 imgptr[(xp+1)*imgDim+yp] +=
2364 eps3*scnptr[(viewNr/2 - view)*binNr + binNr - 1 - bin];
2365 imgptr[(xp+1)*imgDim+(yp-1)] +=
2366 eps2*scnptr[(viewNr/2 - view)*binNr + binNr - 1 - bin];
2367 }
2368 }
2369
2370 // Mirror the LOR on line x=y, and on y-axis i.e x->y and y->-y.
2371 // Case: pi/2 + theta.
2372 // Add img(y,-x)*k to the raysum of LOR (viewNr/2+view,bin).
2373 imgptr[xn*imgDim + yp] +=
2374 eps1 * scnptr[(viewNr/2 + view)*binNr + bin];
2375 imgptr[(xn-1)*imgDim + yp] +=
2376 eps3 * scnptr[(viewNr/2 + view)*binNr + bin];
2377 imgptr[(xn-1)*imgDim + (yp-1)] +=
2378 eps2 *scnptr[(viewNr/2 + view)*binNr + bin];
2379 // Add img(-y,x)*k to the raysum of LOR (viewNr-view,binNr-bin)
2380 if(bin != center){
2381 imgptr[xp*imgDim + yn]+=
2382 eps1 * scnptr[(viewNr/2 + view)*binNr + binNr - 1 - bin];
2383 imgptr[(xp+1)*imgDim+yn] +=
2384 eps3 * scnptr[(viewNr/2 + view)*binNr + binNr - 1 - bin];
2385 imgptr[(xp+1)*imgDim+yn+1] +=
2386 eps2*scnptr[(viewNr/2 + view)*binNr + binNr - 1 - bin];
2387 }
2388 }
2389 }
2390 }
2391 }
2392 }
2393 } // END of X loop
2394 } // End of view>0.
2395 } // END OF VIEW LOOP
2396 free(X);
2397 free(Y);
2398
2399 return 0;
2400
2401} // END OF EXACT AREA BACK TRANSFORM.
2402/*****************************************************************************/
2416 RADON *radtra, int set, int setNr, float *scndata, float *imgdata
2417) {
2418 float *imgptr, *scnptr, *imgorigin;
2419 float sinus, cosinus;
2420 float t; // distance between projection ray and origo.
2421 int mode, imgDim, binNr, viewNr, halfImg, centerBin, view;
2422 int x, y, xright, ybottom;
2423 float tpow2;
2424
2425 // Retrieve the data from given radon transform object.
2426 mode=radonGetMO(radtra); // Should be 3 or 4.
2427 imgDim=radonGetID(radtra);
2428 binNr=radonGetNB(radtra); // Should be equal to imgDim.
2429 viewNr=radonGetNV(radtra);
2430 // Set the center ray and the square of it.
2431 centerBin=binNr/2;
2432 tpow2 = centerBin*centerBin;
2433
2434 if(imgDim != binNr) return -1;
2435
2436 // Set half of the image dimension.
2437 halfImg = imgDim/2;
2438
2439 // Transform one angle at a time.
2440 for(view=set; view<viewNr; view+=setNr){
2441
2442 imgorigin = imgdata + imgDim*(halfImg - 1) + halfImg;
2443
2444 sinus = radonGetSin(radtra,view);
2445 cosinus = radonGetSin(radtra,viewNr/2 + view);
2446
2447 y = halfImg - 2;
2448
2449 if((float)y > centerBin){
2450 y = (int)(centerBin);
2451 ybottom = -y;
2452 } else{
2453 ybottom = -halfImg + 1;
2454 }
2455 for(; y >= ybottom; y--){
2456 xright =
2457 (int)sqrt(/*fabs(*/tpow2 - ((float)y+0.5) * ((float)y+0.5)/*)*/) + 1;
2458 if(xright >= halfImg){
2459 xright = halfImg - 1;
2460 x = -halfImg;
2461 }
2462 else
2463 x = -xright;
2464
2466 // t = centerBin - (float)y * sinus + ((float)(x + 1)) * cosinus;
2467 t = centerBin + (float)y * sinus + ((float)(x + 1)) * cosinus;
2468
2469 imgptr = imgorigin - y*imgDim + x;
2470 scnptr = scndata + view*binNr;
2471 for(; x <= xright; x++, t += cosinus){
2472 if(mode == 3){ // If the linear interpolation is to be utilised.
2473 *imgptr++ +=
2474 ( *(scnptr+(int)t) + (*(scnptr+(int)t+1) - *(scnptr+(int)t))
2475 * (t - (float)(int)t) );
2476 } else {// If the nearest neighbour interpolation is to be utilised.
2477 *imgptr++ += *(scnptr+(int)(t + 0.5)); /* (float)(1.0 / (float)views)*/
2478 }
2479 }
2480 }
2481 }
2482 return 0;
2483}
2484/*****************************************************************************/
2504 PRMAT *mat, int set, int setNr, float *scndata, float *imgdata
2505) {
2506 float *imgptr, *scnptr; // pointers for the image and sinogram data
2507 unsigned int imgDim=128, binNr=256, viewNr=192, view, bin, row, col;
2508 unsigned int half, centerbin;
2509 int xp, xn, yp, yn;
2510 float fact;
2511
2512 // Retrieve the data from given projection matrix.
2513 imgDim=prmatGetID(mat);
2514 binNr=prmatGetNB(mat); // Should be equal to imgDim.
2515 viewNr=prmatGetNV(mat);
2516
2517 // Calculate and set center bin for current geometrics.
2518 if((binNr%2) != 0){
2519 half = (binNr - 1)/2 + 1;
2520 centerbin = half - 1;
2521 } else {
2522 half = binNr/2;
2523 // In the case binNr is even there is no center bin.
2524 centerbin = -1;
2525 }
2526
2527 imgptr = imgdata;
2528 scnptr = scndata;
2529
2530 // Draw sinogram according to projection matrix.
2531 for(view=set; view<=viewNr/4; view=view+setNr){
2532 for(bin=0; bin<half; bin++){
2533 row = view*half + bin;
2534 for(col=0; col<prmatGetPixels(mat,row); col++){
2535
2536 fact = prmatGetFactor(mat,row,col);
2537 xp = prmatGetXCoord(mat,row,col);
2538 xn = imgDim - 1 - xp;
2539 yp = prmatGetYCoord(mat,row,col);
2540 yn = imgDim - 1 - yp;
2541
2542 // Add img(x,y)*k to the raysum of LOR (view,bin)
2543 imgptr[yp*imgDim + xp] += fact * scnptr[view*binNr + bin];
2544 if(bin != centerbin)
2545 // Add img(-x,-y)*k to the raysum of LOR (view,binNr-bin)
2546 imgptr[yn*imgDim + xn] += fact * scnptr[view*binNr + binNr - 1 - bin];
2547
2548 if(view != 0 && view != viewNr/4){
2549 // Mirror the original LOR on y-axis, i.e. x->-x
2550 // Case: pi-theta.
2551 // Add img(-x,y)*k to the raysum of LOR (viewNr-view,bin)
2552 imgptr[yp*imgDim + xn] += fact * scnptr[(viewNr - view)*binNr + bin];
2553 // Add img(x,-y)*k to the raysum of LOR (viewNr-view,binNr-bin)
2554 if(bin != centerbin)
2555 imgptr[yn*imgDim + xp] +=
2556 fact * scnptr[(viewNr-view)*binNr + binNr - 1 - bin];
2557
2558 // Mirror the LOR on line x=y, i.e. x->y.
2559 // Case: pi/2-theta
2560 // Add img(-y,-x)*k to the raysum of LOR (viewNr/2-view,bin)
2561 imgptr[xn*imgDim + yn] += fact * scnptr[(viewNr/2 - view)*binNr + bin];
2562 // Add img(y,x)*k to the raysum of LOR (viewNr/2-view,binNr-bin)
2563 if(bin != centerbin)
2564 imgptr[xp*imgDim + yp] +=
2565 fact * scnptr[(viewNr/2 - view)*binNr + binNr - 1 - bin];
2566 }
2567
2568 // Mirror the LOR on line x=y, and on y-axis i.e x->y and y->-y.
2569 // Case: pi/2+theta
2570 // Add img(y,-x)*k to the raysum of LOR (viewNr/2+view,bin)
2571 imgptr[xn*imgDim + yp] += fact * scnptr[(viewNr/2 + view)*binNr + bin];
2572 // Add img(y,-x)*k to the raysum of LOR (viewNr/2+view,binNr-bin)
2573 if(bin != centerbin)
2574 imgptr[xp*imgDim + yn] +=
2575 fact * scnptr[(viewNr/2 + view)*binNr + binNr - 1 - bin];
2576
2577 }
2578 }
2579 }
2580
2581 return 0;
2582}
2583/*****************************************************************************/
2584/* PROCEDURES FOR SETTING PROJECTION MATRIX IN THE PROJECTION MATRIX
2585 DATA STRUCTURE */
2586/*****************************************************************************/
2603 RADON *radtra,ELLIPSE *elli, PRMAT *mat
2604) {
2605 // temporary pointers for storing the coordinates and factors
2606 unsigned short int **coords, *factors, **coptr, *facptr;
2607 // pointers for the values of LOR in integer points
2608 float *Y, *X, *Xptr, *Yptr;
2609 double sinus, cosinus, tanus; // sin, cosine and tangent
2610 double shift_x, shift_y; // shift for LOR
2611 int xp, xn, yp, yn, z; //integer points
2612 int x_left, x_right, y_top, y_bottom; // limits for fast search
2613 int col, row, view, bin, pix; //counters
2614 int binNr, viewNr, imgDim, views, rows, mode, half; // properties
2615 float diam, sdist;
2616 float scale, sum=0, sqr_sum=0, min=0, max=0;
2617 float dx, dy , loi = 1; // delta x and y and length of intersection
2618
2619 // Check that the data for this radon transform is initialized.
2620 if(radtra->status != RADON_STATUS_INITIALIZED) return -1;
2621
2622 // Retrieve the data from given radon transform object.
2623 mode=radonGetMO(radtra);
2624 imgDim=radonGetID(radtra);
2625 binNr=radonGetNB(radtra);
2626 viewNr=radonGetNV(radtra);
2627 sdist=radonGetSD(radtra);
2628 half=radonGetHI(radtra);
2629
2630 // Set information in the projection matrix data stucture.
2631 if(binNr == 192) {
2632 mat->type=PRMAT_TYPE_ECAT931;
2633 } else if(binNr == 281){
2634 mat->type=PRMAT_TYPE_GE;
2635 } else
2636 mat->type=PRMAT_TYPE_NA;
2637
2638 mat->viewNr=viewNr;
2639 mat->binNr=binNr;
2640 mat->imgDim=imgDim;
2641
2642 mat->mode = mode;
2643 // Allocate memory in PRMAT struct and set fov.
2644 mat->prmatfov = (int*)calloc(2,sizeof(int));
2645 mat->prmatfov[0] = ellipseGetMajor(elli);
2646 mat->prmatfov[1] = ellipseGetMinor(elli);
2647
2648 // rows := number of lines in the base set = (views*half)
2649 views = viewNr/4 + 1;
2650 rows = views*half;
2651
2652 mat->factor_sqr_sum=calloc(rows,sizeof(float));
2653 mat->dimr=rows;
2654 //entries in one line
2655 mat->dime=calloc(rows,sizeof(int));
2656 mat->_factdata=(unsigned short int***)calloc(rows,sizeof(unsigned short int**));
2657 //if not enough memory
2658 if(!mat->_factdata || !mat->dime) return(4);
2659
2660 // Compute scaling factor, assuming that maximum value is 1.
2661 scale=65534./1;
2662 mat->scaling_factor=1./scale; //is the inverse of scale
2663
2664 /* Allocate (temporary) coordinate and factor arrays to maximum size
2665 (= 2*imgDim).
2666 Coords contains pairs (x,y), coordinates in cartesian coordinate system. */
2667 coords = (unsigned short int**)calloc(2*imgDim,sizeof(unsigned short int*));
2668 factors = (unsigned short int*)calloc(2*imgDim,sizeof(unsigned short int));
2669 if(!coords || !factors) return 5;
2670
2671 for(col=0; col<2*imgDim; col++){
2672 coords[col] = (unsigned short int*)calloc(2,sizeof(unsigned short int));
2673 if(!coords[col]) return -1;
2674 }
2675
2676 coptr = coords;
2677 facptr = factors;
2678
2680 // Set diameter of a pixel.
2681 diam = sqrt(2);
2682
2683 // Array for storing values A_x.
2684 X=(float*)calloc(imgDim+1,sizeof(float));
2685 // Array for storing values A_y.
2686 Y=(float*)calloc(imgDim+1,sizeof(float));
2687 if(X==NULL || Y==NULL){
2688 return -2;
2689 }
2690 Xptr=X;
2691 Yptr=Y;
2692
2694 // Find pixel coordinates of the contributing pixels for lines of response
2695 // belonging to first 1/4th of angles. From these pixel coordinates
2696 // others can be calculated via symmetries in projection space.
2697 // N.B. The line of response: a*x+b*y+c
2698 // => solve y: y=-x/tan(view) + s*(cos(theta)/tan(theta) + sin(theta))
2699 // solve x: x=-y*tan(theta) + s*(sin(theta)*tan(theta) + cos(theta))
2700
2701 for(view=0; view<views; view++){
2702 // Angle theta=0 -> sin(theta)=0.
2703 if(view==0){
2704
2705 //If the mode switch is on zero do the 0-1 model transform.
2706 if(mode == 0)
2707 loi = 1.;
2708 else
2709 loi=1/diam;
2710
2711 // Choose column according to sample distance for angle 0.
2712 col = 0;
2713 for(bin=0; bin<half; bin++){
2714 col = floor((float)(bin+.5*sdist)*sdist);
2715
2716 pix = 0; // length of list pixels (and factors)
2717 sqr_sum = 0;
2718
2719 // Iterate through the entries in the image matrix.
2720 // Set factors for pixels intersected by lines in the base set.
2721 for(row=0; row<imgDim; row++){
2722
2723 /* Check that pixel and pixels hit by symmetrical lines lay inside
2724 the FOV. */
2725 if(ellipseIsInside(elli,row,col) && ellipseIsInside(elli,row,imgDim -
2726 1 - col) && ellipseIsInside(elli,imgDim-1-col,row) &&
2727 ellipseIsInside(elli,col,row))
2728 {
2729 coptr[pix][0] = (unsigned short int)col;
2730 coptr[pix][1] = (unsigned short int)row;
2731 // Convert loi to unsigned short int.
2732 facptr[pix] = (unsigned short int)(scale*loi);
2733 // Look for minimal and maximal factor.
2734 if(min>loi) min=loi;
2735 if(max<loi) max=loi;
2736 // Compute square sums in every row.
2737 sqr_sum += loi*loi;
2738 sum += loi;
2739 pix++;
2740 }
2741 }
2742
2743 /* Allocate memory in factor pointer (dynamically according to number
2744 of pixels intersected). */
2745 if(pix){
2746 mat->_factdata[bin]=
2747 (unsigned short int**)calloc(pix,sizeof(unsigned short int*));
2748 if(!mat->_factdata[bin]) return -1;
2749 }
2750
2751 // Allocate leaves.
2752 for(col=0; col<pix; col++) {
2753 mat->_factdata[bin][col]=
2754 (unsigned short int*)calloc(3,sizeof(unsigned short int));
2755 if(!mat->_factdata[bin][col]) return -1;
2756 }
2757
2758 // Put now values in coordinates and factors array to result pointer.
2759 mat->fact = mat->_factdata;
2760 for(col=0; col<pix; col++) {
2761 mat->fact[bin][col][0] = coptr[col][0]; // x-coodinate
2762 mat->fact[bin][col][1] = coptr[col][1]; // y-coordinate
2763 mat->fact[bin][col][2] = facptr[col]; // factor
2764 }
2765
2766 //Set also the number of pixels belonging to each row and square sums.
2767 mat->dime[bin]=pix;
2768 mat->factor_sqr_sum[bin]=sqr_sum;
2769
2770 } // END OF BIN-LOOP FOR ANGLE 0.
2771 // End of view=0.
2772 } else {
2773
2774 // Set sine and cosine for this angle.
2775 sinus = (double)radonGetSin(radtra,view);
2776 cosinus = (double)radonGetSin(radtra,viewNr/2 + view);
2777 tanus = sinus/cosinus;
2778
2779 // Set shift from origin for the first line of response (-n/2,theta).
2780 // NOTE that image matrix is on cartesian coordinate system where origin
2781 // is in the middle and shift is in pixels.
2782 shift_y = -(imgDim/2 -.5*sdist)/sinus;
2783 shift_x = -(imgDim/2 -.5*sdist)/cosinus;
2784
2785 // Evaluate the function of the first LOR in integer points [-n/2,n/2].
2786 // NOTE that image matrix is on cartesian coordinate system where origin
2787 // is in the middle.
2788 z=-imgDim/2;
2789 for(col=0; col<imgDim+1; col++){
2790 Yptr[col]=(float)(shift_y - z/tanus);
2791 Xptr[col]=(float)(shift_x - z*tanus);
2792 z++;
2793 }
2794
2795 // Set shift from the first LOR.
2796 shift_y = (double)(sdist/sinus);
2797 shift_x = (double)(sdist/cosinus);
2798
2799 // Iterate through half the bins in this view,
2800 // and determine coordinates of pixels contributing to this LOR.
2801 // NOTE that shift is added according to 'bin' in every loop.
2802 // Calculate also the length of intersection.
2803 // Others are determined via symmetry in projection space.
2804
2805 for(bin=0; bin<half; bin++){
2806
2807 coptr = coords;
2808 facptr = factors;
2809 pix = 0;
2810 sqr_sum = 0;
2811
2812 // Limit (x-)indices for fast search.
2813 // Note that indices are non-negative integers.
2814
2815 x_left = floor((float)(Xptr[imgDim] + bin*shift_x + imgDim/2));
2816 if(x_left < 0) x_left = 0;
2817
2818 x_right = floor((float)(Xptr[0] + bin*shift_x + imgDim/2));
2819 if(x_right <= 0) x_right = 1;
2820 if(x_right > imgDim) x_right = imgDim - 1;
2821
2822 /* Iterate through the values in vector Y, in integer points
2823 [x_left,x_rigth]. */
2824 for(z=x_left; z <= x_right; z++) {
2825
2826 xp = z; //positive x-coordinate
2827 xn = imgDim - 1 - xp; //negative x-coordinate
2828
2829 // Look y from left.
2830 yp = imgDim/2 - floor(Yptr[xp + 1] + bin*shift_y) - 1;
2831 yn = imgDim - 1 - yp;
2832
2833 // If the y-value for this x (z) is inside the image grid.
2834 if(yp < imgDim && yp >= 0 && yn < imgDim && yn >= 0 && xp >= 0 &&
2835 xp < imgDim && xn < imgDim && xn >= 0) {
2836
2837 if(!mode) {
2838 loi = 1;
2839 } else {
2840 // Compute delta x and y.
2841 dx = (float)(xp + 1 - (imgDim/2 + Xptr[imgDim - yp] + bin*shift_x));
2842 dy = (float)(floor(Yptr[xp + 1] + bin*shift_y) + 1 -
2843 (Yptr[xp + 1] + bin*shift_y));
2844 if(dx > 1 || dx < 0) dx = 1;
2845 if(dy > 1 || dy < 0) dy = 1;
2846 loi = sqrt(dx*dx + dy*dy);
2847 loi=loi/diam;
2848 }
2849
2850 /* Check that pixel and pixels hit by symmetrical lines lay inside
2851 the FOV. */
2852 if(ellipseIsInside(elli,yp,xp) && ellipseIsInside(elli,yn,xn) &&
2853 ellipseIsInside(elli,yp,xn) && ellipseIsInside(elli,yn,xp) &&
2854 ellipseIsInside(elli,xn,yn) && ellipseIsInside(elli,xp,yp) &&
2855 ellipseIsInside(elli,xn,yp) && ellipseIsInside(elli,xp,yn)) {
2856
2857 // Put coordinates and factors in the list.
2858 coptr[pix][0] = xp;
2859 coptr[pix][1] = yp;
2860 facptr[pix] = (unsigned short int)(scale*loi);
2861
2862 // Look for minimal and maximal factor.
2863 if(min>loi) min=loi;
2864 if(max<loi) max=loi;
2865 sqr_sum += loi*loi;
2866 sum += loi;
2867 pix++;
2868 }
2869 }
2870 }
2871
2872 // Limit (y-)indices for fast search.
2873 // Note that indices are non-negative integers.
2874 y_bottom = floor((float)(Yptr[imgDim] + bin*shift_y + imgDim/2));
2875 if(y_bottom < 0) y_bottom = 0;
2876 if(y_bottom > imgDim) y_bottom = 0;
2877
2878 y_top = floor((float)(Yptr[0] + bin*shift_y + imgDim/2));
2879 if(y_top > imgDim) y_top = imgDim-1;
2880 if(y_top <= 0) y_top = 1;
2881
2882 /* Iterate through the values in vector X, in integer points
2883 [y_bottom,y_top]. */
2884 for(z=y_top; z >= y_bottom; z--) {
2885
2886 // Look y from this location.
2887 xp = floor(Xptr[z] + bin*shift_x) + imgDim/2;
2888 xn = imgDim - 1 - xp;
2889
2890 yp = imgDim - z - 1;
2891 yn = imgDim - yp - 1;
2892
2893 // If the x-value for this y (z) is inside the image grid.
2894 if(yp < imgDim && yp >= 0 && yn < imgDim && yn >= 0 && xp >= 0 &&
2895 xp < imgDim && xn < imgDim && xn >= 0) {
2896
2897 if(!mode){
2898 loi = 1;
2899 } else {
2900 dx = (float)(Xptr[z] + bin*shift_x + imgDim/2 - xp);
2901 dy = (float)(Yptr[xp] + bin*shift_y - z + imgDim/2);
2902 if(dy > 1 || dy < 0) {
2903 dx = dx - (float)(Xptr[z+1] + bin*shift_x + imgDim/2 - xp);
2904 dy = 1;
2905 }
2906 loi = sqrt(dx*dx + dy*dy)/diam;
2907 }
2908
2909 /* Check that pixel and pixels hit by symmetrical lines lay inside
2910 the FOV. */
2911 if(ellipseIsInside(elli,yp,xp) && ellipseIsInside(elli,yn,xn) &&
2912 ellipseIsInside(elli,yp,xn) && ellipseIsInside(elli,yn,xp) &&
2913 ellipseIsInside(elli,xn,yn) && ellipseIsInside(elli,xp,yp) &&
2914 ellipseIsInside(elli,xn,yp) && ellipseIsInside(elli,xp,yn)){
2915
2916 // Put coordinates and factors in the list.
2917 coptr[pix][0] = xp;
2918 coptr[pix][1] = yp;
2919 facptr[pix] = (unsigned short int)(scale*loi);
2920
2921 // Look for minimal and maximal factor.
2922 if(min>loi) min=loi;
2923 if(max<loi) max=loi;
2924 sqr_sum += loi*loi;
2925 sum += loi;
2926 pix++;
2927 }
2928 }
2929 }
2930 // Allocate memory in result pointer.
2931 if(pix){
2932 mat->_factdata[view*half + bin]=
2933 (unsigned short int**)calloc(pix,sizeof(unsigned short int*));
2934 if(!mat->_factdata[view*half + bin]) return -1;
2935 }
2936
2937 // Allocate leaves.
2938 for(col=0; col<pix; col++){
2939 mat->_factdata[view*half + bin][col]=
2940 (unsigned short int*)calloc(3,sizeof(unsigned short int));
2941 if(!mat->_factdata[view*half + bin][col]) return -1;
2942 }
2943
2944 // Put now values in coordinates and factors array to result pointer.
2945 mat->fact = mat->_factdata;
2946 for(col=0; col<pix; col++){
2947 mat->fact[view*half + bin][col][0] = coptr[col][0];
2948 mat->fact[view*half + bin][col][1] = coptr[col][1];
2949 mat->fact[view*half + bin][col][2] = facptr[col];
2950 }
2951
2952 // Update also lists mat->dime and mat->factor_sqr_sums
2953 mat->dime[view*half + bin]=pix;
2954
2955 mat->factor_sqr_sum[view*half + bin]=sqr_sum;
2956
2957 }// END of bin loop
2958
2959 }// End of view>0.
2960
2961 }// END OF VIEW LOOP
2962
2963 free(X);
2964 free(Y);
2965 free(coords);
2966 free(factors);
2967
2968 mat->min = min;
2969 mat->max = max;
2970 mat->factor_sum = sum;
2971 mat->status = PRMAT_STATUS_BS_OCCUPIED;
2972 return 0;
2973
2974} // END OF SETTING BASE LINES.
2975/*****************************************************************************/
2984int radonSetBasesEA(RADON *radtra,ELLIPSE *elli, PRMAT *mat)
2985{
2986 // temporary pointers for storing the coordinates and factors
2987 unsigned short int **coords, *factors, **coptr, *facptr;
2988 // pointers for the values of LOR in integer points
2989 float *Y, *X, *Xptr, *Yptr;
2990 double sinus, cosinus, tanus; // sin, cosine and tangent
2991 double shift_x, shift_y; // shift for LOR
2992 int xp, xn, yp, yn, z, xp2; //integer points
2993 int x_left, x_right, y_top, y_bottom; // limits for fast search
2994 int col, col1, col2, row, view, bin, pix, errors=0; //counters
2995 int binNr, viewNr, imgDim, mode, views, rows, half;
2996 float sdist;
2997 float a=0,b=0, c=0, d=0, g=0, h=0, A;
2998 // delta x and y and factors epsilon.
2999 float dx, dy , eps1 = 0, eps2 = 0, eps3 = 0;
3000 float min=0, max=0, sum=0, scale, sqr_sum=0;
3001
3002 // Check that the data for this radon transform is initialized.
3003 if(radtra->status != RADON_STATUS_INITIALIZED) return -1;
3004
3005 // Retrieve the data from given radon transform object.
3006 mode=radonGetMO(radtra); // Should be 2.
3007 imgDim=radonGetID(radtra);
3008 binNr=radonGetNB(radtra);
3009 viewNr=radonGetNV(radtra);
3010 sdist=radonGetSD(radtra);
3011 half=radonGetHI(radtra);
3012
3013 /*printf("radonSetBases(): m=%i, id=%i, b=%i, v=%i, sd=%f, h=%i.\n",
3014 mode,imgDim,binNr,viewNr,sdist,half);*/
3015
3016 // Set information in the projection matrix data stucture.
3017 if(binNr == 192){
3018 mat->type=PRMAT_TYPE_ECAT931;
3019 } else if(binNr == 281) {
3020 mat->type=PRMAT_TYPE_GE;
3021 } else
3022 mat->type=PRMAT_TYPE_NA;
3023
3024 mat->viewNr=viewNr;
3025 mat->binNr=binNr;
3026 mat->imgDim=imgDim;
3027
3028 mat->mode = mode;
3029 // Allocate memory in PRMAT struct and set fov.
3030 mat->prmatfov = (int*)calloc(2,sizeof(int));
3031 mat->prmatfov[0] = ellipseGetMajor(elli);
3032 mat->prmatfov[1] = ellipseGetMinor(elli);
3033
3034 // rows := number of lines in the base set = (views*half)
3035 views = viewNr/4 + 1;
3036 rows = views*half;
3037
3038 mat->factor_sqr_sum=calloc(rows,sizeof(float));
3039 mat->dimr=rows;
3040 //entries in one line
3041 mat->dime=calloc(rows,sizeof(int));
3042 mat->_factdata=(unsigned short int***)calloc(rows,sizeof(unsigned short int**));
3043 //if not enough memory
3044 if(!mat->_factdata || !mat->dime) return(4);
3045
3046 // Compute scaling factor, assuming that maximum value is 1.
3047 scale=65534./1;
3048 mat->scaling_factor=1.0/scale; //is the inverse of scale
3049
3050 /* Allocate (temporary) coordinate and factor arrays to maximum size
3051 (= 4*imgDim). Coords contains pairs (x,y), coordinates in cartesian
3052 coordinate system. */
3053 coords = (unsigned short int**)calloc(4*imgDim,sizeof(unsigned short int*));
3054 factors = (unsigned short int*)calloc(4*imgDim,sizeof(unsigned short int));
3055 if(!coords || !factors) return 5;
3056
3057 for(col=0; col<4*imgDim; col++){
3058 coords[col] = (unsigned short int*)calloc(2,sizeof(unsigned short int));
3059 if(!coords[col]) return -1;
3060 }
3061
3062 coptr = coords;
3063 facptr = factors;
3064
3065 // Array for storing values f_x.
3066 X=(float*)calloc(imgDim+1,sizeof(float));
3067 // Array for storing values f_y.
3068 Y=(float*)calloc(imgDim+1,sizeof(float));
3069 if(X==NULL || Y==NULL){
3070 return -2;
3071 }
3072 Xptr=X;
3073 Yptr=Y;
3074
3076 // Find pixel coordinates of the contributing pixels for tubes of response
3077 // belonging to first 1/4th of angles. From these pixel coordinates
3078 // others can be calculated via symmetries in projection space.
3079 // N.B. The line of response: a*x+b*y+c
3080 // => solve y: y=-x/tan(view) + s*(cos(theta)/tan(theta) + sin(theta))
3081 // solve x: x=-y*tan(theta) + s*(sin(theta)*tan(theta) + cos(theta))
3082 for(view=0; view<views; view++){
3083 // view=0 -> sin(theta)=0
3084 if(view==0){
3085
3086 // Choose column(s) according to sample distance for angles 0 and pi/2.
3087 col1 = 0;
3088 col2 = 0;
3089 for(bin = 0; bin < half; bin++){
3090
3091 pix = 0; // length of list pixels (and factors)
3092 sqr_sum = 0;
3093
3094 col1 = col2;
3095 col2 = floor((float)(bin + 1)*sdist);
3096
3097 // Determine factor epsilon.
3098 if(col1 == col2){
3099 eps1 = sdist;
3100 eps2 = 0;
3101 eps3 = 0;
3102 }
3103 if((col2-col1) == 1){
3104 eps1 = (float)(col2 - (bin)*sdist);
3105 eps2 = 0;
3106 eps3 = (float)((bin+1)*sdist - col2);
3107 }
3108 // If sdist > pixel size!
3109 if((col2-col1) > 1){
3110 eps1 = (float)(col1 + 1 - (bin)*sdist);
3111 eps2 = 1; // middle pixel.
3112 eps3 = (float)((bin+1)*sdist - col2);
3113 }
3114
3115 // Iterate through the entries in the image matrix.
3116 for(row=0; row<imgDim; row++){
3117
3118 /* Check that pixel and pixels hit by symmetrical lines lay inside
3119 the FOV. */
3120 if(ellipseIsInside(elli,row,col1) &&
3121 ellipseIsInside(elli,row,imgDim - 1 - col1) &&
3122 ellipseIsInside(elli,imgDim-1-col1,row) &&
3123 ellipseIsInside(elli,col1,row)) {
3124
3125 if(!eps3){
3126 coptr[pix][0] = (unsigned short int)col1;
3127 coptr[pix][1] = (unsigned short int)row;
3128 // Convert eps to unsigned short int.
3129 facptr[pix] = (unsigned short int)(scale*eps1);
3130 // Look for minimal and maximal factor.
3131 if(min>eps1) min=eps1;
3132 if(max<eps1) max=eps1;
3133 // Compute square sums in every row.
3134 sqr_sum += eps1*eps1;
3135 sum += eps1;
3136 pix++;
3137 }
3138
3139 if(eps3 && !eps2){
3140 coptr[pix][0] = (unsigned short int)col1;
3141 coptr[pix][1] = (unsigned short int)row;
3142 // Convert eps to unsigned short int.
3143 facptr[pix] = (unsigned short int)(scale*eps1);
3144 // Look for minimal and maximal factor.
3145 if(min>eps1) min=eps1;
3146 if(max<eps1) max=eps1;
3147 // Compute square sums in every row.
3148 sqr_sum += eps1*eps1;
3149 sum += eps1;
3150 pix++;
3151
3152 coptr[pix][0] = (unsigned short int)col2;
3153 coptr[pix][1] = (unsigned short int)row;
3154 // Convert eps to unsigned short int.
3155 facptr[pix] = (unsigned short int)(scale*eps3);
3156 // Look for minimal and maximal factor.
3157 if(min>eps3) min=eps3;
3158 if(max<eps3) max=eps3;
3159 // Compute square sums in every row.
3160 sqr_sum += eps3*eps3;
3161 sum += eps3;
3162 pix++;
3163 }
3164
3165 if(eps3 && eps2){
3166 for(col = col1; col<=col2; col++){
3167
3168 if(col == col1){
3169 coptr[pix][0] = (unsigned short int)col1;
3170 coptr[pix][1] = (unsigned short int)row;
3171 // Convert eps to unsigned short int.
3172 facptr[pix] = (unsigned short int)(scale*eps1);
3173 // Look for minimal and maximal factor.
3174 if(min>eps1) min=eps1;
3175 if(max<eps1) max=eps1;
3176 // Compute square sums in every row.
3177 sqr_sum += eps1*eps1;
3178 sum += eps1;
3179 pix++;
3180 }
3181
3182 if(col == col2){
3183 coptr[pix][0] = (unsigned short int)col2;
3184 coptr[pix][1] = (unsigned short int)row;
3185 // Convert eps to unsigned short int.
3186 facptr[pix] = (unsigned short int)(scale*eps3);
3187 // Look for minimal and maximal factor.
3188 if(min>eps3) min=eps3;
3189 if(max<eps3) max=eps3;
3190 // Compute square sums in every row.
3191 sqr_sum += eps3*eps3;
3192 sum += eps3;
3193 pix++;
3194 }
3195
3196 if(col != col1 && col != col2){
3197 coptr[pix][0] = (unsigned short int)col;
3198 coptr[pix][1] = (unsigned short int)row;
3199 // Convert eps to unsigned short int.
3200 facptr[pix] = (unsigned short int)(scale*eps2);
3201 // Look for minimal and maximal factor.
3202 if(min>eps2) min=eps2;
3203 if(max<eps2) max=eps2;
3204 // Compute square sums in every row.
3205 sqr_sum += eps2*eps2;
3206 sum += eps2;
3207 pix++;
3208 }
3209 }
3210 }
3211 }// Pixel is inside the fov
3212 }// END OF ROW-LOOP
3213
3214 /* Allocate memory in factor pointer (dynamically according to number
3215 of pixels intersected). */
3216 if(pix){
3217 mat->_factdata[bin]= // 0 angle
3218 (unsigned short int**)calloc(pix,sizeof(unsigned short int*));
3219 if(!mat->_factdata[bin]) return -1;
3220 }
3221 // Allocate leaves.
3222 for(col=0; col<pix; col++){
3223 mat->_factdata[bin][col]=
3224 (unsigned short int*)calloc(3,sizeof(unsigned short int));
3225 if(!mat->_factdata[bin][col]) return -1;
3226 }
3227
3228 // Put now values in coordinates and factors array to result pointer.
3229 mat->fact = mat->_factdata;
3230 for(col=0; col<pix; col++){
3231 mat->fact[bin][col][0] = coptr[col][0]; // x-coodinate
3232 mat->fact[bin][col][1] = coptr[col][1]; // y-coordinate
3233 mat->fact[bin][col][2] = facptr[col]; // factor
3234 }
3235
3236 //Set also the number of pixels belonging to each row and square sums.
3237 mat->dime[bin]=pix;
3238 mat->factor_sqr_sum[bin]=sqr_sum;
3239
3240 } // END OF BIN-LOOP FOR ANGLE 0
3241 // End of view==0 (handles angles 0,pi/4,pi/2,3pi/4).
3242 } else { // Angles in (0,pi)
3243
3244 // Set sine and cosine for this angle.
3245 sinus = (double)radonGetSin(radtra,view);
3246 cosinus = (double)radonGetSin(radtra,viewNr/2 + view);
3247 tanus = sinus/cosinus;
3248
3249 // Set shift from origin for the first line of response (-n/2,theta).
3250 // NOTE that image matrix is on cartesian coordinate system where origin
3251 // is in the middle and shift is in pixels.
3252 shift_y = -(imgDim/2)/sinus;
3253 shift_x = -(imgDim/2)/cosinus;
3254
3255 // Evaluate the function of the first LOR in integer points [-n/2,n/2].
3256 // NOTE that image matrix is on cartesian coordinate system where origin
3257 // is in the middle.
3258 z=-imgDim/2;
3259 for(col=0; col<imgDim+1; col++){
3260 Yptr[col]=(float)(-z/tanus + shift_y);
3261 Xptr[col]=(float)(-z*tanus + shift_x);
3262 z++;
3263 }
3264
3265 // Set shift from the first LOR.
3266 shift_y = (double)(sdist/sinus);
3267 shift_x = (double)(sdist/cosinus);
3268
3269 // Iterate through half the bins in this view,
3270 // and determine coordinates of pixels contributing to this LOR.
3271 // NOTE that shift is added according to 'bin' in every loop.
3272 // Calculate also the length of intersection.
3273 // Others are determined via symmetry in projection space.
3274
3275 for(bin=0; bin<half; bin++){
3276
3277 pix = 0;
3278 sqr_sum = 0;
3279
3280 // Limit (x-)indices for fast search.
3281 // Note that indices are non-negative integers.
3282
3283 x_left = floor((float)(Xptr[imgDim] + bin*shift_x + imgDim/2));
3284 if(x_left < 0) x_left = 0;
3285
3286 x_right = floor((float)(Xptr[0] + bin*shift_x + imgDim/2));
3287 if(x_right <= 0) x_right = 1;
3288 if(x_right > imgDim) x_right = imgDim - 1;
3289
3290 /* Iterate through the values in vector Y, in integer points
3291 [x_left,x_rigth]. */
3292 for(z=x_left; z <= x_right; z++) {
3293
3294 xp = z; //positive x-coordinate
3295 xn = imgDim - 1 - xp; //negative x-coordinate
3296
3297 // Look y from left.
3298 yp = imgDim/2 - floor(Yptr[xp + 1] + bin*shift_y) - 1;
3299 yn = imgDim - 1 - yp;
3300
3301 // If the y-value for this x (z) is inside the image grid.
3302 if(yp < imgDim && yp >= 0 && yn < imgDim && yn >= 0 && xp >= 0 &&
3303 xp < imgDim && xn < imgDim && xn >= 0) {
3304
3305 /* Check that pixel and pixels hit by symmetrical lines lay inside
3306 the FOV. */
3307 if(ellipseIsInside(elli,yp,xp) && ellipseIsInside(elli,yn,xn) &&
3308 ellipseIsInside(elli,yp,xn) && ellipseIsInside(elli,yn,xp) &&
3309 ellipseIsInside(elli,xn,yn) && ellipseIsInside(elli,xp,yp) &&
3310 ellipseIsInside(elli,xn,yp) && ellipseIsInside(elli,xp,yn)){
3311
3312 /* NOTE that pixels found in this part are always hit from right
3313 side. */
3314 // Compute a := |AF| and b := |FB|.
3315 a = (float)(xp + 1 - (imgDim/2 + Xptr[imgDim - yp] + bin*shift_x));
3316 b = (float)(floor(Yptr[xp + 1] + bin*shift_y) + 1 -
3317 (Yptr[xp + 1] + bin*shift_y));
3318
3319 // Calculate the area of lower triangle.
3320 A = a*b/2;
3321
3322 // c := |FC|
3323 c = (float)(xp + 1 - (imgDim/2 + Xptr[imgDim - yp] +
3324 (bin+1)*shift_x));
3325
3326 if(c > 0) {
3327
3328 // d := |FD|
3329 d = (float)(floor(Yptr[xp + 1] + (bin+1)*shift_y) + 1 -
3330 (Yptr[xp + 1] + (bin+1)*shift_y));
3331
3332 // Subtract the area of upper triangle.
3333 A = A - c*d/2;
3334 }
3335
3336 eps1 = A;
3337
3338 if(eps1 < 0 || eps1 > 1) errors++;
3339
3340 // Put coordinates and factors in the list.
3341 coptr[pix][0] = xp;
3342 coptr[pix][1] = yp;
3343 facptr[pix] = (unsigned short int)(scale*eps1);
3344
3345 // Look for minimal and maximal factor.
3346 if(min>eps1) min=eps1;
3347 if(max<eps1) max=eps1;
3348 sqr_sum += eps1*eps1;
3349 sum += eps1;
3350 pix++;
3351 }// Is inside the FOV.
3352 }
3353 }
3354
3355 // Limit (y-)indices for fast search.
3356 // Note that indices are non-negative integers.
3357 y_bottom = floor((float)(Yptr[imgDim] + bin*shift_y + imgDim/2));
3358 if(y_bottom < 0) y_bottom = 0;
3359 if(y_bottom > imgDim) y_bottom = 0;
3360
3361 y_top = floor((float)(Yptr[0] + bin*shift_y + imgDim/2));
3362 if(y_top > imgDim) y_top = imgDim;
3363 if(y_top <= 0) y_top = 1;
3364
3365 /* Iterate through the values in vector X, in integer points
3366 [y_bottom,y_top]. */
3367 for(z=y_top; z >= y_bottom; z--) {
3368
3369 // Look y from this location.
3370 xp = floor(Xptr[z] + bin*shift_x) + imgDim/2;
3371 xn = imgDim - 1 - xp;
3372
3373 yp = imgDim - z - 1;
3374 yn = imgDim - yp - 1;
3375
3376 // If the x-value for this y (z) is inside the image grid.
3377 if(yp < imgDim && yp >= 0 && yn < imgDim && yn >= 0 && xp >= 0 &&
3378 xp < imgDim && xn < imgDim && xn >= 0) {
3379
3380 /* Check that pixel and pixels hit by symmetrical lines lay inside
3381 the FOV. */
3382 if(ellipseIsInside(elli,yp,xp) && ellipseIsInside(elli,yn,xn) &&
3383 ellipseIsInside(elli,yp,xn) && ellipseIsInside(elli,yn,xp) &&
3384 ellipseIsInside(elli,xn,yn) && ellipseIsInside(elli,xp,yp) &&
3385 ellipseIsInside(elli,xn,yp) && ellipseIsInside(elli,xp,yn)){
3386
3387 eps1=eps2=eps3=0;
3388
3389 dx = (float)(Xptr[z] + bin*shift_x + imgDim/2 - xp);
3390 dy = (float)(Yptr[xp] + bin*shift_y - z + imgDim/2);
3391
3392 if(dy < 1){ // Cases 3,4,5 and 6.
3393
3394 // 1. PART
3395 // a := |HA|
3396 a = dy;
3397
3398 // b := |HB| (b < 1 for angles in [0,pi/4))
3399 b = dx;
3400
3401 // h := height of rectangle R.
3402 h = a + shift_y;
3403
3404 if(h > 1){ // Cases 3,4 and 5.
3405 h = 1;
3406 g = b + shift_x;
3407 if(g > 1){ // Cases 3 and 4.
3408 g = 1;
3409 xp2 =floor(Xptr[z+1] + (bin+1)*shift_x) + imgDim/2;
3410
3411 if(xp == xp2){ // Case 4.
3412 // c := |FC|
3413 c = (float)(xp + 1 - (imgDim/2 + Xptr[z+1] +
3414 (bin+1)*shift_x));
3415 // d := |FD|
3416 d = (float)(floor(Yptr[xp + 1] + (bin+1)*shift_y) + 1 -
3417 (Yptr[xp + 1] + (bin+1)*shift_y));
3418 eps1 = 1 - (a*b + c*d)/2;
3419 eps2 = 0;
3420 // Lower triangle on the next pixel (x+1,y).
3421 eps3 = (1 - d)*(b + shift_x - 1)/2;
3422 } else { // Case 3.
3423 // c=d=0.
3424 eps1 = 1 - a*b/2;
3425 // Calculate area on pixel in place (xp+1,yp-1).
3426 dy = (float)(Yptr[xp+1] + (bin+1)*shift_y - (z + 1) +
3427 imgDim/2);
3428 if(dy < 1){ // Case 11.
3429 // c := |HC|
3430 c = dy;
3431 // d := |HD|
3432 d = (float)(xp + 2 - (imgDim/2 + Xptr[z+1] +
3433 (bin+1)*shift_x));
3434 eps2 = c*d/2;
3435 } else{ // Cases 9 and 10.
3436 dx = (float)(xp + 2 - (imgDim/2 + Xptr[z+1] +
3437 (bin+1)*shift_x));
3438 if(dx < 1) { // Case 10.
3439 // g := length of rectangle Q.
3440 g = dx;
3441 // c := |CD| (on x-axis).
3442 c = dx - (float)(xp + 2 - (imgDim/2 + Xptr[z+2] +
3443 (bin+1)*shift_x));
3444 // Rectangle Q - triangle c*h (h = 1).
3445 eps2 = g - c/2;
3446 } else { // Case 9.
3447 // c := |FC|
3448 c = (float)(xp + 2 - (imgDim/2 + Xptr[z+2] +
3449 (bin+1)*shift_x));
3450 // d := |FD|
3451 d = (float)(floor(Yptr[xp + 2] + (bin+1)*shift_y) +
3452 2 - (Yptr[xp + 2] + (bin+1)*shift_y));
3453 // Rectangle Q - triangle CFD.
3454 eps2 = 1 - c*d/2;
3455 }
3456 }
3457
3458 // Calculate area on pixel in place (xp+1,yp).
3459 dx = (float)(xp + 2 - (imgDim/2 + Xptr[z] +
3460 (bin+1)*shift_x));
3461 if(dx < 1) { // Case 10.
3462 // g := length of rectangle Q.
3463 g = dx;
3464 // c := |CD| (on x-axis).
3465 c = dx - (float)(xp + 2 - (imgDim/2 + Xptr[z+1] +
3466 (bin+1)*shift_x));
3467 // Rectangle Q - triangle c*h (h = 1).
3468 eps3 = g - c/2;
3469 } else { // Case 9.
3470 // c := |FC|
3471 c = (float)(xp + 2 - (imgDim/2 + Xptr[z+1] +
3472 (bin+1)*shift_x));
3473 // d := |FD|
3474 d = (float)(floor(Yptr[xp + 2] + (bin+1)*shift_y) +
3475 1 - (Yptr[xp + 2] + (bin+1)*shift_y));
3476 // Rectangle Q - triangle CFD.
3477 eps3 = 1 - c*d/2;
3478 }
3479 }
3480 } else { // Case 5. (g < 1)
3481 // c := |DC|.
3482 c = g - (imgDim/2 + Xptr[z+1] + (bin+1)*shift_x - xp);
3483 // d := heigth
3484 d = 1;
3485
3486 eps1 = g*h - (a*b + c*d)/2;
3487 eps2 = 0;
3488 eps3 = 0;
3489 }
3490 } else { // Case 6 (h <= 1).
3491 // g := legth of rectangle R
3492 g = b + shift_x;
3493 if(g > 1) // Should always be < 1 for angles in [0,pi/4)
3494 g = 1;
3495
3496 eps1 = (g*h - a*b)/2;
3497 eps2 = 0;
3498 eps3 = 0;
3499 }
3500 } else { // 2. PART. Cases 2,7 and 8. (dy >= 1).
3501
3502 // a := |HA|
3503 a = 1;
3504
3505 // b := |HB| (>=1)
3506 b = dx - (float)(Xptr[z+1] + bin*shift_x + imgDim/2 - xp);
3507
3508 // h := heigth of rectangle R
3509 h = 1;
3510
3511 // g := length of rectangle R
3512 g = dx + shift_x;
3513
3514 if(g > 1){ // Cases 2 and 8.
3515 g = 1 - (float)(Xptr[z+1] + bin*shift_x + imgDim/2 - xp);
3516 xp2 = floor(Xptr[z+1] + (bin+1)*shift_x) + imgDim/2;
3517 if(xp == xp2){ // Case 8.
3518 // c := |FC|
3519 c = (float)(xp + 1 - (imgDim/2 + Xptr[z+1] +
3520 (bin+1)*shift_x));
3521 // d := |FD|
3522 d = (float)(floor(Yptr[xp + 1] + (bin+1)*shift_y) + 1 -
3523 (Yptr[xp + 1] + (bin+1)*shift_y));
3524 eps1 = g*h - (a*b + c*d)/2;
3525 eps2 = 0;
3526 // Lower triangle on the next pixel (x+1,y).
3527 eps3 = (1 - d)*((Xptr[z] + (bin+1)*shift_x + imgDim/2)
3528 - (xp+1))/2;
3529 } else { // Case 2.
3530 // c=d=0.
3531 eps1 = g*h - a*b/2;
3532 /* Pixel in place (xp+1,yp-1) should have been found in
3533 the previous step. */
3534 eps2 = 0;
3535
3536 // Calculate area on pixel in place (xp+1,yp).
3537 dx = (float)((imgDim/2 + Xptr[z] + (bin+1)*shift_x) - (xp+1));
3538 if(dx < 1){ // Case 10 (trapezium).
3539 // g := bottom of trapezium Q.
3540 g = dx;
3541 // c := top of trapezium Q.
3542 c = (float)((imgDim/2 + Xptr[z+1] + (bin+1)*shift_x) -
3543 (xp+1));
3544 // Area of trapezium Q. Heigth = 1.
3545 eps3 = (g + c)/2;
3546 } else { // Case 9.
3547 // c := |FC|
3548 c = (float)(xp + 2 - (imgDim/2 + Xptr[z+1] +
3549 (bin+1)*shift_x));
3550 // d := |FD|
3551 d = (float)(floor(Yptr[xp + 2] + (bin+1)*shift_y) + 1 -
3552 (Yptr[xp + 2] + (bin+1)*shift_y));
3553 // Rectangle Q - triangle CFD.
3554 eps3 = 1 - c*d/2;
3555 }
3556 }
3557 } else { // Case 7. (g < = 1)
3558 // Area of the parallelogram R.
3559 eps1 = sdist/cosinus;
3560 eps2 = 0;
3561 eps3 = 0;
3562 }
3563 }
3564 if(eps1 <= 0 || eps1 > 1) {
3565 errors++;
3566 printf("Error: eps1 = %f \n",eps1);
3567 eps1 = fabs(eps1);
3568 }
3569 if(eps2 < 0 || eps2 > 1){
3570 errors++;
3571 eps2 = fabs(eps2);
3572 }
3573 if(eps3 < 0 || eps3 > 1){
3574 errors++;
3575 eps1 = fabs(eps3);
3576 }
3577 if(!eps2 && !eps3){ // Cases 5,6 and 7.
3578 // Put coordinates and factors in the list.
3579 coptr[pix][0] = xp;
3580 coptr[pix][1] = yp;
3581 facptr[pix] = (unsigned short int)(scale*eps1);
3582 pix++;
3583 // Look for minimal and maximal factor.
3584 if(min>eps1) min=eps1;
3585 if(max<eps1) max=eps1;
3586 sqr_sum += eps1*eps1;
3587 sum += eps1;
3588 } else{
3589 if(!eps2){ // <=> eps3 != 0 & eps2 = 0 <=> Cases 3,4 and 8.
3590 if(xp + 1 < imgDim && xn - 1 >= 0){
3591 // Put coordinates and factors in the list.
3592 coptr[pix][0] = xp;
3593 coptr[pix][1] = yp;
3594 facptr[pix] = (unsigned short int)(scale*eps1);
3595
3596 // Look for minimal and maximal factor.
3597 if(min>eps1) min=eps1;
3598 if(max<eps1) max=eps1;
3599 sqr_sum += eps1*eps1;
3600 sum += eps1;
3601 pix++;
3602
3603 // Put coordinates and factors in the list.
3604 coptr[pix][0] = xp+1;
3605 coptr[pix][1] = yp;
3606 facptr[pix] = (unsigned short int)(scale*eps3);
3607
3608 // Look for minimal and maximal factor.
3609 if(min>eps3) min=eps3;
3610 if(max<eps3) max=eps3;
3611 sqr_sum += eps3*eps3;
3612 sum += eps3;
3613 pix++;
3614 }
3615 } else{ // <=> eps2!=0 && eps3!=0 <=> Case 3.
3616 if(xp+1 < imgDim && xn-1 >= 0 && yp-1 >= 0 && yn+1 < imgDim) {
3617 // Put coordinates and factors in the list.
3618 coptr[pix][0] = xp;
3619 coptr[pix][1] = yp;
3620 facptr[pix] = (unsigned short int)(scale*eps1);
3621
3622 // Look for minimal and maximal factor.
3623 if(min>eps1) min=eps1;
3624 if(max<eps1) max=eps1;
3625 sqr_sum += eps1*eps1;
3626 sum += eps1;
3627 pix++;
3628
3629 // Put coordinates and factors in the list.
3630 coptr[pix][0] = xp+1;
3631 coptr[pix][1] = yp;
3632 facptr[pix] = (unsigned short int)(scale*eps3);
3633
3634 // Look for minimal and maximal factor.
3635 if(min>eps3) min=eps3;
3636 if(max<eps3) max=eps3;
3637 sqr_sum += eps3*eps3;
3638 sum += eps3;
3639 pix++;
3640
3641 // Put coordinates and factors in the list.
3642 coptr[pix][0] = xp+1;
3643 coptr[pix][1] = yp-1;
3644 facptr[pix] = (unsigned short int)(scale*eps2);
3645
3646 // Look for minimal and maximal factor.
3647 if(min>eps2) min=eps2;
3648 if(max<eps2) max=eps2;
3649 sqr_sum += eps2*eps2;
3650 sum += eps2;
3651 pix++;
3652 }
3653 }
3654 }
3655
3656 }// Pixel is inside the FOV.
3657 }
3658 }
3659 /* Allocate memory in factor pointer (dynamically according to number
3660 of pixels intersected). */
3661 if(pix){
3662 mat->_factdata[half*view + bin]=
3663 (unsigned short int**)calloc(pix,sizeof(unsigned short int*));
3664 if(!mat->_factdata[half*view + bin]) return -1;
3665 }
3666
3667 // Allocate leaves.
3668 for(col=0; col<pix; col++){
3669 mat->_factdata[half*view + bin][col]=
3670 (unsigned short int*)calloc(3,sizeof(unsigned short int));
3671 if(!mat->_factdata[half*view + bin][col]) return -1;
3672 }
3673
3674 // Put now values in coordinates and factors array to result pointer.
3675 mat->fact = mat->_factdata;
3676 for(col=0; col<pix; col++){
3677 mat->fact[half*view + bin][col][0] = coptr[col][0]; // x-coodinate
3678 mat->fact[half*view + bin][col][1] = coptr[col][1]; // y-coordinate
3679 mat->fact[half*view + bin][col][2] = facptr[col]; // factor
3680 }
3681
3682 //Set also the number of pixels belonging to each row and square sums.
3683 mat->dime[half*view + bin]=pix;
3684 mat->factor_sqr_sum[half*view + bin]=sqr_sum;
3685
3686 }// END OF BIN-LOOP
3687
3688 }// End of view>0.
3689
3690 }// END OF VIEW LOOP
3691
3692 free(X);
3693 free(Y);
3694 free(coords);
3695 free(factors);
3696
3697 mat->min = min;
3698 mat->max = max;
3699 mat->factor_sum = sum;
3700 mat->status = PRMAT_STATUS_BS_OCCUPIED;
3701 return 0;
3702
3703}// END OF SETTING BASE LINES (EXACT AREA).
3704/*****************************************************************************/
3719int radonSetLUT(RADON *radtra, ELLIPSE *elli, PRMAT *mat)
3720{
3721 unsigned int **tmpData, **tmpptr; // coordinates of lines response.
3722 unsigned int *coords, *iptr;
3723 unsigned int col, row, pix=0, p=0, lors=0, view, bin; //counters
3724 unsigned int binNr, viewNr, imgDim, views, half, center;
3725 int ret=0;
3726 int xp, xn, yp, yn;
3727 float diam, sampledist;
3728
3729 //Check that projections are set.
3730 if(mat->status < PRMAT_STATUS_BS_OCCUPIED) return -1;
3731
3732 //Retrieve data from given radon transform object
3733 imgDim=radonGetID(radtra);
3734 binNr=radonGetNB(radtra);
3735 viewNr=radonGetNV(radtra);
3736 sampledist=radonGetSD(radtra);
3737 half=radonGetHI(radtra);
3738 center=radonGetCB(radtra);
3739 diam=sqrt(2);
3740
3741 /* Allocate memory for temporary list where we store coordinates of lines of
3742 response. Maximum number of lines (in one angle) hitting a pixel is
3743 [diameter of a pixel]/[sample distance]. */
3744 lors = ceil(diam/sampledist) + 1;
3745 tmpData = (unsigned int**)calloc(imgDim*imgDim,sizeof(unsigned int*));
3746 for(p=0; p<imgDim*imgDim; p++){
3747 tmpData[p]=(unsigned int*)calloc(lors*viewNr,sizeof(unsigned int));
3748 if(!tmpData[p]){
3749 fprintf(stderr, "Error: not enough memory.\n");
3750 return(4);
3751 }
3752 }
3753 tmpptr = tmpData;
3754
3755 /* Initialize the first entry in the list, to keep the number of entries
3756 in each row. And then fill the list from second entry. */
3757 for(p=0; p<imgDim*imgDim; p++) tmpptr[p][0]=0;
3758 views = viewNr/4;
3759 // Analyse the given projection matrix.
3760 for(view=0; view<views + 1; view++){
3761 for(bin=0; bin<half; bin++){
3762 row = view*half + bin;
3763 for(col=0; col<prmatGetPixels(mat,row); col++){
3764
3765 xp = prmatGetXCoord(mat,row,col);
3766 xn = imgDim - 1 - xp;
3767 yp = prmatGetYCoord(mat,row,col);
3768 yn = imgDim - 1 - yp;
3769
3770 if(xp != 0 || yp != 0){
3771 if(view == 0){
3772 /* Put coordinates of coincidence line in the next free place and
3773 increase the counter. */
3774 tmpptr[yp*imgDim + xp][++tmpptr[yp*imgDim + xp][0]] = bin;
3775 if(bin != center)
3776 tmpptr[yp*imgDim+(imgDim-1-xp)][++tmpptr[yp*imgDim+(imgDim-1-xp)][0]]=
3777 binNr-bin-1;
3778 tmpptr[(imgDim-1-xp)*imgDim+yp][++tmpptr[(imgDim-1-xp)*imgDim+yp][0]]=
3779 binNr*(viewNr/2) + bin;
3780 if(bin != center)
3781 tmpptr[xp*imgDim+yp][++tmpptr[xp*imgDim+yp][0]] =
3782 binNr*(viewNr/2) + (binNr-bin-1);
3783 }
3784
3785 if(view == viewNr/4) {
3786
3787 // Add img(x,y)*k to the raysum of LOR (view,bin)
3788 tmpptr[yp*imgDim + xp][++tmpptr[yp*imgDim + xp][0]] =
3789 (viewNr/4)*binNr + bin;
3790 // Add img(-x,-y)*k to the raysum of LOR (view,binNr-bin)
3791 if(bin != center)
3792 tmpptr[yn*imgDim + xn][++tmpptr[yn*imgDim + xn][0]] =
3793 (viewNr/4)*binNr + binNr - 1 - bin;
3794
3795 // Rotate the LOR 90 degrees, i.e. x->-x.
3796 // Case: pi/2 + theta = 3pi/4.
3797 // Add img(-y,x)*k to the raysum of LOR (viewNr/2+view,bin)
3798 tmpptr[xn*imgDim + yp][++tmpptr[xn*imgDim + yp][0]] =
3799 (viewNr/2 + viewNr/4)*binNr + bin;
3800 // Add img(y,-x)*k to the raysum of LOR (viewNr/2+view,binNr-bin)
3801 if(bin != center)
3802 tmpptr[xp*imgDim + yn][++tmpptr[xp*imgDim + yn][0]] =
3803 (viewNr/2 + viewNr/4)*binNr + binNr - 1 - bin;
3804 }
3805
3806 if(view != 0 && view != viewNr/4) {
3807
3808 // Add img(x,y)*k to the raysum of LOR (view,bin)
3809 tmpptr[yp*imgDim + xp][++tmpptr[yp*imgDim + xp][0]] =
3810 view*binNr + bin;
3811 if(bin != center)
3812 // Add img(-x,-y)*k to the raysum of LOR (view,binNr-bin)
3813 tmpptr[yn*imgDim + xn][++tmpptr[yn*imgDim + xn][0]] =
3814 view*binNr + binNr - 1 - bin;
3815
3816 // Mirror the LOR on line x=y, and on y-axis i.e x->y and y->-y.
3817 // Case: pi/2+theta
3818 // Add img(y,-x)*k to the raysum of LOR (viewNr/2+view,bin)
3819 tmpptr[xn*imgDim + yp][++tmpptr[xn*imgDim + yp][0]] =
3820 (viewNr/2 + view)*binNr + bin;
3821 // Add img(y,-x)*k to the raysum of LOR (viewNr/2+view,binNr-bin)
3822 if(bin != center)
3823 tmpptr[xp*imgDim + yn][++tmpptr[xp*imgDim + yn][0]] =
3824 (viewNr/2 + view)*binNr + binNr - 1 - bin;
3825
3826 // Mirror the original LOR on y-axis, i.e. x->-x
3827 // Case: pi-theta.
3828 // Add img(-x,y)*k to the raysum of LOR (viewNr-view,bin)
3829 tmpptr[yp*imgDim + xn][++tmpptr[yp*imgDim + xn][0]] =
3830 (viewNr - view)*binNr + bin;
3831 // Add img(x,-y)*k to the raysum of LOR (viewNr-view,binNr-bin)
3832 if(bin != center)
3833 tmpptr[yn*imgDim + xp][++tmpptr[yn*imgDim + xp][0]] =
3834 (viewNr-view)*binNr + binNr - 1 - bin;
3835
3836 // Mirror the LOR on line x=y, i.e. x->y.
3837 // Case: pi/2-theta
3838 // Add img(-y,-x)*k to the raysum of LOR (viewNr/2-view,bin)
3839 tmpptr[xn*imgDim + yn][++tmpptr[xn*imgDim + yn][0]] =
3840 (viewNr/2 - view)*binNr + bin;
3841 // Add img(y,x)*k to the raysum of LOR (viewNr/2-view,binNr-bin)
3842 if(bin != center)
3843 tmpptr[xp*imgDim + yp][++tmpptr[xp*imgDim + yp][0]] =
3844 (viewNr/2 - view)*binNr + binNr - 1 - bin;
3845 }
3846 }
3847 }
3848 }
3849 }
3850
3851 pix = 0;
3852 // Get the number of pixels inside the FOV.
3853 for(row = 0; row < imgDim; row++){
3854 for(col = 0; col < imgDim; col++){
3855 if(ellipseIsInside(elli,row,col))
3856 pix++;
3857 }
3858 }
3859
3860 // Analyse the tmp data array.
3861 p = 0; // index of a pixel inside the FOV
3862 coords = (unsigned int*)calloc(pix,sizeof(int));
3863 iptr = coords;
3864 for(row = 0; row < imgDim; row++){
3865 for(col = 0; col < imgDim; col++){
3866 if(ellipseIsInside(elli,row,col)){
3867 // Put the number of coincidence lines hitting this pixel into the list.
3868 iptr[p] = tmpptr[row*imgDim + col][0];
3869 p++; // increase pixel counter
3870 }
3871 }
3872 }
3873
3874 // Allocate memory for the look-up table.
3875 ret = prmatAllocate(mat,0,pix,coords);
3876 if(ret){
3877 free((unsigned int**)tmpData);
3878 free((int*)coords);
3879 return(ret);
3880 }
3881
3882 /* Put pixel coordinates, number of lines and the coordinates of
3883 the coincidence lines in the structure. */
3884 p = 0;
3885 tmpptr = tmpData;
3886 iptr = coords;
3887 for(row = 0; row < imgDim; row++) {
3888 for(col = 0; col < imgDim; col++) {
3889 if(ellipseIsInside(elli,row,col)) {
3890 // Put pixel coordinates in the list.
3891 mat -> lines[p][0] = row*imgDim + col;
3892 // Put the number of lines hitting this pixel in the list.
3893 mat -> lines[p][1] = iptr[p];
3894 // Put the coordinates of the coincidence lines in the list.
3895 for(lors = 0; lors < iptr[p]; lors++)
3896 mat -> lines[p][lors + 2] = tmpptr[row*imgDim + col][lors+1];
3897
3898 p++; // increase pixel counter
3899 }
3900 }
3901 }
3902
3903 printf("\n");
3904 mat->status = PRMAT_STATUS_LU_OCCUPIED;
3905
3906 free((unsigned int**)tmpData);
3907 free((int*)coords);
3908
3909 return 0;
3910}// END OF SETTING LOOK-UP TABLE.
3911/*****************************************************************************/
3925int radonSetLORS(RADON *radtra, ELLIPSE *elli, PRMAT *mat)
3926{
3927 unsigned int *coords, *iptr;
3928 unsigned int imgDim=128, binNr=256, viewNr=192, view, bin, pixNr=0;
3929 unsigned int row, col, rows, half, centerbin, p;
3930 int ret=0;
3931 int xp, xn, yp, yn;
3932 float fact, sqr_sum;
3933 PRMAT ext_mat; // temporary extented projection matrix
3934
3935 if(elli) {} // to prevent compiler warning about not being used.
3936
3937 printf("radonSetLors() started. \n");
3938
3939 //Retrieve data from given radon transform object
3940 imgDim=radonGetID(radtra);
3941 binNr=radonGetNB(radtra);
3942 viewNr=radonGetNV(radtra);
3943
3944 // Calculate and set center bin for the current geometrics.
3945 if((binNr%2) != 0){
3946 half = (binNr - 1)/2 + 1;
3947 centerbin = half - 1;
3948 }
3949 else{
3950 half = binNr/2;
3951 // In the case binNr is even there is no center bin.
3952 centerbin = -1;
3953 }
3954
3955 // Initiate extented projection matrix.
3956 prmatInit(&ext_mat);
3957
3958 // Prepare to allocate extented projection matrix.
3959 rows = viewNr*binNr;
3960 coords = (unsigned int*)calloc(rows,sizeof(int));
3961 iptr = coords;
3962 // Determine the number of hit pixels for EVERY row.
3963 p = viewNr/4;
3964 // Extend the projection matrix according to given base set.
3965 for(view=0; view<p + 1; view++){
3966 for(bin=0; bin<half; bin++){
3967 row = view*half + bin;
3968 pixNr = prmatGetPixels(mat,row);
3969 // Line in the base set.
3970 iptr[view*binNr + bin] = pixNr;
3971 // Symmetrical lines.
3972 if(bin != centerbin)
3973 iptr[view*binNr + binNr - 1 - bin] = pixNr;
3974
3975 if(view != 0 && view != viewNr/4){
3976 // Mirror the original LOR on y-axis, i.e. x->-x
3977 // Case: pi-theta.
3978 iptr[(viewNr - view)*binNr + bin] = pixNr;
3979 if(bin != centerbin)
3980 iptr[(viewNr-view)*binNr + binNr - 1 - bin] = pixNr;
3981
3982 // Mirror the LOR on line x=y, i.e. x->y.
3983 // Case: pi/2-theta
3984 iptr[(viewNr/2 - view)*binNr + bin] = pixNr;
3985 if(bin != centerbin)
3986 iptr[(viewNr/2 - view)*binNr + binNr - 1 - bin] = pixNr;
3987 }
3988
3989 // Mirror the LOR on line x=y, and on y-axis i.e x->y and y->-y.
3990 // Case: pi/2+theta
3991 iptr[(viewNr/2 + view)*binNr + bin] = pixNr;
3992 if(bin != centerbin)
3993 iptr[(viewNr/2 + view)*binNr + binNr - 1 - bin] = pixNr;
3994
3995 }
3996 }
3997
3998 // Allocate the extented projection matrix.
3999 ret = prmatAllocate(&ext_mat,1,rows,coords);
4000 if(ret){
4001 free(coords);
4002 return(ret);
4003 }
4004 printf("Allocation done \n");
4005
4006 // Extend the projection matrix according to given base set.
4007 for(view=0; view<p + 1; view++){
4008 for(bin=0; bin<half; bin++){
4009 row = view*half + bin;
4010 for(col=0; col<prmatGetPixels(mat,row); col++){
4011
4012 sqr_sum = prmatGetFactorSqrSum(mat,row);
4013 // Notice that we want the factor in unsigned short int.
4014 fact = mat->fact[row][col][2];
4015 xp = prmatGetXCoord(mat,row,col);
4016 xn = imgDim - 1 - xp;
4017 yp = prmatGetYCoord(mat,row,col);
4018 yn = imgDim - 1 - yp;
4019
4020 // Line in the base set.
4021 ext_mat.fact[view*binNr + bin][col][0] = xp;
4022 ext_mat.fact[view*binNr + bin][col][1] = yp;
4023 ext_mat.fact[view*binNr + bin][col][2] = fact;
4024 ext_mat.factor_sqr_sum[view*binNr + bin] = sqr_sum;
4025
4026 // Then symmetrical lines.
4027 if(bin != centerbin){
4028 ext_mat.fact[view*binNr + binNr - 1 - bin][col][0] = xn;
4029 ext_mat.fact[view*binNr + binNr - 1 - bin][col][1] = yn;
4030 ext_mat.fact[view*binNr + binNr - 1 - bin][col][2] = fact;
4031 ext_mat.factor_sqr_sum[view*binNr + binNr - 1 - bin] = sqr_sum;
4032 }
4033
4034 if(view != 0 && view != viewNr/4){
4035 // Mirror the original LOR on y-axis, i.e. x->-x
4036 // Case: pi-theta.
4037 ext_mat.fact[(viewNr - view)*binNr + bin][col][0] = xn;
4038 ext_mat.fact[(viewNr - view)*binNr + bin][col][1] = yp;
4039 ext_mat.fact[(viewNr - view)*binNr + bin][col][2] = fact;
4040 ext_mat.factor_sqr_sum[(viewNr - view)*binNr + bin] = sqr_sum;
4041
4042 if(bin != centerbin){
4043
4044 ext_mat.fact[(viewNr - view)*binNr +binNr - 1 - bin][col][0] = xp;
4045 ext_mat.fact[(viewNr - view)*binNr +binNr - 1 - bin][col][1] = yn;
4046 ext_mat.fact[(viewNr - view)*binNr +binNr - 1 - bin][col][2] = fact;
4047 ext_mat.factor_sqr_sum[(viewNr - view)*binNr +binNr - 1 - bin] =
4048 sqr_sum;
4049 }
4050
4051 // Mirror the LOR on line x=y, i.e. x->y.
4052 // Case: pi/2-theta
4053 ext_mat.fact[(viewNr/2 - view)*binNr + bin][col][0] = yn;
4054 ext_mat.fact[(viewNr/2 - view)*binNr + bin][col][1] = xn;
4055 ext_mat.fact[(viewNr/2 - view)*binNr + bin][col][2] = fact;
4056 ext_mat.factor_sqr_sum[(viewNr/2 - view)*binNr + bin] = sqr_sum;
4057
4058 if(bin != centerbin){
4059 ext_mat.fact[(viewNr/2 - view)*binNr +binNr-1-bin][col][0] = yp;
4060 ext_mat.fact[(viewNr/2 - view)*binNr +binNr-1-bin][col][1] = xp;
4061 ext_mat.fact[(viewNr/2 - view)*binNr +binNr-1-bin][col][2] = fact;
4062 ext_mat.factor_sqr_sum[(viewNr/2-view)*binNr+binNr-1-bin] = sqr_sum;
4063 }
4064 }
4065
4066 // Mirror the LOR on line x=y, and on y-axis i.e x->y and y->-y.
4067 // Case: pi/2+theta
4068 ext_mat.fact[(viewNr/2 + view)*binNr + bin][col][0] = yp;
4069 ext_mat.fact[(viewNr/2 + view)*binNr + bin][col][1] = xn;
4070 ext_mat.fact[(viewNr/2 + view)*binNr + bin][col][2] = fact;
4071 ext_mat.factor_sqr_sum[(viewNr/2 + view)*binNr + bin] = sqr_sum;
4072
4073 // Add img(y,-x)*k to the raysum of LOR (viewNr/2+view,binNr-bin)
4074 if(bin != centerbin){
4075 ext_mat.fact[(viewNr/2 + view)*binNr + binNr-1-bin][col][0] = yn;
4076 ext_mat.fact[(viewNr/2 + view)*binNr + binNr-1-bin][col][1] = xp;
4077 ext_mat.fact[(viewNr/2 + view)*binNr + binNr-1-bin][col][2] = fact;
4078 ext_mat.factor_sqr_sum[(viewNr/2 +view)*binNr +binNr-1-bin] = sqr_sum;
4079 }
4080 }
4081 }
4082 }
4083
4084
4085 // Empty old data from the given projection matrix.
4086 free((float*)mat->factor_sqr_sum);
4087
4088 for(row=0; row<mat->dimr; row++){ //every row
4089 for(col=0; col<mat->dime[row]; col++){ //every factor
4090 free((unsigned short int*)mat->_factdata[row][col]);
4091 }
4092 }
4093
4094 free((int*)mat->dime);
4095
4096 if(mat->dimr>0) free(mat->_factdata);
4097 mat->dimr=0;
4098
4099 // Allocate memory in mat structure for new extented matrix.
4100 ret = prmatAllocate(mat, 1, rows, coords);
4101 if(ret){
4102 free(coords);
4103 prmatEmpty(&ext_mat);
4104 return(ret);
4105 }
4106 printf("Allocation done \n");
4107
4108 // Copy the matrix from the temporary projection matrix.
4109 for(row=0; row<prmatGetRows(&ext_mat); row++){
4110 // Square sums.
4111 mat->factor_sqr_sum[row] = prmatGetFactorSqrSum(&ext_mat,row);
4112 for(col=0; col<prmatGetPixels(&ext_mat,row); col++){
4113 // Coordinates and factors.
4114 mat->fact[row][col][0] = prmatGetXCoord(&ext_mat,row,col);
4115 mat->fact[row][col][1] = prmatGetYCoord(&ext_mat,row,col);
4116 mat->fact[row][col][2] = ext_mat.fact[row][col][2];
4117 }
4118 }
4119
4120 // Release the temporary projection matrix.
4121 prmatEmpty(&ext_mat);
4122 free(coords);
4123
4124 return 0;
4125
4126
4127}//END OF radonSetLORS
4128/*****************************************************************************/
4129
4130/*****************************************************************************/
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
Header file for libtpcrec.
unsigned int prmatGetNV(PRMAT *mat)
Definition prmat.c:175
unsigned int prmatGetRows(PRMAT *mat)
Definition prmat.c:267
void prmatEmpty(PRMAT *mat)
Definition prmat.c:56
void prmatInit(PRMAT *mat)
Definition prmat.c:22
float prmatGetFactorSqrSum(PRMAT *mat, int row)
Definition prmat.c:409
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
int RADON_VERBOSE
Drive in verbose mode if not 0.
Definition radon.c:13
int RADON_TEST
Drive in test mode if not 0.
Definition radon.c:12
unsigned int prmatGetID(PRMAT *mat)
Definition prmat.c:197
int prmatAllocate(PRMAT *mat, int set, unsigned int rows, unsigned int *coords)
Definition prmat.c:105
float prmatGetFactor(PRMAT *mat, int row, int pix)
Definition prmat.c:342
unsigned int prmatGetPixels(PRMAT *mat, int row)
Definition prmat.c:282
unsigned int prmatGetNB(PRMAT *mat)
Definition prmat.c:186
int radonGetMO(RADON *radtra)
Definition radon.c:119
int radonFwdTransformEA(RADON *radtra, int set, int setNr, float *imgdata, float *scndata)
Definition radon.c:550
int radonSet(RADON *radtra, int mode, int imgDim, int viewNr, int binNr)
Definition radon.c:62
int radonGetID(RADON *radtra)
Definition radon.c:128
int radonGetHI(RADON *radtra)
Definition radon.c:169
int radonFwdTransform(RADON *radtra, int set, int setNr, float *imgdata, float *scndata)
Definition radon.c:216
int radonSetBases(RADON *radtra, ELLIPSE *elli, PRMAT *mat)
Definition radon.c:2602
int radonFwdTransformSA(RADON *radtra, int set, int setNr, float *imgdata, float *scndata)
Definition radon.c:1238
int radonGetNB(RADON *radtra)
Definition radon.c:148
int radonBackTransformPRM(PRMAT *mat, int set, int setNr, float *scndata, float *imgdata)
Definition radon.c:2503
int radonGetNV(RADON *radtra)
Definition radon.c:138
int radonFwdTransformPRM(PRMAT *mat, int set, int setNr, float *imgdata, float *scndata)
Definition radon.c:1328
float radonGetSin(RADON *radtra, int nr)
Definition radon.c:192
int radonSetLORS(RADON *radtra, ELLIPSE *elli, PRMAT *mat)
Definition radon.c:3925
int radonGetCB(RADON *radtra)
Definition radon.c:180
int radonSetLUT(RADON *radtra, ELLIPSE *elli, PRMAT *mat)
Definition radon.c:3719
int radonSetBasesEA(RADON *radtra, ELLIPSE *elli, PRMAT *mat)
Definition radon.c:2984
float radonGetSD(RADON *radtra)
Definition radon.c:159
int radonBackTransformEA(RADON *radtra, int set, int setNr, float *scndata, float *imgdata)
Definition radon.c:1696
void radonEmpty(RADON *radtra)
Definition radon.c:27
int radonBackTransformSA(RADON *radtra, int set, int setNr, float *scndata, float *imgdata)
Definition radon.c:2415
int radonBackTransform(RADON *radtra, int set, int setNr, float *scndata, float *imgdata)
Definition radon.c:1429
Ellipse on two dimensional plane.
Definition libtpcrec.h:37
float max
Maximal factor value in the projection matrix.
Definition libtpcrec.h:181
float min
Minimal factor value in the projection matrix.
Definition libtpcrec.h:179
char type
Scanner information on the prmat. 0=ECAT931 1=GE Advance.
Definition libtpcrec.h:166
int * prmatfov
Definition libtpcrec.h:177
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
float scaling_factor
Scaling factor for factors (notice that factors are stored in integers).
Definition libtpcrec.h:185
unsigned int * dime
Number of pixels hit by a line for every line.
Definition libtpcrec.h:204
unsigned int imgDim
Scanner geometrics, field imgDim.
Definition libtpcrec.h:172
float factor_sum
The sum of all factors in the projection matrix.
Definition libtpcrec.h:183
unsigned int dimr
Dimension of rows (lines of response) in the projection matrix.
Definition libtpcrec.h:200
unsigned int viewNr
Scanner geometrics, field viewNr.
Definition libtpcrec.h:168
int mode
Discretisation model utilised.
Definition libtpcrec.h:174
unsigned int binNr
Scanner geometrics, field binNr.
Definition libtpcrec.h:170
unsigned short int *** _factdata
Hidden pointer for the actual data.
Definition libtpcrec.h:210
int imgDim
Definition libtpcrec.h:261
int centerBin
Definition libtpcrec.h:269
int binNr
Definition libtpcrec.h:265
int viewNr
Definition libtpcrec.h:263
float * sines
Definition libtpcrec.h:274
char status
Definition libtpcrec.h:257
char mode
Definition libtpcrec.h:259
float sampleDist
Definition libtpcrec.h:271
int half
Definition libtpcrec.h:267