void GLFFTWater::computeHeightfield(float t) { const int hN = m_params.N / 2; const int hNp2 = m_params.N + 2; for(int y=0; y<m_params.N; y++) { int nk_x=m_params.N-1-y; for(int x=0; x<=hN; x++) { int nk_y=m_params.N-1-x; int idx = (nk_x)*(m_params.N)+nk_y; float pcos = cosf(m_w[y*m_params.N+x]*t); float psin = sinf(m_w[y*m_params.N+x]*t); // @TODO: check this math simplification ... float ht_r = m_htilde0[y*m_params.N+x][0]*pcos-m_htilde0[y*m_params.N+x][0]*psin+ m_htilde0[idx][0]*pcos-m_htilde0[idx][0]*psin; float ht_c = -2.0f*m_htilde0[idx][0]*psin; m_h[x*2+hNp2*y] = ht_r; m_h[x*2+1+hNp2*y] = ht_c; float kkx = m_kx[y*(hN+1)+x]; float kkz = m_kz[y*(hN+1)+x]; m_dx[x*2+hNp2*y] = -ht_c*kkx; m_dx[x*2+1+hNp2*y] = ht_r*kkx; m_dz[x*2+hNp2*y] = -ht_c*kkz; m_dz[x*2+1+hNp2*y] = ht_r*kkz; } } m_dx[m_params.N + hNp2*hN] = 0.f; m_dz[m_params.N + hNp2*hN] = 0.f; m_dx[m_params.N + hNp2*hN+1] = 0.f; m_dz[m_params.N + hNp2*hN+1] = 0.f; fftwf_execute_dft_c2r(m_fftplan, (fftwf_complex *)m_h, m_h); fftwf_execute_dft_c2r(m_fftplan, (fftwf_complex *)m_dx, m_dx); fftwf_execute_dft_c2r(m_fftplan, (fftwf_complex *)m_dz, m_dz); const float scale = m_params.L / (float)m_params.N * m_params.chop; for(int y=0; y<m_params.N;y++) { for(int x=0; x<m_params.N; x++) { if((x+y)%2==0) { m_heightmap[x+m_params.N*y].x = m_dx[x+hNp2*y]*scale; m_heightmap[x+m_params.N*y].y = m_h[x+hNp2*y]; m_heightmap[x+m_params.N*y].z = m_dz[x+hNp2*y]*scale; } else { m_heightmap[x+m_params.N*y].x = -m_dx[x+hNp2*y]*scale; m_heightmap[x+m_params.N*y].y = -m_h[x+hNp2*y]; m_heightmap[x+m_params.N*y].z = -m_dz[x+hNp2*y]*scale; } } } }
void fft_apply(PluginData *pd) { int w = pd->image_width, h = pd->image_height, pw = w/2+1; // physical width fftwf_complex *multiplied = (fftwf_complex*) fftwf_malloc(sizeof(fftwf_complex) * pw * h); float diagonal = sqrt(h*h + w*w)/2.0; // save current state of the curve curve_copy(&pd->curve_user, &pd->curve_fft); for(int channel=0; channel < pd->channel_count; channel++) { //skip DC value multiplied[0][0] = pd->image_freq[channel][0][0]; multiplied[0][1] = pd->image_freq[channel][0][1]; // apply convolution for (int i=1; i < pw*h; i++){ float dist = index_to_dist(i, pw, h); float coef = curve_get_value(dist_to_graph(dist), &pd->curve_fft); multiplied[i][0] = pd->image_freq[channel][i][0] * coef; multiplied[i][1] = pd->image_freq[channel][i][1] * coef; } // apply inverse FFT fftwf_execute_dft_c2r(pd->plan, multiplied, pd->image[channel]); // pack results for GIMP for(int x=0; x < w; x ++) { for(int y=0; y < h; y ++) { float v = pd->image[channel][y*w + x]; pd->img_pixels[(y*w + x)*pd->channel_count + channel] = CLAMPED(v,0,255); } } } fftwf_free(multiplied); }
void wavelet_prepare(PluginData *pd) { int w = pd->image_width, h = pd->image_height, pw = w/2+1; // physical width fftwf_complex *multiplied = (fftwf_complex*) fftwf_malloc(sizeof(fftwf_complex) * pw * h); float *image_temp = (float*)fftwf_malloc(sizeof(float) * w * h); float diagonal = sqrt(h*h + w*w)/2; pd->image_wavelet = (char*)fftwf_malloc(WAVELET_DEPTH * w * h * sizeof(char)); // printf("Wavelet layers occupy %lu MB.\n", (WAVELET_DEPTH * w * h * sizeof(short)) >> 20); // TODO: keep only the selected part of the image (->save memory) int lower = 0, peak = 1, upper = scale_to_dist(1, diagonal); for (int scale = 0; scale < WAVELET_DEPTH; scale ++) { float above = upper-peak, below = peak-lower; for (int i=0; i < pw*h; i++){ multiplied[i][0] = multiplied[i][1] = 0.0; } for (int i=0; i < pw*h; i++) { float dist = index_to_dist(i, pw, h); if (dist <= upper){ if (dist > lower){ if (dist > peak){ for(int channel=0; channel < pd->channel_count; channel ++) { multiplied[i][0] += pd->image_freq[channel][i][0]; multiplied[i][1] += pd->image_freq[channel][i][1]; } float coef = (1.0 - (dist-peak)/above) / pd->channel_count; multiplied[i][0] *= coef; multiplied[i][1] *= coef; } else { for(int channel=0; channel < pd->channel_count; channel ++) { multiplied[i][0] += pd->image_freq[channel][i][0]; multiplied[i][1] += pd->image_freq[channel][i][1]; } float coef = (1.0 - (peak-dist)/below) / pd->channel_count; multiplied[i][0] *= coef; multiplied[i][1] *= coef; } } } } // apply inverse FFT fftwf_execute_dft_c2r(pd->plan, multiplied, image_temp); for (int i=0; i < w*h; i++) { pd->image_wavelet[i*WAVELET_DEPTH + scale] = CLAMPED(image_temp[i], -127, 127); } lower = peak; peak = upper; upper = scale_to_dist(scale+2, diagonal); } fftwf_free(multiplied); fftwf_free(image_temp); }
void fftw1d_c2r(fftwplan_h h, complex float *po, int cdist, int nmemb, float *pr, int rdist, int repeat) { fftwplan_t *t = (fftwplan_t*)h; for(int i=0; i<repeat; i++) for(int j=0; j<nmemb; j++) fftwf_execute_dft_c2r(t->c2r, (fftwf_complex*)(po+j*cdist), pr+j*rdist); }
/****** fft_conv ************************************************************ PROTO void fft_conv(float *data1, float *fdata2, int *size) PURPOSE Optimized 2-dimensional FFT convolution using the FFTW library. INPUT ptr to the first image, ptr to the Fourier transform of the second image, image size vector. OUTPUT -. NOTES For data1 and fdata2, memory must be allocated for size[0]* ... * 2*(size[naxis-1]/2+1) floats (padding required). AUTHOR E. Bertin (IAP) VERSION 29/03/2013 ***/ void fft_conv(float *data1, float *fdata2, int *size) { float *fdata1p,*fdata2p, real,imag, fac; int i, npix,npix2; /* Convert axis indexing to that of FFTW */ npix = size[0]*size[1]; npix2 = ((size[0]/2) + 1) * size[1]; /* Forward FFT "in place" for data1 */ if (!fplan) { QFFTWF_MALLOC(fdata1, fftwf_complex, npix2); fplan = fftwf_plan_dft_r2c_2d(size[1], size[0], data1, (fftwf_complex *)fdata1, FFTW_ESTIMATE); } fftwf_execute_dft_r2c(fplan, data1, fdata1); /* Actual convolution (Fourier product) */ fac = 1.0/npix; fdata1p = (float *)fdata1; fdata2p = fdata2; #pragma ivdep for (i=npix2; i--;) { real = *fdata1p **fdata2p - *(fdata1p+1)**(fdata2p+1); imag = *(fdata1p+1)**fdata2p + *fdata1p**(fdata2p+1); *(fdata1p) = fac*real; *(fdata1p+1) = fac*imag; fdata1p+=2; fdata2p+=2; } /* Reverse FFT */ if (!bplan) bplan = fftwf_plan_dft_c2r_2d(size[1], size[0], (fftwf_complex *)fdata1, data1, FFTW_ESTIMATE); fftwf_execute_dft_c2r(bplan, fdata1, data1); // fftwf_execute(plan); return; }
// buf must be fftwf_malloc'd with size `sizeof(float) * fftLen` // // im should be approx offset from fix by hint. Point phaseCorr(const float *fix, const float *im, const Size &imSz, const fftwf_plan &plan, float *buf, const Point2f &hint, double &bestSqDist, const Mat &mask, Point &maxLoc, float &conf, const ConfGetter getConf, const char *saveIm) { unsigned fftLen = getFFTLen(imSz); for (unsigned i = 0; i < fftLen; i += 2) { float a = fix[i] * im[i] + fix[i + 1] * im[i + 1]; float b = fix[i + 1] * im[i] - fix[i] * im[i + 1]; float norm = sqrt(a * a + b * b); buf[i] = (norm != 0) ? (a / norm) : 0; buf[i + 1] = (norm != 0) ? (b / norm) : 0; //printf("wow %f, %f, %f, %f, %f, %f, %f, %f\n", fix[i], fix[i+1], im[i], im[i+1], a, b, buf[i], buf[i + 1]); } fftwf_execute_dft_c2r(plan, (fftwf_complex *)buf, buf); Mat bufMat(imSz.height, imSz.width + 2, CV_32FC1, buf); // bufMat = abs(bufMat); blur(bufMat, bufMat, Size(21, 21)); if (saveIm) { saveFloatIm(saveIm, bufMat); } minMaxLoc(bufMat, NULL, NULL, NULL, &maxLoc, mask); // there are four potential shifts corresponding to one peak // we choose the shift that is closest to the microscope's guess for the offset between the two Point bestPt; bestSqDist = 1e99; for (int dx = -imSz.width; dx <= 0; dx += imSz.width) { for (int dy = -imSz.height; dy <= 0; dy += imSz.height) { Point curPt(maxLoc.x + dx, maxLoc.y + dy); double curSqDist = getSqDist(curPt, hint); if (curSqDist < bestSqDist) { bestSqDist = curSqDist; bestPt = curPt; } } } conf = getConf(bufMat, maxLoc, bestSqDist); return bestPt; }
void profile_harm2phase(struct profile_harm *in, struct profile_phase *out, const struct cyclic_work *w) { fftwf_execute_dft_c2r(w->harm2phase, in->data, out->data); }