Вперед FFT изображение и назад FFT изображение, чтобы получить тот же результат
Я пытаюсь FFT изображение, используя библиотеку из http://www.fftw.org/ так что я могу сделать свертку в частотной области. Но я не могу понять, как это сделать. Чтобы понять, как это сделать, я пытаюсь переслать FFT изображение как массив pixelcolors, а затем назад FFT его, чтобы получить тот же массив pixelcolors. Вот что я делаю:--4-->
fftw_plan planR, planG, planB;
fftw_complex *inR, *inG, *inB, *outR, *outG, *outB, *resultR, *resultG, *resultB;
//Allocate arrays.
inR = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * width * width);
inG = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * width * width);
inB = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * width * width);
outR = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * width * width);
outG = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * width * width);
outB = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * width * width);
resultR = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * width * width);
resultG = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * width * width);
resultB = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * width * width);
//Fill in arrays with the pixelcolors.
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int currentIndex = ((y * width) + (x)) * 3;
inR[y * width + x][0] = pixelColors[currentIndex];
inG[y * width + x][0] = pixelColors[currentIndex + 1];
inB[y * width + x][0] = pixelColors[currentIndex + 2];
}
}
//Forward plans.
planR = fftw_plan_dft_2d(width, width, inR, outR, FFTW_FORWARD, FFTW_MEASURE);
planG = fftw_plan_dft_2d(width, width, inG, outG, FFTW_FORWARD, FFTW_MEASURE);
planB = fftw_plan_dft_2d(width, width, inB, outB, FFTW_FORWARD, FFTW_MEASURE);
//Forward FFT.
fftw_execute(planR);
fftw_execute(planG);
fftw_execute(planB);
//Backward plans.
planR = fftw_plan_dft_2d(width, width, outR, resultR, FFTW_BACKWARD, FFTW_MEASURE);
planG = fftw_plan_dft_2d(width, width, outG, resultG, FFTW_BACKWARD, FFTW_MEASURE);
planB = fftw_plan_dft_2d(width, width, outB, resultB, FFTW_BACKWARD, FFTW_MEASURE);
//Backward fft
fftw_execute(planR);
fftw_execute(planG);
fftw_execute(planB);
//Overwrite the pixelcolors with the result.
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int currentIndex = ((y * width) + (x)) * 3;
pixelColors[currentIndex] = resultR[y * width + x][0];
pixelColors[currentIndex + 1] = resultG[y * width + x][0];
pixelColors[currentIndex + 2] = resultB[y * width + x][0];
}
}
может кто-нибудь, пожалуйста, покажите мне пример того, как переслать FFT изображение, а затем назад FFT изображение с помощью FFTW, чтобы получить тот же результат? Я просмотрел много примеров, показывающих, как использовать FFTW для FFT, но я не могу понять, как это применимо к моей ситуации, когда у меня есть массив pixelcolors, представляющий изображение.
2 ответов
одна важная вещь, которую следует отметить, когда вы делаете вперед БПФ, а затем обратный БПФ, заключается в том, что это обычно приводит к масштабированию коэффициента N, применяемого к конечному результату, т. е. результирующие значения пикселей изображения должны быть разделены на N, чтобы соответствовать исходным значениям пикселей. (N - размер БПФ.) Таким образом, ваш выходной цикл должен выглядеть примерно так:
//Overwrite the pixelcolors with the result.
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int currentIndex = ((y * width) + (x)) * 3;
pixelColors[currentIndex] = resultR[y * width + x][0] / (width * height);
pixelColors[currentIndex + 1] = resultG[y * width + x][0] / (width * height);
pixelColors[currentIndex + 2] = resultB[y * width + x][0] / (width * height);
}
}
также обратите внимание, что вы, вероятно, хотите сделать real-to-complex FFT, а затем complex-to-real IFFT (несколько более эффективный с точки зрения как памяти, так и производительности). На данный момент, хотя кажется, что вы делаете комплекс к комплексу в обоих направлениях, что нормально, но вы неправильно заполняете входные массивы. Если вы собираетесь придерживаться сложного к сложному, то вы, вероятно, хотите изменить свой входной цикл на что-то вроде этого:
//Fill in arrays with the pixelcolors.
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int currentIndex = ((y * width) + (x)) * 3;
inR[y * width + x][0] = (double)pixelColors[currentIndex];
inR[y * width + x][1] = 0.0;
inG[y * width + x][0] = (double)pixelColors[currentIndex + 1];
inG[y * width + x][1] = 0.0;
inB[y * width + x][0] = (double)pixelColors[currentIndex + 2];
inB[y * width + x][1] = 0.0;
}
}
т. е. значения пикселей входят в реальные части комплексных входных значений, а мнимые части должны быть обнуленный.
еще одна вещь, чтобы отметить: когда вы в конечном итоге получите эту работу, вы обнаружите, что производительность ужасна - требуется много времени, чтобы создать план относительно времени, затраченного на фактический БПФ. Идея заключается в том, что вы создаете план только один раз, но используете его для выполнения многих БПФ. Таким образом, вы захотите отделить создание плана от фактического кода FFT и поместить его в процедуру инициализации или конструктор или что-то еще.
но если вы используете realToComplex или ComplexToRealFunction обратите внимание на то, что изображение будет храниться в матрице размеров [Высота x (Ширина/2 +1)], и если вы хотите сделать некоторые промежуточные вычисления в частотной области, они станут немного сложнее...