2015-06-09 2 views
4

Я написал программу, которая загружает, сохраняет и выполняет fft и ifft на черно-белых изображениях png. После значительной отладки головной боли, я, наконец, получил некоторый последовательный вывод только для того, чтобы найти, что он исказил исходное изображение.Странный, но близкий fft и ifft изображения в C++

вход:

input

FFT:

fft

IFFT:

enter image description here

Насколько я испытал, то я пиксельные данные Каждый массив хранится и преобразуется правильно. Пиксели хранятся в двух массивах: «данные», которые содержат значение ч/б каждого пикселя и «complex_data», которое в два раза длиннее «данных» и сохраняет реальное значение ч/б и мнимые части каждого пикселя в переменных индексах. Мой алгоритм fft работает с массивом, структурированным как «complex_data». После кода команды чтения от пользователя, вот код в вопросе:

if (cmd == "fft") 
     {    
      if (height > width) size = height; 
      else size = width; 

      N = (int)pow(2.0, ceil(log((double)size)/log(2.0))); 

      temp_data = (double*) malloc(sizeof(double) * width * 2); //array to hold each row of the image for processing in FFT() 

      for (i = 0; i < (int) height; i++) 
      { 
       for (j = 0; j < (int) width; j++) 
       { 
        temp_data[j*2] = complex_data[(i*width*2)+(j*2)]; 
        temp_data[j*2+1] = complex_data[(i*width*2)+(j*2)+1]; 
       } 
       FFT(temp_data, N, 1); 
       for (j = 0; j < (int) width; j++) 
       { 
        complex_data[(i*width*2)+(j*2)] = temp_data[j*2]; 
        complex_data[(i*width*2)+(j*2)+1] = temp_data[j*2+1]; 
       } 
      } 
      transpose(complex_data, width, height); //tested 
      free(temp_data); 
      temp_data = (double*) malloc(sizeof(double) * height * 2); 
      for (i = 0; i < (int) width; i++) 
      { 
       for (j = 0; j < (int) height; j++) 
       { 
        temp_data[j*2] = complex_data[(i*height*2)+(j*2)]; 
        temp_data[j*2+1] = complex_data[(i*height*2)+(j*2)+1]; 
       } 
       FFT(temp_data, N, 1); 
       for (j = 0; j < (int) height; j++) 
       { 
        complex_data[(i*height*2)+(j*2)] = temp_data[j*2]; 
        complex_data[(i*height*2)+(j*2)+1] = temp_data[j*2+1]; 
       } 
      } 
      transpose(complex_data, height, width); 

      free(temp_data); 
      free(data); 

      data = complex_to_real(complex_data, image.size()/4); //tested 
      image = bw_data_to_vector(data, image.size()/4); //tested 
      cout << "*** fft success ***" << endl << endl; 



void FFT(double* data, unsigned long nn, int f_or_b){ // f_or_b is 1 for fft, -1 for ifft 

unsigned long n, mmax, m, j, istep, i; 
double wtemp, w_real, wp_real, wp_imaginary, w_imaginary, theta; 
double temp_real, temp_imaginary; 

// reverse-binary reindexing to separate even and odd indices 
// and to allow us to compute the FFT in place 

n = nn<<1; 
j = 1; 
for (i = 1; i < n; i += 2) { 
    if (j > i) { 
     swap(data[j-1], data[i-1]); 
     swap(data[j], data[i]); 
    } 
    m = nn; 
    while (m >= 2 && j > m) { 
     j -= m; 
     m >>= 1; 
    } 
    j += m; 
}; 

// here begins the Danielson-Lanczos section 

mmax = 2; 
while (n > mmax) { 
    istep = mmax<<1; 
    theta = f_or_b * (2 * M_PI/mmax); 
    wtemp = sin(0.5 * theta); 
    wp_real = -2.0 * wtemp * wtemp; 
    wp_imaginary = sin(theta); 
    w_real = 1.0; 
    w_imaginary = 0.0; 
    for (m = 1; m < mmax; m += 2) { 
     for (i = m; i <= n; i += istep) { 
      j = i + mmax; 
      temp_real = w_real * data[j-1] - w_imaginary * data[j]; 
      temp_imaginary = w_real * data[j] + w_imaginary * data[j-1]; 

      data[j-1] = data[i-1] - temp_real; 
      data[j] = data[i] - temp_imaginary; 
      data[i-1] += temp_real; 
      data[i] += temp_imaginary; 
     } 
     wtemp = w_real; 
     w_real += w_real * wp_real - w_imaginary * wp_imaginary; 
     w_imaginary += w_imaginary * wp_real + wtemp * wp_imaginary; 
    } 
    mmax=istep; 
}} 

Мой IFFT то же самое только с f_or_b установлен в -1 вместо 1. Моя программа вызывает быстрое преобразование Фурье() на каждой строке, транспонированные изображение, снова вызывает FFT() в каждой строке, затем переносит обратно. Может быть, ошибка с моим индексированием?

+3

Ничего общего с вашей проблемой, но вы должны действительно избегать malloc/free в C++ и вместо этого использовать new/delete. – Christophe

+0

Старые привычки от кодирования в c. –

+1

[Опасная привычка] (http://stackoverflow.com/questions/184537/in-what-cases-do-i-use-malloc-vs-new), как только вы используете данные не POD – Christophe

ответ

1

Не фактический ответ, как этот вопрос отладки только поэтому некоторые намеки вместо этого:

ваши результаты действительно плохо

он должен выглядеть следующим образом:

good results

  • первая строка - фактическая DFFT результат
  • Re,Im,Power усиливается постоянным иначе вы бы увидеть черное изображение
  • последнее изображение IDFFT оригинала не усиливается Re,IM результат
  • вторая линия та же, но результат DFFT обернута на половину размера изображения в кабине x,y, чтобы соответствовать общим результатам в большинстве DIP/CV тексты

Как вы можете увидеть, если вы I DFFT назад обернутых результатов результат не является правильным (шашка плата маска)

У вас есть только одно изображение в DFFT результате

  • это спектр мощности?
  • или вы забыли включить мнимую часть? просматривать или, возможно, также вычислять где-нибудь?

Ваш 1D ** DFFT работает? **

  • для реальных данных результат должен быть симметричным
  • проверить ссылки с моего комментария и сравнить результаты для некоторого образца 1D массив
  • отладки/отремонтировать 1D FFT первый и только затем перейти к следующему уровню
  • не забудьте проверить действительные и комплексные данные ...

ваш IDFFT выглядит BW (не серый) насыщенный

  • так вы усилить DFFT результаты, чтобы увидеть изображение и использовать, что для IDFFT вместо оригинала DFFT результат?
  • также проверить, если вы не округлять до целых чисел где-то по вычислению

остерегаться (I) DFFT перетоков/недостаточному

Если интенсивность пикселов изображения большие и разрешение изображения слишком то ваши вычисления могут привести к потере точности. Новейшие видели это на изображениях, но если ваше изображение HDR, то это возможно. Это общая проблема со сверткой, рассчитанная для больших многочленов DFFT.

0

Предложите посмотреть на статью http://www.yolinux.com/TUTORIALS/C++MemoryCorruptionAndMemoryLeaks.html

Christophe имеет хорошую точку, но он не так об этом не связано с проблемой, потому что кажется, что в наше время с помощью таНос вместо нового()/свободный() не инициализирует память или выбрать подходящий тип данных, который приведет всех проблем, перечисленных ниже: -

Возможно причины:

  1. Знак ряда меняющегося где-то, я видел подобные вопросы, когда платформа invok e был использован в dll, и значение передается значением вместо ссылки. Это вызвано тем, что память не обязательно пуста, поэтому, когда ваши данные изображения поступают в нее, будут выполняться логические вычисления по ее значениям. Я бы предположил, что вы убедитесь, что память пуста, прежде чем вы разместите свои данные изображения.

  2. Память, вращающаяся вправо (ROR в сборе langauge) или влево (ROL). Это произойдет, если используются типы данных, которые не обязательно совпадают, например. знаковое значение, вводящее неподписанный тип данных, или количество бит в одной переменной в другой.

  3. Данные теряются из-за значения без знака, вводящего подписанную переменную. Исходы составляют 1 бит, потому что он будет использоваться для определения отрицательного или положительного результата, или в крайних случаях, если произойдет удвоение количества, число будет перевернуто по смыслу, ищите два дополнения к википедии.

Также смотрите, как память должна быть очищена/назначена перед использованием. http://www.cprogramming.com/tutorial/memory_debugging_parallel_inspector.html

+0

В дальнейшем, пожалуйста, «отредактируйте» свой ответ, чтобы добавить дополнительную информацию, а не публиковать несколько ответов на один и тот же вопрос. – Matt

1

Спасибо всем за ваше мнение. Все, что связано с повреждением памяти, в то время как оно делает точку, не является корнем проблемы. Размеры данных, которые я разделяю, не слишком велики, и я освобождаю их в нужном месте. У меня было много практики с этим, изучая c. Проблема заключалась не в алгоритме fft, ни даже в его двумерной реализации.

Все, что я пропустил, было масштабирование по 1/(M * N) в самом конце моего кода ifft. Поскольку изображение равно 512x512, мне нужно было увеличить мой вывод ifft на 1/(512 * 512). Кроме того, мой fft выглядит как белый шум, потому что пиксельные данные не были перемасштабированы, чтобы соответствовать между 0 и 255.

+0

вы должны принять свой ответ (щелкните значок проверки возле счетчика голосов слева, чтобы другие четко и быстро увидели, что проблема решена (и как) – Spektre

 Смежные вопросы

  • Нет связанных вопросов^_^