Сценарий Д.М., зачем преобразованию Фурье гауссовского кенеля нужен модуль

Недавно я выучил 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()' для свертки?

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

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

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)

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

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

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

Другие вопросы по тегам