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