Processing math: 100%

Fourier Interpolation

Mathematics 2024. 3. 20. 21:37

0x<L 구간에서 일정한 간격(Δ=L/N)으로 샘플링된 데이터 {yk|k=0,...,N1}이 주어졌을 때 이들의  DFT 계수 {Yk|k=0,N1}을 이용하면 보간함수를 만들 수 있다.

y(x)=Y0+0<k<N/2(Yke+2πiLkx+YNke2πiLkx)+YN/2cos(πLNx)

마지막 항(Nyquist term)은 N이 짝수일 때만 더해진다. 구체적인 유도과정은 https://kipl.tistory.com/406에 있다. 샘플링 데이터가 실수인 경우는 YNk=(Yk)가 성립하므로 표현이 더 간단해진다.

 

FFT를 이용한 영상의 미분

주어진 함수 y(x)를 구간 0x<L에서 일정한 간격으로 샘플링해서 얻은 N개의 data {yn=y(nL/N)|n=0,1,...,N1}의 discrete Fourier transform(DFT) Yk는 $$ Y_ k = \frac {1}{N} \sum _{n = 0}^{N-1} y_n e^{ -\frac {2\p

kipl.tistory.com

 

x/Lx으로 하면 이 보간함수의 domain은 [0,1]로 제한된다.

// [x=0:1]
// Fourier coefficient (re[], im[]);
double FourierInterp(double x, std::vector<double>& re, std::vector<double>& im) {
    const int N = re.size();
    double fval = re[0];
    for (int k = N >> 1; k-->1;) {
        double ang = TWOPI * k * x;
        double cc = cos(ang);
        double ss = sin(ang);
        fval += re[k] * cc - im[k] * ss;     // 입력데이터가 실수인 경우:
        fval += re[N-k] * cc + im[N-k] * ss; // Y[N-k] = (Y[k])*
    }
    if (!(N&1))           //k = N/2 for even N;
        fval += re[N>>1] * cos(PI * N * x);
    return fval;
}

f(x)=sin2(x)cos(x)[0,3π] 구간에서 일정한 간격으로 얻은 30개의 데이터를 이용해서 보간함수를 만든다.

double f(double x) {
    return sin(x) * sin(x) * cos(x);
}
void Finterpolate() {
    const int nsamples = 30;
    std::vector<double> sample(nsamples);
    const double L = 3 * PI, dx = L / nsamples;
    for (int k = 0; k < nsamples; k++) sample[k] = f(k * dx);

    std::vector<double> re(sample.size(), 0), im(sample.size(), 0);
    // perform DFT;
    DFT(sample, re, im);

    FILE *fp = fopen("finp.txt", "w");
    const double N = 200;
    const double dy = dx * sample.size() / N;
    for (int k = 0; k < N; k++) { 
        double x = k * dy;
        fprintf(fp, "%f %f\n", x, FourierInterp(x / L, re, im));
    }
    fclose(fp);
}

728x90
,