1 | #!/usr/bin/python -tti
|
---|
2 | #
|
---|
3 | # Dominik Neise
|
---|
4 | # TU Dortmund
|
---|
5 | # March 2012
|
---|
6 | import numpy as np
|
---|
7 | import random
|
---|
8 | from coor import Coordinator # class which prepares next neighbor dictionary
|
---|
9 |
|
---|
10 | # just a dummy callback function
|
---|
11 | def _dummy( data, core_c, core, surv ):
|
---|
12 | pass
|
---|
13 |
|
---|
14 | class AmplitudeCleaner( object ):
|
---|
15 | """ Image Cleaning based on signal strength
|
---|
16 |
|
---|
17 | signal strength is a very general term here
|
---|
18 | it could be:
|
---|
19 | * max amplitude
|
---|
20 | * integral
|
---|
21 | * max of sliding sum
|
---|
22 | * ...
|
---|
23 | The Cleaning procedure or algorith is based on the
|
---|
24 | 3 step precedute on the diss of M.Gauk called 'absolute cleaning'
|
---|
25 | """
|
---|
26 |
|
---|
27 | def __init__(self, coreTHR, edgeTHR=None):
|
---|
28 | """ initialize object
|
---|
29 |
|
---|
30 | set the two needed thresholds
|
---|
31 | in case only one is given:
|
---|
32 | edgeTHR is assumen to be coreTHR/2.
|
---|
33 | """
|
---|
34 | self.coreTHR = coreTHR
|
---|
35 | if edgeTHR==None:
|
---|
36 | self.edgeTHR = coreTHR/2.
|
---|
37 | else:
|
---|
38 | self.edgeTHR = edgeTHR
|
---|
39 |
|
---|
40 | self.return_bool_mask = True # default value!
|
---|
41 |
|
---|
42 | # init coordinator
|
---|
43 | self.coordinator = Coordinator()
|
---|
44 | # retrieve next neighbor dict
|
---|
45 | self.nn = self.coordinator.nn
|
---|
46 |
|
---|
47 | def __call__( self, data, return_bool_mask=None , callback=_dummy ):
|
---|
48 | """ compute cleaned image
|
---|
49 |
|
---|
50 | the return value might be:
|
---|
51 | np.array of same shape as data (dtype=bool)
|
---|
52 | or
|
---|
53 | an np.array (dtype=int), which lengths is the number of
|
---|
54 | pixel which survived the cleaning, and which contains the CHIDs
|
---|
55 | of these survivors
|
---|
56 |
|
---|
57 | the default is to return the bool array
|
---|
58 | but if you set it once, differently, eg like this:
|
---|
59 | myAmplitudeCleaner.return_bool_mask = False
|
---|
60 | or like
|
---|
61 | myAmplitudeCleaner( mydata, False)
|
---|
62 |
|
---|
63 | it will be stored, until you change it again...
|
---|
64 | """
|
---|
65 | #shortcuts
|
---|
66 | coreTHR = self.coreTHR
|
---|
67 | edgeTHR = self.edgeTHR
|
---|
68 | nn = self.nn
|
---|
69 |
|
---|
70 | # once set, never forget :-)
|
---|
71 | if return_bool_mask != None:
|
---|
72 | self.return_bool_mask = return_bool_mask
|
---|
73 | return_bool_mask = self.return_bool_mask
|
---|
74 |
|
---|
75 | # these will hold the outcome of..
|
---|
76 | core_c = np.zeros( len(data), dtype=bool ) # ... step 1
|
---|
77 | core = np.zeros( len(data), dtype=bool ) # ... step 2
|
---|
78 | surv = np.zeros( len(data), dtype=bool ) # ... step 3
|
---|
79 | # It could be done in one variable, but for debugging and simplicity,
|
---|
80 | # I use more ...
|
---|
81 |
|
---|
82 | # this is Gauks step 1
|
---|
83 | core_c = data > coreTHR
|
---|
84 | # loop over all candidates and check if it has a next neighbor core pixel
|
---|
85 |
|
---|
86 | for c in np.where(core_c)[0]:
|
---|
87 | # loop over all n'eighbors of c'andidate
|
---|
88 | for n in nn[c]:
|
---|
89 | # if c has a neighbor, beeing also a candidate
|
---|
90 | # then c is definitely a core.
|
---|
91 | # Note: DN 13.03.12
|
---|
92 | # actually the neighbor is also now found to be core pixel,
|
---|
93 | # and still this knowledge is thrown away and later this
|
---|
94 | # neighbor itself is treated again as a c'andidate.
|
---|
95 | # this should be improved.
|
---|
96 | if core_c[n]:
|
---|
97 | core[c]=True
|
---|
98 | break
|
---|
99 | # at this moment step 2 is done
|
---|
100 |
|
---|
101 | # start of step 3.
|
---|
102 | # every core pixel is automaticaly a survivor, --> copy it
|
---|
103 | surv = core.copy()
|
---|
104 | for c in np.where(core)[0]:
|
---|
105 | for n in nn[c]:
|
---|
106 | # if neighbor is a core pixel, then do nothing
|
---|
107 | if core[n]:
|
---|
108 | pass
|
---|
109 | # if neighbor is over edgeTHR, it is lucky and survived.
|
---|
110 | elif data[n] > edgeTHR:
|
---|
111 | surv[n] = True
|
---|
112 |
|
---|
113 |
|
---|
114 | # calculate number of islands
|
---|
115 | surv_id = np.where(surv)[0]
|
---|
116 | # make a copy of survivors:
|
---|
117 | self.surv_copy = list(surv_id.copy())
|
---|
118 | surv_copy = self.surv_copy
|
---|
119 | # the first survivor belongs to the first island, by definition
|
---|
120 | self.islands = []
|
---|
121 | islands = self.islands
|
---|
122 | if len(surv_copy) > 0:
|
---|
123 | islands.append([surv_copy[0]])
|
---|
124 | del surv_copy[0]
|
---|
125 | nn_found = True
|
---|
126 | while len(surv_copy) > 0:
|
---|
127 | if nn_found:
|
---|
128 | nn_found = False
|
---|
129 | for i in islands[-1]:
|
---|
130 | #print 'i:',i
|
---|
131 | #print 'nn[i]:', nn[i]
|
---|
132 | #print 'type(nn[i]):', type(nn[i])
|
---|
133 | for n in nn[i]:
|
---|
134 | if n in surv_copy:
|
---|
135 | del surv_copy[surv_copy.index(n)]
|
---|
136 | islands[-1].append(n)
|
---|
137 | nn_found = True
|
---|
138 | #print 'islands'
|
---|
139 | #print islands, len(islands)
|
---|
140 | #print 'surv_copy'
|
---|
141 | #print surv_copy, len(surv_copy)
|
---|
142 | #print '*'*80
|
---|
143 | #print 'END of for i in islands[-1]:'
|
---|
144 | #print '*'*80
|
---|
145 |
|
---|
146 | else:
|
---|
147 | islands.append( [ surv_copy[0] ])
|
---|
148 | del surv_copy[0]
|
---|
149 | nn_found = True
|
---|
150 |
|
---|
151 | #print 'cleaner found' ,len(islands), 'islands'
|
---|
152 |
|
---|
153 | callback( data, core_c, core, surv)
|
---|
154 |
|
---|
155 | if return_bool_mask:
|
---|
156 | return surv
|
---|
157 | else:
|
---|
158 | return np.where(surv)[0]
|
---|
159 |
|
---|
160 |
|
---|
161 | def info(self):
|
---|
162 | """ print Cleaner Informatio
|
---|
163 |
|
---|
164 | """
|
---|
165 | print 'coreTHR: ', self.coreTHR
|
---|
166 | print 'edgeTHR: ', self.edgeTHR
|
---|
167 | print 'return_bool_mask:', self.return_bool_mask
|
---|
168 |
|
---|
169 | def _test_callback( data, core_c, core, surv ):
|
---|
170 | """ test callback functionality of AmplitudeCleaner"""
|
---|
171 | print 'core_c', np.where(core_c)[0], '<--', core_c.sum()
|
---|
172 | print 'core', np.where(core)[0], '<--', core.sum()
|
---|
173 | print 'surv', np.where(surv)[0], '<--', surv.sum()
|
---|
174 | print 'data', '*'*60
|
---|
175 | print data
|
---|
176 |
|
---|
177 |
|
---|
178 | def _test_cleaner():
|
---|
179 | """ test for class AmplitudeCleaner"""
|
---|
180 | from plotters import CamPlotter
|
---|
181 | NPIX = 1440
|
---|
182 | SIGMA = 1
|
---|
183 |
|
---|
184 | CORE_THR = 45
|
---|
185 | EDGE_THR = 18
|
---|
186 |
|
---|
187 | harvey_keitel = AmplitudeCleaner( CORE_THR, EDGE_THR)
|
---|
188 | harvey_keitel.info()
|
---|
189 | # if you wonder why the cleaner object is called is it is:
|
---|
190 | # http://www.youtube.com/watch?v=pf-Amvro2SY
|
---|
191 |
|
---|
192 | nn = Coordinator().nn
|
---|
193 |
|
---|
194 | testdata = np.zeros( NPIX )
|
---|
195 | #add some noise
|
---|
196 | testdata += 3
|
---|
197 |
|
---|
198 | # 'make' 3 doubleflowers
|
---|
199 | cores = []
|
---|
200 | for i in range(3):
|
---|
201 | cores.append( random.randint(0, NPIX-1) )
|
---|
202 | nene = nn[ cores[-1] ] # shortcut
|
---|
203 | luckynn = random.sample( nene, 1)[0] # shortcut
|
---|
204 | #print nene
|
---|
205 | #print luckynn
|
---|
206 | cores.append( luckynn )
|
---|
207 | edges = []
|
---|
208 | for c in cores:
|
---|
209 | for n in nn[c]:
|
---|
210 | if n not in cores:
|
---|
211 | edges.append(n)
|
---|
212 |
|
---|
213 | # add those doubleflowers to the testdata
|
---|
214 | for c in cores:
|
---|
215 | testdata[c] += 1.2*CORE_THR
|
---|
216 | for e in edges:
|
---|
217 | testdata[e] += 1.2*EDGE_THR
|
---|
218 |
|
---|
219 |
|
---|
220 | #cleaning_mask = harvey_keitel(testdata, callback=_test_callback)
|
---|
221 | cleaning_mask = harvey_keitel(testdata)
|
---|
222 |
|
---|
223 | plotall = CamPlotter('all')
|
---|
224 | plotclean = CamPlotter('cleaned')
|
---|
225 |
|
---|
226 | plotall(testdata)
|
---|
227 | plotclean(testdata, cleaning_mask)
|
---|
228 |
|
---|
229 |
|
---|
230 |
|
---|
231 | if __name__ == '__main__':
|
---|
232 | """ tests """
|
---|
233 |
|
---|
234 | _test_cleaner() |
---|