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 import gzip
36 import numpy as np
37 import time
38 import pyvision as pv
39 import scipy.interpolate as it
40 import scipy.ndimage as nd
41
43 '''
44 This class is used to handle range images. Originally written to handle
45 output from the Minolta Vivid sensors distributed with the Face Recognition
46 Grand Challenge 2004
47
48 This implementation currently can parse range images in ".abs" or ".abs.gz" format.
49
50 Very little type checking is done during parsing so unexpected exception or
51 unusual behavior may occur if the file is not formated properly.
52
53 This is a sample for the .abs file format:
54 480 rows
55 640 columns
56 pixels (flag X Y Z):
57 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ...
58 -999999.000000 -999999.000000 -999999.000000 -9999 ...
59 -999999.000000 -999999.000000 -999999.000000 -9999 ...
60 -999999.000000 -999999.000000 -999999.000000 -9999 ...
61
62 Author: David S. Bolme 2009
63 '''
64
66 '''
67 Reads a file containing range data.
68 '''
69
70 if filename[-7:] == '.abs.gz':
71
72 f = gzip.open(filename)
73
74 if filename[-4:] == '.abs':
75
76 f = open(filename)
77
78
79
80
81 rows = int(f.next().split()[0])
82 cols = int(f.next().split()[0])
83
84
85 self.width = cols
86 self.height = rows
87
88 self.flags = np.array([int(v) for v in f.next().split()]).reshape(rows,cols).transpose()
89 self.x = np.array([float(v) for v in f.next().split()]).reshape(rows,cols).transpose()
90 self.y = np.array([float(v) for v in f.next().split()]).reshape(rows,cols).transpose()
91 self.z = np.array([float(v) for v in f.next().split()]).reshape(rows,cols).transpose()
92
93
95 '''
96 @returns: xmin,xmax,ymin,ymax,zmin,zmax
97 '''
98
99 flags = np.array(self.flags.flatten(),dtype=np.bool)
100
101 X = self.x.flatten()[flags]
102 Y = self.y.flatten()[flags]
103 Z = self.z.flatten()[flags]
104 return min(X),max(X),min(Y),max(Y),min(Z),max(Z)
105
106
108 '''
109 @returns: the x coordinates.
110 '''
111 xmin,_,_,_,_,_ = self.getRange()
112
113 r,c = self.x.shape
114
115 flags = np.array(self.flags.flatten(),dtype=np.bool)
116 X = self.x.flatten().copy()
117 X[ flags != True ] = xmin
118
119 X = X.reshape(r,c)
120
121 return pv.Image(X)
122
123
125 '''
126 @returns: the y coordinates.
127 '''
128 _,_,ymin,_,_,_ = self.getRange()
129
130 r,c = self.x.shape
131
132 flags = np.array(self.flags.flatten(),dtype=np.bool)
133 Y = self.y.flatten().copy()
134 Y[ flags != True ] = ymin
135
136 Y = Y.reshape(r,c)
137
138 return pv.Image(Y)
139
140
142 '''
143 @returns: the z coordinates.
144 '''
145 _,_,_,_,zmin,_ = self.getRange()
146
147 r,c = self.x.shape
148
149 flags = np.array(self.flags.flatten(),dtype=np.bool)
150 Z = self.z.flatten().copy()
151 Z[ flags != True ] = zmin
152
153 Z = Z.reshape(r,c)
154
155 return pv.Image(Z)
156
158 '''
159 @returns: the missing value mask.
160 '''
161 _,_,_,_,zmin,_ = self.getRange()
162
163 r,c = self.x.shape
164
165 flags = np.array(self.flags.flatten(),dtype=np.bool)
166 Z = self.z.flatten().copy()
167 Z[ flags != True ] = zmin
168
169 Z = Z.reshape(r,c)
170
171 return pv.Image(Z)
172
174 '''
175 This function is used to interpolate missing data in the image.
176 '''
177 if approach == 'Smooth':
178
179
180 mask = np.array(self.flags,dtype=np.bool)
181
182 z = self.getZImage().asMatrix2D()
183 median = nd.median_filter(z,size=(15,15))
184
185 mask = mask.flatten()
186 z = z.flatten()
187 median = median.flatten()
188
189 z[ mask==False ] = median[ mask==False ]
190
191 if ilog != None:
192 ilog.log(pv.Image(median.reshape(self.width,self.height)),label="Median")
193 ilog.log(pv.Image(z.reshape(self.width,self.height)),label="ZMedian")
194
195 mask = mask.flatten()
196 z = z.flatten()
197 median = median.flatten()
198
199 for i in range(5):
200 tmp = z.copy()
201 smooth = nd.gaussian_filter(z.reshape(self.width,self.height),2.0).flatten()
202 z[ mask==False ] = smooth[ mask==False ]
203 print "Iteration:",i,(z-tmp).max(),(z-tmp).min()
204 ilog.log(pv.Image(z.reshape(self.width,self.height)),label="ZSmooth%02d"%i)
205 ilog.log(pv.Image((z-tmp).reshape(self.width,self.height)),label="ZSmooth%02d"%i)
206
207
208 if approach == 'RBF':
209 mask = np.array(self.flags,dtype=np.bool)
210 mask = mask.flatten()
211
212 x = np.arange(self.width).reshape(self.width,1)
213 x = x*np.ones((1,self.height))
214 x = x.flatten()
215
216 y = np.arange(self.height).reshape(1,self.height)
217 y = y*np.ones((self.width,1))
218 y = y.flatten()
219
220 z = self.z.copy()
221 z = z.flatten()
222
223 print "Coords:"
224 print len(mask)
225 print len(x[mask])
226 print len(y[mask])
227 print len(z[mask])
228
229
230 it.Rbf(x[mask],y[mask],z[mask])
231 pass
232
233
234
235
236
237
238 if __name__ == "__main__":
239 ilog = pv.ImageLog()
240 filename = "02463d562.abs.gz"
241 im = pv.Image("02463d563.ppm")
242
243 t = time.time()
244 ri = RangeImage(filename)
245 t = time.time() - t
246 print t
247
248 print ri.getRange()
249 ilog.log(ri.getXImage(),"X_Image")
250 ilog.log(ri.getYImage(),"Y_Image")
251 ilog.log(ri.getZImage(),"Z_Image")
252 ilog.log(im,"Color")
253
254 ri.populateMissingData(ilog=ilog)
255
256 ilog.show()
257