주어진 함수
로 정의된다. 역변환(IDFT)은
이산적인 data
이다. 추가 위상이
그런데
따라서 주어진 샘플링 데이터
로 얻어진다(마지막 항은
로 계산된다(마지막 항은
처럼 쓸 수 있는데 이 식은
따라서 DFT를 이용해서 미분계수를 구하는 전체적인 알고리즘은
1. DFT로
2.
3.
위에서 구한 보간 함수를 이용하면 이차 미분 값도 DFT를 이용해서 구할 수 있다.
아래 그림은 6개의 주파수

void fftgrad1d() {
const double TWOPI = 8.0 * atan(1.0);
const int samples = 64;
double re[samples], im[samples];
const int nfreqs = 6;
const double freq[nfreqs] = {2, 5, 9, 11, 21, 29};
for ( int i = 0; i < samples; i++ ) {
double ti = double(i) / samples;
double signal = 0;
for ( int k = 0; k < nfreqs; k++ )
signal += (k + 1) * cos ( TWOPI * freq[k] * ti);
re[i] = signal;
im[i] = 0.;
}
// int fft1d(int dir, int nn, double x[], double y[]);
fft1d(1, samples, re, im);
const double norm = TWOPI / 1.0;
for (int i = 0; i < samples; i++) {
double rv = re[i];
double iv = im[i];
double fac = norm * double (i > samples / 2 ? i - samples: i);
if (i == samples / 2) fac = 0;
re[i] = - fac * iv;
im[i] = fac * rv;
}
//invers FFT: re[] stores derivatives.
fft1d(-1, samples, re, im);
}
이차원에서 DFT를 이용해서 gradient을 구하는 경우는 복소함수
임을 이용하면 된다.
영상(실수 함수)의 IDFT 식에 적용하면 미분 연산자가 우변에 전체적으로




void FFTGrad(CRaster& raster, CRaster& out) {
const double TWOPI = 8.0 * atan(1.0);
CSize sz = raster.GetSize();
int nx = sz.cx, ny = sz.cy;
int stride = nx << 1;
std::vector<double> data(stride * sz.cy);
for (int y = 0; y < ny; y++) {
BYTE *p = (BYTE *)raster.GetLinePtr(y);
double *re = &data[y * stride];
double *im = re + nx;
for (int x = 0; x < nx; x++) {
re[x] = *p++;
im[x] = 0;
}
}
// forward FFT(1): https://kipl.tistory.com/22
fft2d(&data[0], nx, ny, 1);
double normx = TWOPI / double(nx);
double normy = TWOPI / double(ny);
int hnx = nx >> 1;
int hny = ny >> 1;
for (int y = 0; y < ny; y++) {
double *re = &data[y * stride];
double *im = re + nx;
for (int x = 0; x < nx; x++) {
double rv = re[x];
double iv = im[x];
double xx = normx * double(x > hnx ? x - nx: x);
double yy = normy * double(y > hny ? y - ny: y);
if (x == hnx) xx = 0; // N = even;
if (y == hny) yy = 0;
re[x] = yy * rv + xx * iv;
im[x] = -xx * rv + yy * iv;
}
}
/* inverse FFT of {Y'_k} */
fft2d(&data[0], nx, ny, -1);
std::vector<double> mag(nx * ny);
double magmax = 0, magmin = 1.e+20;
for (int y = 0, k = 0; y < ny; y++) {
double *re = &data[y * stride];
double *im = re + nx;
for (int x = 0; x < nx; x++) {
double m = hypot(re[x], im[x]);
if (m > magmax) magmax = m;
if (m < magmin) magmin = m;
mag[k++] = m;
}
}
// stretch the magnitude;
for (int y = 0, k = 0; y < ny; y++)
for (int x = 0; x < nx; x++) {
double a = 255 * (mag[k++] - magmin) / (magmax - magmin);
out.SetPixel(x, y, 255-int(a));
}
}
'Image Recognition > Fundamental' 카테고리의 다른 글
Valley emphasis Otsu threshold (0) | 2022.02.23 |
---|---|
Image rotation by FFT (0) | 2022.02.18 |
SVD Fitting (0) | 2022.02.07 |
Color Histogram Equalization (4) | 2022.02.07 |
Least Squares Fitting of Ellipses (0) | 2022.01.27 |