Скрипт DM, зачем преобразованию Фурье гаусса-Кенеля нужен модуль

Недавно я изучаю DM_Script для обработки изображений TEM. Мне понадобился процесс размытия по Гауссу, и я нашел тот, который называется «Размытие по Гауссу» в http://www.dmscripting.com/recent_updates.html

Этот код реализует алгоритм размытия по Гауссу, умножая быстрое преобразование Фурье (БПФ) исходного изображения на БПФ изображения с гауссовым ядром и, наконец, выполняя его обратное преобразование Фурье.

Вот часть кода,

// Carry out the convolution in Fourier space

compleximage fftkernelimg:=realFFT(kernelimg) (-> FFT of Gaussian-kernel image)
compleximage FFTSource:=realfft(warpimg) (-> FFT of source image)
compleximage FFTProduct:=FFTSource*fftkernelimg.modulus().sqrt()
realimage invFFT:=realIFFT(FFTProduct)

Я хочу спросить это сложное изображение FFTProduct: = FFTSource * fftkernelimg.modulus (). Sqrt ()

Почему для БПФ гауссовского ядра требуется '.modulus (). Sqrt ()' для свертки?

Это связано с тем, что преобразование Фурье гауссовой функции становится другой гауссовой функцией? Или это связано с неким ограничением дискретного преобразования Фурье?

Пожалуйста ответь мне спасибо


person Ryu    schedule 18.03.2017    source источник


Ответы (1)


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

Вращательный (действительный) гауссиан stand.dev. сигма должна быть преобразована в гауссианов вращательного движения 100% реальных значений 1 / сигма. Тем не менее, если вы сделаете это численно, вы увидите отклонения: просто попробуйте следующее:

number sigma = 30
number A0 = 1
realimage first := RealImage( "First", 8, 256, 256 )
first = A0 * exp( - (iradius**2/(2*sigma*sigma) ))
first.showimage()
complexImage second := FFT(first)
second.Showimage()

image nonZeroImaginaryMask = ( 0 != second.Imaginary() )
nonZeroImaginaryMask.Showimage()
nonZeroImaginaryMask.SetLimits(0,1)

Когда вы затем умножаете эти сложные изображения (перед обратным переносом), вы вносите еще больше ошибок. Используя модуль, можно гарантировать, что преобразованное в прямом направлении ядро ​​является чисто реальным и, следовательно, имеет лучшую кривую «демпфирования».

Лучшая реализация кода фильтрации БПФ фактически создала бы БПФ (гауссово) напрямую с std.dev равным 1 / сигма, поскольку это аналитически правильный результат. Выполнение БПФ ядра имеет смысл только в том случае, если ядро ​​(или его БПФ) не известно аналитически.

В общем: при реализации любой «математики» в программном коде стоит очень дорого обдумать это с числовыми ограничениями вычислений в затылке. По возможности сокращайте фактические вычисления (т. Е. Вычисляйте аналитически и используйте результат вместо того, чтобы полагаться на численные вычисления методом грубой силы) и старайтесь «изменить форму» уравнений, когда это возможно, например. избегайте больших сумм по множеству маленьких чисел, будьте осторожны при проверке точных числовых значений, старайтесь избегать выражений, которые очень чувствительны к небольшим числовым ошибкам и т. д.

person BmyGuest    schedule 19.03.2017