-
Notifications
You must be signed in to change notification settings - Fork 2
/
filter.py
114 lines (85 loc) · 3.13 KB
/
filter.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
""" Functions necessary for smoothing 2D terrain """
import sys, pickle, os.path, itertools, collections, errno
import numpy
try:
import scipy.ndimage
except ImportError, e:
pass
filters = {
'smooth': 'smooth',
'gauss': 'gsmooth',
}
def ftrim(a, cut):
"""
Takes a 2D DFT spectral result and removes frequencies
above the cut off frequency.
"""
b = a.copy()
mx, my = b.shape
for x in xrange(0, mx):
for y in xrange(0, my):
f = numpy.sqrt(min(pow(x, 2) + pow(y, 2),
pow(x - mx, 2) + pow(y, 2),
pow(x, 2) + pow(y - my, 2),
pow(x - mx, 2) + pow(y - my, 2)))
b[x, y] = 0 if f > cut else a[x, y]
return b
def fftrim(a, drop):
"""
Takes a 2D DFT spectral result and removes frequencies
according to the normalised drop off function.
"""
b = a.copy()
mx, my = b.shape
for x in xrange(0, mx):
for y in xrange(0, my):
f = numpy.sqrt(min(pow(x, 2) + pow(y, 2),
pow(x - mx, 2) + pow(y, 2),
pow(x, 2) + pow(y - my, 2),
pow(x - mx, 2) + pow(y - my, 2)))
b[x, y] = a[x, y]*drop(f)
return b
def pad(a, radius):
"""
Pad a 2D array with a radius number of equally sized
arrays on every side. Extends the values at the edges
of the original array in all directions.
"""
def samp(c, cm):
""" Take a sample from the edge of the input """
n = c - cm*radius
if n < 0:
return 0
elif n >= cm:
return cm - 1
else:
return n
mx, my = a.shape
factor = radius*2+1
b = numpy.empty((mx*factor, my*factor), a.dtype)
for x in xrange(0, mx*factor):
for y in xrange(0, my*factor):
b[x, y] = a[samp(x, mx)][samp(y, my)]
return b
def crop(a, radius=1):
"""
Crop a 2D array removing an radius number of equally
sized arrays from each edge only leaving the centre.
"""
my, mx = a.shape
mx = mx / (radius*2+1)
my = my / (radius*2+1)
b = numpy.empty((mx, my), a.dtype)
for n, x in enumerate(xrange(mx*radius, mx*(radius+1))):
b[n] = a[x][my*radius:my*(radius+1)]
return b
def smooth(a, cut, padder=pad, padding=1):
""" Smooth by cutting out high frequencies """
cut *= 1 + padding*2
return crop(numpy.real(numpy.fft.ifft2(ftrim(numpy.fft.fft2(padder(a, padding)), cut))), padding)
def fsmooth(a, drop, padder=pad, padding=1):
""" Smooth by cutting out high frequencies, drop function defines gradual drop-off """
return crop(numpy.real(numpy.fft.ifft2(fftrim(numpy.fft.fft2(padder(a, padding)), drop))), padding)
def gsmooth(a, sigma, padder=pad, padding=1):
""" Smooth with gaussian filter """
return scipy.ndimage.filters.gaussian_filter(a, sigma, mode='nearest')