void resample_2d_y ( /*************************************************************/ float **u, /* in : input image */ int nx, /* in : x dimension of input image */ int ny, /* in : y dimension of input image */ int bx, /* in : size of border in x-direction */ int by, /* in : size of border in y-direction */ float **u_out, /* out : output image */ int my /* in : y dimension of output image */ /*************************************************************/ ) /* resample a 2-D image in y-direction using area-based resampling */ { /****************************************************/ int i, j; /* loop variables */ float *uhelp, *vhelp; /* auxiliary vectors */ /****************************************************/ /* allocate memory */ malloc_multi (1,1,sizeof(float), ny+2, 0,0, &uhelp); malloc_multi (1,1,sizeof(float), my+2, 0,0, &vhelp); /* resample image columnwise in y-direction */ for (i=bx; i<nx+bx; i++) { /* initialsie left boundary of 1-D array with zero */ uhelp[0]=u[i][by]; /* copy current column in this 1-D array */ for (j=by; j<ny+by; j++) uhelp[j-by+1] = u[i][j]; /* initialise right boundary of this 1-D array with zero */ uhelp[ny+1]=u[i][ny+by-1]; /* resample this 1-D array */ resample_1d (uhelp, ny, my, vhelp); /* copy resmapled array in corresponding output column */ for (j=by; j<my+by; j++) u_out[i][j] = vhelp[j-by+1]; } /* free memory */ free_multi (1,1,sizeof(float), ny+2, 0,0, &uhelp); free_multi (1,1,sizeof(float), my+2, 0,0, &vhelp); return; }
int main(int argc, char** argv) { //Precompute FFT coefficients Wkn_fft = precompute_fft_coefficients(); Wkn_ifft = precompute_ifft_coefficients(); // Declare local variables int i, j, n; // Read in data // 1. allocate buffer space for the data. Holds Nx * Ny * Nf complex numbers. // 2. pass the filename and buffer to read_data which will read the file // into the buffer. printf("Reading Data ...\n"); tick(); complex* s = (complex*)safe_malloc(Nx * Ny * Nf * sizeof(complex), "Failed to allocate memory for radar data."); read_data(s, "scene_4.dat"); tock(); // Perform a single 2D FFT for each frequency // Each element s[i,j,n] is located at s[i * Ny * Nf + j * Nf + n] // Thus x-stride = Ny*Nf, y-stride = Nf, and z-stride = 1 // and each xy plane starts at s + 0 * Ny * Nf + 0 * Nf + n printf("Performing FFT\n"); tick(); for(n=0; n<Nf; n++) fft_2d(s + n, Nx, Ny, Ny*Nf, Nf); tock(); // Multiply each element in the frequency-domain signal by the // downward continuation phase operator. // 1. for each element (i,j,n) in the signal matrix // i in 0 ... Nx, j in 0 ... Ny, n in 0 ... Nf // 2. compute kx, ky, and k // kx = 2*pi/Dx * i/Nx if i < Nx/2, // 2*pi/Dx * (i-Nx)/Nx otherwise // ky = 2*pi/Dy * j/Ny if j < Ny/2, // 2*pi/Dy * (j-Ny)/Ny otherwise // w = 2*pi*(f0 + n*Df) // k = w/c // // 3. compute kz // kz = sqrt(4 * k^2 - kx^2 - ky^2 ) // 4. compute the phase delay // phi = exp(j * kz * z0) // 5. multiply the signal with the phase delay // where s(i,j,k) = s[i * Ny * Nf + j * Nf + n] printf("Performing Downward Continuation.\n"); tick(); for(i=0; i<Nx; i++) for(j=0; j<Ny; j++) for(n=0; n<Nf; n++){ float kx = i < Nx/2 ? 2*pi/Dx * i/Nx : 2*pi/Dx * (i - Nx)/Nx; float ky = j < Ny/2 ? 2*pi/Dy * j/Ny : 2*pi/Dy * (j - Ny)/Ny; float w = 2*pi*(f0 + n*Df); float k = w/c_speed; float kz = sqrt(4*k*k - kx*kx - ky*ky); complex phi = c_jexp(kz * z0); s[i * Ny * Nf + j * Nf + n] = c_mult(s[i * Ny * Nf + j * Nf + n], phi); } tock(); // Calculate the range of the Stolt interpolation indices. // The minimum angular frequency, w_min = 2*pi * f0 // The maximum angular frequency, w_max = 2*pi * (f0 + (N - 1)*Df) // From which the // minimum wavenumber, k_min = w_min / c // maximum wavenumber, k_max = w_max / c // The maximum wavenumber in the x direction, kx_max = 2*pi/Dx * 0.5 * (Nx-1)/Nx // The maximum wavenumber in the y direction, ky_max = 2*pi/Dy * 0.5 * (Ny-1)/Ny // The minimum wavenumbers in the x and y direction are assumed to be 0 // From which the // minimum wavenumber in the z direction, kz_min = sqrt(4*k_min^2 - kx_max^2 - ky_max^2) // maximum wavenumber in the z direction, kz_max = sqrt(4*k_max^2 - 0 - 0) float w_min = 2*pi * f0; float w_max = 2*pi * (f0 + (Nf - 1)*Df); float k_min = w_min / c_speed; float k_max = w_max / c_speed; float kx_max = 2*pi/Dx * 0.5 * (Nx-1)/Nx; float ky_max = 2*pi/Dy * 0.5 * (Ny-1)/Ny; float kz_min = sqrt(4*k_min*k_min - kx_max*kx_max - ky_max*ky_max); float kz_max = sqrt(4*k_max*k_max); // Perform Stolt Interpolation // 1. for each step in the x direction, i in 0 ... Nx // and each step in the y direction, j in 0 ... Ny // 2. compute kx, and ky as per step 2. above // 3. create float buffer of size Nf for storing the interpolation indices, n_interp // 4. for each step in frequency, n in 0 ... Nf // compute kz = kz_min + (kz_max - kz_min) * n/(Nf - 1) // 4. compute desired k = 0.5 * sqrt(kx^2 + ky^2 + kz^2) // 5. which corresponds to the interpolated array element // n_interp[n] = (c*k/(2*pi) - f0)/Df // 6. resample this line in s on interpolated indices n_interp // s[i,j,n] is at s[i * Ny * Nf + j * Nf + n] thus this line // starts at s + i * Ny * Nf + j * Nf + 0, has length Nf, and has stride 1 printf("Performing Stolt Interpolation.\n"); tick(); for(i=0; i<Nx; i++) for(j=0; j<Ny; j++){ float kx = i < Nx/2 ? 2*pi/Dx * i/Nx : 2*pi/Dx * (i - Nx)/Nx; float ky = j < Ny/2 ? 2*pi/Dy * j/Ny : 2*pi/Dy * (j - Ny)/Ny; float n_interp[Nf]; for(n=0; n<Nf; n++){ float kz = kz_min + (kz_max - kz_min) * n/(Nf - 1); float k = 0.5 * sqrt(kx*kx + ky*ky + kz*kz); n_interp[n] = (c_speed*k/(2*pi) - f0)/Df; } resample_1d(s + i*Ny*Nf + j*Nf, Nf, 1, n_interp); } tock(); // Perform a 3D IFFT on the signal // Each element s[i,j,n] is located at s[i * Ny * Nf + j * Nf + n] // Thus x-stride = Ny*Nf, y-stride = Nf, and z-stride = 1 printf("Performing IFFT.\n"); tick(); ifft_3d(s, Nx, Ny, Nf, Ny*Nf, Nf, 1); tock(); // End the simulation by writing out the computed signal and write it out to a file. // Pass the computed matrix and a output filename to write_data() printf("Writing data ...\n"); tick(); write_data(s, "scene_4.out"); tock(); printf("Done.\n"); // Free all the temporary memory free(s); }