# # figuring out the correct forward/reverse procedure # # demonstrate FFT and inverse FFT on a grayscale image. # # need: # the fftw library installed as a shared library (on OS X, use "configure --enable-shared") # numpy # # I wrote this while trying to remove patterned noise from some scans of old photos. # I never quite figured out exactly *what* to do to the complex FFT image in the star-shaped # areas... I if make the slightest change at all to the array it will damage the image. # # Having since discovered ImageJ (which thankfully comes with source), I'm fairly certain that # those areas are just being set to zero (masked out), but I get different results. # # If you can explain it to me, send me email! # http://www.nightmare.com/~rushing/ # # Regardless, this shows how to use ctypes with the fftw library, and how cool numpy is. # import ctypes import numpy import time import pickle fftw3 = ctypes.cdll.LoadLibrary ("/usr/local/lib/libfftw3.3.dylib") def read_ch (f): while 1: ch = f.read (1) if ch == '#': f.readline() else: return ch def read_pgm_num (f): r = [] found = False while 1: ch = read_ch (f) if not found: if ch in ' \r\n\t': pass elif ch in '0123456789': found = True r.append (ch) else: raise ValueError else: if ch in '0123456789': r.append (ch) else: break return int (''.join (r)) def read_pgm_header (f): h0 = f.read (1) h1 = f.read (1) m = h0+h1 assert (m == 'P5') w = read_pgm_num (f) h = read_pgm_num (f) maxval = read_pgm_num (f) return w, h, maxval def image_test (pgm_file): global h, w, scale f = open (pgm_file, 'rb') w, h, maxval = read_pgm_header (f) pixels = w * h a = numpy.fromfile (f, dtype=numpy.int8, count=pixels) a = a.astype (numpy.double) a2 = numpy.zeros ((w,h/2+1), dtype=numpy.complex) print 'planning to plan...' plan = fftw3.fftw_plan_dft_r2c_2d (w, h, a.ctypes.data, a2.ctypes.data, 64) # print 'printing the plan...' # fftw3.fftw_print_plan (plan) print 'executing the plan...', plan fftw3.fftw_execute (plan) print 'done!' # now go backward... print 'reversing...' a3 = numpy.zeros ((w,h), dtype=numpy.double) plan = fftw3.fftw_plan_dft_c2r_2d (w, h, a2.ctypes.data, a3.ctypes.data, 64) fftw3.fftw_execute (plan) a4 = a3 / (w*h) print 'done!' a4 = a4.astype (numpy.int8) f = open ('fft_inv.pgm', 'wb') f.write ('P5\n%d\n%d\n255\n' % (w, h)) a4.tofile (f) f.close() if __name__ == '__main__': import sys image_test (sys.argv[1])