Я пытаюсь удалить синусоидальный шум на этом изображении:
Вот его спектр DFT (после применения логарифма и произвольного масштабирования интенсивности):
У меня уже есть фильтр Баттерворта для применения к этому изображению. Он будет выбивать среднечастотные пики. Я позабочусь о его масштабировании с [0..255] до [0..1.0] после загрузки. Здесь фильтр:
Результаты невелики:
Мои вопросы:
- Почему в изображении остается значительное количество шума?
- Почему результат темнее исходного изображения? Фильтр явно не касается термина DC, поэтому я ожидаю, что средняя интенсивность будет одинаковой.
- Почему фильтр выбирает только некоторые пики? Это из учебника, поэтому я склонен полагать, что это правильно, но есть другие пики в спектре - они также являются частью шума? Я попытался удалить их с помощью концентрических фильтров, но он не принес много пользы и затемнил изображение до неузнаваемости.
Я взял изображение (обрезанное) и отфильтровываю из книги Обработка цифровых изображений по Gonzalez и Woods. В их примере периодический шум полностью удаляется фильтрацией, а средняя интенсивность изображения остается неизменной.
Мой исходный код для загрузки изображения и фильтра, DFT, фильтрация, IDFT находится ниже:
import cv
def unshift_crop(comp, width, height):
result = cv.CreateImage((width, height), cv.IPL_DEPTH_8U, 1)
for x in range(height):
for y in range(width):
real, _, _, _ = cv.Get2D(comp, x, y)
real = int(real) * ((-1)**(x+y))
cv.Set2D(result, x, y, cv.Scalar(real))
return result
def load_filter(fname):
loaded = cv.LoadImage(fname, cv.CV_LOAD_IMAGE_GRAYSCALE)
flt = cv.CreateImage(cv.GetSize(loaded), cv.IPL_DEPTH_32F, 2)
width, height = cv.GetSize(loaded)
for i in range(width*height):
px, _, _, _ = cv.Get1D(loaded, i)
#cv.Set1D(flt, i, cv.Scalar(px/255.0, 0))
cv.Set1D(flt, i, cv.Scalar(px/255.0, px/255.0))
return flt
if __name__ == '__main__':
import sys
fname, filt_name, ofname = sys.argv[1:]
img = cv.LoadImage(fname, cv.CV_LOAD_IMAGE_GRAYSCALE)
width, height = cv.GetSize(img)
src = cv.CreateImage((width*2, height*2), cv.IPL_DEPTH_32F, 2)
dst = cv.CreateImage((width*2, height*2), cv.IPL_DEPTH_32F, 2)
cv.SetZero(src)
for x in range(height):
for y in range(width):
px, _, _, _ = cv.Get2D(img, x, y)
px = float(px) * ((-1) ** (x+y))
cv.Set2D(src, x, y, cv.Scalar(px, 0))
cv.DFT(src, dst, cv.CV_DXT_FORWARD)
flt = load_filter(filt_name)
cv.Mul(dst, flt, src)
cv.DFT(src, dst, cv.CV_DXT_INV_SCALE)
result = unshift_crop(dst, width, height)
cv.SaveImage(ofname, result)
ИЗМЕНИТЬ
В исходном источнике произошла ошибка, в которой фильтровальные мнимые компоненты были загружены как ноль. Это то, что заставило изображение результата выглядеть темнее, чем было на самом деле. Я исправил это и прокомментировал связанную строку.
Использование фиксированного источника и фильтра, предоставленного @0x69 (да, я знаю, что это не фильтр Баттерворта, но на этом этапе я счастлив попробовать что-нибудь), это результат:
Лучше, чем я должен был начать, но все же не так хорошо, как я надеюсь. Может ли кто-нибудь победить? Я подозреваю, что добавление большего количества выемок для выведения оставшихся пиков может принести пользу.
РЕДАКТИРОВАТЬ 2
Я связался с автором. Это их ответ:
Проблема заключается в том, что изображение, используемое в эксперимент был плавающей точкой, в то время как тот, который показан в книге (и оригинал, представленный в загрузок) - 8 бит. Это требуется для печати и т.д.
Чтобы дублировать эксперимент, вы должны начать с бесшумного изображения, а затем добавить свой собственный шум в он.