|
| 1 | +#include <TH/TH.h> |
| 2 | +#define MAXX(x,y) ((x) > (y) ? (x) : (y)) |
| 3 | + |
| 4 | +int cpu_radon(THFloatTensor * P, THFloatTensor * R, THFloatTensor * img, THFloatTensor * theta) |
| 5 | +{ |
| 6 | + // Image size |
| 7 | + int M = THFloatTensor_size(img, 0); |
| 8 | + int N = THFloatTensor_size(img, 1); |
| 9 | + int m = THFloatTensor_size(theta, 0); |
| 10 | + int n = THFloatTensor_size(theta, 1); |
| 11 | + |
| 12 | + float * P_flat = THFloatTensor_data(P); |
| 13 | + float * R_flat = THFloatTensor_data(R); |
| 14 | + float * img_flat = THFloatTensor_data(img); |
| 15 | + float * theta_flat = THFloatTensor_data(theta); |
| 16 | + |
| 17 | + radonc(img_flat, theta_flat, M, N, m, n, P_flat, R_flat); |
| 18 | +} |
| 19 | + |
| 20 | +void radonc(float* Img, float* theta, int M, int N, int m, int n, float* P, float* R) |
| 21 | +{ |
| 22 | + int numAngles; /* number of theta values */ |
| 23 | + float *thetaPtr; /* pointer to theta values in radians */ |
| 24 | + float *pr1, *pr2; /* float pointers used in loop */ |
| 25 | + float deg2rad; /* conversion factor */ |
| 26 | + float temp; /* temporary theta-value holder */ |
| 27 | + int k; /* loop counter */ |
| 28 | + int xOrigin, yOrigin; /* center of image */ |
| 29 | + int temp1, temp2; /* used in output size computation */ |
| 30 | + int rFirst, rLast; /* r-values for first and last row of output */ |
| 31 | + int rSize; /* number of rows in output */ |
| 32 | + |
| 33 | + /* Get THETA values */ |
| 34 | + deg2rad = 3.14159265358979 / 180.0; |
| 35 | + numAngles = m * n; |
| 36 | + thetaPtr = new float[numAngles]; |
| 37 | + for (k = 0; k < numAngles; k++) |
| 38 | + *(thetaPtr++) = *(theta++) * deg2rad; |
| 39 | + |
| 40 | + /* Where is the coordinate system's origin? */ |
| 41 | + xOrigin = MAXX(0, (N-1)/2); |
| 42 | + yOrigin = MAXX(0, (M-1)/2); |
| 43 | + /* How big will the output be? */ |
| 44 | + temp1 = M - 1 - yOrigin; |
| 45 | + temp2 = N - 1 - xOrigin; |
| 46 | + rLast = (int) ceil(sqrt((float) (temp1*temp1+temp2*temp2))) + 1; |
| 47 | + rFirst = -rLast; |
| 48 | + rSize = rLast - rFirst + 1; |
| 49 | + |
| 50 | + R = new float[rSize]; |
| 51 | + for (k = rFirst; k <= rLast; k++) |
| 52 | + *(R++) = (float) k; |
| 53 | + |
| 54 | + /* Invoke main computation routines */ |
| 55 | + P = new float[rSize*numAngles]; |
| 56 | + radonckernel(P, I, thetaPtr, M, N, xOrigin, yOrigin, numAngles, rFirst, rSize); |
| 57 | + |
| 58 | +} |
| 59 | + |
| 60 | +void incrementRadon(float *pr, float pixel, float r) |
| 61 | +{ |
| 62 | + int r1; |
| 63 | + float delta; |
| 64 | + |
| 65 | + r1 = (int) r; |
| 66 | + delta = r - r1; |
| 67 | + pr[r1] += pixel * (1.0 - delta); |
| 68 | + pr[r1+1] += pixel * delta; |
| 69 | +} |
| 70 | + |
| 71 | +static void |
| 72 | +radonckernel(float *pPtr, float *iPtr, float *thetaPtr, int M, int N, |
| 73 | + int xOrigin, int yOrigin, int numAngles, int rFirst, int rSize) |
| 74 | +{ |
| 75 | + int k, m, n; /* loop counters */ |
| 76 | + float angle; /* radian angle value */ |
| 77 | + float cosine, sine; /* cosine and sine of current angle */ |
| 78 | + float *pr; /* points inside output array */ |
| 79 | + float *pixelPtr; /* points inside input array */ |
| 80 | + float pixel; /* current pixel value */ |
| 81 | + float *ySinTable, *xCosTable; |
| 82 | + /* tables for x*cos(angle) and y*sin(angle) */ |
| 83 | + float x,y; |
| 84 | + float r, delta; |
| 85 | + int r1; |
| 86 | + |
| 87 | + /* Allocate space for the lookup tables */ |
| 88 | + xCosTable = new float[2*N]; |
| 89 | + ySinTable = new float[2*M]; |
| 90 | + |
| 91 | + for (k = 0; k < numAngles; k++) { |
| 92 | + angle = thetaPtr[k]; |
| 93 | + pr = pPtr + k*rSize; /* pointer to the top of the output column */ |
| 94 | + cosine = cos(angle); |
| 95 | + sine = sin(angle); |
| 96 | + |
| 97 | + /* Radon impulse response locus: R = X*cos(angle) + Y*sin(angle) */ |
| 98 | + /* Fill the X*cos table and the Y*sin table. */ |
| 99 | + /* x- and y-coordinates are offset from pixel locations by 0.25 */ |
| 100 | + /* spaced by intervals of 0.5. */ |
| 101 | + for (n = 0; n < N; n++) |
| 102 | + { |
| 103 | + x = n - xOrigin; |
| 104 | + xCosTable[2*n] = (x - 0.25)*cosine; |
| 105 | + xCosTable[2*n+1] = (x + 0.25)*cosine; |
| 106 | + } |
| 107 | + for (m = 0; m < M; m++) |
| 108 | + { |
| 109 | + y = yOrigin - m; |
| 110 | + ySinTable[2*m] = (y - 0.25)*sine; |
| 111 | + ySinTable[2*m+1] = (y + 0.25)*sine; |
| 112 | + } |
| 113 | + |
| 114 | + pixelPtr = iPtr; |
| 115 | + for (n = 0; n < N; n++) |
| 116 | + { |
| 117 | + for (m = 0; m < M; m++) |
| 118 | + { |
| 119 | + pixel = *pixelPtr++; |
| 120 | + if (pixel != 0.0) |
| 121 | + { |
| 122 | + pixel *= 0.25; |
| 123 | + |
| 124 | + r = xCosTable[2*n] + ySinTable[2*m] - rFirst; |
| 125 | + incrementRadon(pr, pixel, r); |
| 126 | + |
| 127 | + r = xCosTable[2*n+1] + ySinTable[2*m] - rFirst; |
| 128 | + incrementRadon(pr, pixel, r); |
| 129 | + |
| 130 | + r = xCosTable[2*n] + ySinTable[2*m+1] - rFirst; |
| 131 | + incrementRadon(pr, pixel, r); |
| 132 | + |
| 133 | + r = xCosTable[2*n+1] + ySinTable[2*m+1] - rFirst; |
| 134 | + incrementRadon(pr, pixel, r); |
| 135 | + } |
| 136 | + } |
| 137 | + } |
| 138 | + } |
| 139 | + |
| 140 | + delete [] xCosTable; |
| 141 | + delete [] ySinTable; |
| 142 | +} |
0 commit comments