Commit 1ea30e1a8036001b46b0fccacc929cd8a1c4c190
1 parent
6f637a00
Exists in
master
and in
6 other branches
FIX: Again function to reduce vtkImageData with 3 dimension.
Showing
2 changed files
with
58 additions
and
40 deletions
Show diff stats
invesalius/data/imagedata_utils.py
... | ... | @@ -4,7 +4,27 @@ import vtk |
4 | 4 | # TODO: Test cases which are originally in sagittal/coronal orientation |
5 | 5 | # and have gantry |
6 | 6 | |
7 | -def ResampleMatrix(imagedata, xy_dimension): | |
7 | +def ResampleImage3D(imagedata, value): | |
8 | + """ | |
9 | + Resample vtkImageData matrix. | |
10 | + """ | |
11 | + spacing = imagedata.GetSpacing() | |
12 | + extent = imagedata.GetExtent() | |
13 | + size = imagedata.GetDimensions() | |
14 | + | |
15 | + width = float(size[0]) | |
16 | + height = float(size[1]/value) | |
17 | + | |
18 | + resolution = (height/(extent[1]-extent[0])+1)*spacing[1] | |
19 | + | |
20 | + resample = vtk.vtkImageResample() | |
21 | + resample.SetInput(imagedata) | |
22 | + resample.SetAxisMagnificationFactor(0, resolution) | |
23 | + resample.SetAxisMagnificationFactor(1, resolution) | |
24 | + | |
25 | + return resample.GetOutput() | |
26 | + | |
27 | +def ResampleImage2D(imagedata, xy_dimension): | |
8 | 28 | """ |
9 | 29 | Resample vtkImageData matrix. |
10 | 30 | """ |
... | ... | @@ -27,18 +47,16 @@ def ResampleMatrix(imagedata, xy_dimension): |
27 | 47 | y = 2 |
28 | 48 | |
29 | 49 | factor = xy_dimension/float(f+1) |
30 | - | |
50 | + | |
31 | 51 | resample = vtk.vtkImageResample() |
32 | 52 | resample.SetInput(imagedata) |
33 | 53 | resample.SetAxisMagnificationFactor(0, factor) |
34 | 54 | resample.SetAxisMagnificationFactor(1, factor) |
35 | 55 | resample.SetOutputSpacing(spacing[0] * factor, spacing[1] * factor, spacing[2]) |
36 | 56 | resample.Update() |
37 | - | |
38 | - | |
57 | + | |
58 | + | |
39 | 59 | return resample.GetOutput() |
40 | - | |
41 | - | |
42 | 60 | |
43 | 61 | def FixGantryTilt(imagedata, tilt): |
44 | 62 | """ | ... | ... |
invesalius/data/surface.py
... | ... | @@ -29,26 +29,26 @@ class SurfaceManager(): |
29 | 29 | - creating new surfaces; |
30 | 30 | - managing surfaces' properties; |
31 | 31 | - removing existing surfaces. |
32 | - | |
32 | + | |
33 | 33 | Send pubsub events to other classes: |
34 | 34 | - GUI: Update progress status |
35 | 35 | - volume_viewer: Sends surface actors as the are created |
36 | - | |
36 | + | |
37 | 37 | """ |
38 | 38 | def __init__(self): |
39 | 39 | self.actors_dict = {} |
40 | 40 | self.__bind_events() |
41 | - | |
41 | + | |
42 | 42 | def __bind_events(self): |
43 | 43 | ps.Publisher().subscribe(self.AddNewActor, 'Create surface') |
44 | 44 | ps.Publisher().subscribe(self.SetActorTransparency, |
45 | 45 | 'Set surface transparency') |
46 | 46 | ps.Publisher().subscribe(self.SetActorColour, |
47 | 47 | 'Set surface colour') |
48 | - | |
48 | + | |
49 | 49 | ps.Publisher().subscribe(self.OnChangeSurfaceName, 'Change surface name') |
50 | 50 | ps.Publisher().subscribe(self.OnShowSurface, 'Show surface') |
51 | - | |
51 | + | |
52 | 52 | def AddNewActor(self, pubsub_evt): |
53 | 53 | """ |
54 | 54 | Create surface actor, save into project and send it to viewer. |
... | ... | @@ -56,7 +56,7 @@ class SurfaceManager(): |
56 | 56 | imagedata, colour, [min_value, max_value] = pubsub_evt.data |
57 | 57 | quality='Optimal' |
58 | 58 | mode = 'CONTOUR' # 'GRAYSCALE' |
59 | - | |
59 | + | |
60 | 60 | if quality in const.SURFACE_QUALITY.keys(): |
61 | 61 | imagedata_resolution = const.SURFACE_QUALITY[quality][0] |
62 | 62 | smooth_iterations = const.SURFACE_QUALITY[quality][1] |
... | ... | @@ -64,8 +64,8 @@ class SurfaceManager(): |
64 | 64 | decimate_reduction = const.SURFACE_QUALITY[quality][3] |
65 | 65 | |
66 | 66 | if imagedata_resolution: |
67 | - imagedata = iu.ResampleMatrix(imagedata) | |
68 | - | |
67 | + imagedata = iu.ResampleImage3D(imagedata, imagedata_resolution) | |
68 | + | |
69 | 69 | pipeline_size = 3 |
70 | 70 | if decimate_reduction: |
71 | 71 | pipeline_size += 1 |
... | ... | @@ -74,7 +74,7 @@ class SurfaceManager(): |
74 | 74 | |
75 | 75 | # Update progress value in GUI |
76 | 76 | UpdateProgress = vu.ShowProgress(pipeline_size) |
77 | - | |
77 | + | |
78 | 78 | # Flip original vtkImageData |
79 | 79 | flip = vtk.vtkImageFlip() |
80 | 80 | flip.SetInput(imagedata) |
... | ... | @@ -103,7 +103,7 @@ class SurfaceManager(): |
103 | 103 | mcubes.AddObserver("ProgressEvent", lambda obj, evt: |
104 | 104 | UpdateProgress(contour, "Generating 3D surface...")) |
105 | 105 | polydata = mcubes.GetOutput() |
106 | - | |
106 | + | |
107 | 107 | # Reduce number of triangles (previous classes create a large amount) |
108 | 108 | # Important: vtkQuadricDecimation presented better results than |
109 | 109 | # vtkDecimatePro |
... | ... | @@ -112,10 +112,10 @@ class SurfaceManager(): |
112 | 112 | decimation.SetInput(polydata) |
113 | 113 | decimation.SetTargetReduction(decimate_reduction) |
114 | 114 | decimation.GetOutput().ReleaseDataFlagOn() |
115 | - decimation.AddObserver("ProgressEvent", lambda obj, evt: | |
115 | + decimation.AddObserver("ProgressEvent", lambda obj, evt: | |
116 | 116 | UpdateProgress(decimation, "Reducing number of triangles...")) |
117 | 117 | polydata = decimation.GetOutput() |
118 | - | |
118 | + | |
119 | 119 | # TODO (Paulo): Why do we need this filter? |
120 | 120 | #triangle = vtk.vtkTriangleFilter() |
121 | 121 | #triangle.SetInput(polydata) |
... | ... | @@ -127,7 +127,7 @@ class SurfaceManager(): |
127 | 127 | |
128 | 128 | # Smooth surface without changing structures |
129 | 129 | # Important: vtkSmoothPolyDataFilter presented better results than |
130 | - # vtkImageGaussianSmooth and vtkWindowedSincPolyDataFilter | |
130 | + # vtkImageGaussianSmooth and vtkWindowedSincPolyDataFilter | |
131 | 131 | if smooth_iterations and smooth_relaxation_factor: |
132 | 132 | smoother = vtk.vtkSmoothPolyDataFilter() |
133 | 133 | smoother.SetInput(polydata) |
... | ... | @@ -140,7 +140,7 @@ class SurfaceManager(): |
140 | 140 | smoother.AddObserver("ProgressEvent", lambda obj, evt: |
141 | 141 | UpdateProgress(smoother, "Smoothing surface...")) |
142 | 142 | polydata = smoother.GetOutput() |
143 | - | |
143 | + | |
144 | 144 | # Filter used to detect and fill holes. Only fill boundary edges holes. |
145 | 145 | #TODO: Hey! This piece of code is the same from |
146 | 146 | # polydata_utils.FillSurfaceHole, we need to review this. |
... | ... | @@ -161,7 +161,7 @@ class SurfaceManager(): |
161 | 161 | normals.AddObserver("ProgressEvent", lambda obj, evt: |
162 | 162 | UpdateProgress(normals, "Orienting normals...")) |
163 | 163 | polydata = normals.GetOutput() |
164 | - | |
164 | + | |
165 | 165 | #======= Temporary Code ======= |
166 | 166 | stl = vtk.vtkSTLWriter() |
167 | 167 | stl.SetFileTypeToBinary() |
... | ... | @@ -176,24 +176,24 @@ class SurfaceManager(): |
176 | 176 | stripper.SetInput(normals.GetOutput()) |
177 | 177 | stripper.PassThroughCellIdsOn() |
178 | 178 | stripper.PassThroughPointIdsOn() |
179 | - stripper.AddObserver("ProgressEvent", lambda obj, evt: | |
179 | + stripper.AddObserver("ProgressEvent", lambda obj, evt: | |
180 | 180 | UpdateProgress(stripper, "Stripping surface...")) |
181 | - | |
182 | - # Map polygonal data (vtkPolyData) to graphics primitives. | |
181 | + | |
182 | + # Map polygonal data (vtkPolyData) to graphics primitives. | |
183 | 183 | mapper = vtk.vtkPolyDataMapper() |
184 | 184 | mapper.SetInput(stripper.GetOutput()) |
185 | 185 | mapper.ScalarVisibilityOff() |
186 | 186 | |
187 | - # Represent an object (geometry & properties) in the rendered scene | |
187 | + # Represent an object (geometry & properties) in the rendered scene | |
188 | 188 | actor = vtk.vtkActor() |
189 | 189 | actor.SetMapper(mapper) |
190 | - | |
190 | + | |
191 | 191 | # Create Surface instance |
192 | 192 | surface = Surface() |
193 | 193 | surface.colour = colour |
194 | 194 | surface.polydata = polydata |
195 | 195 | |
196 | - | |
196 | + | |
197 | 197 | # Set actor colour and transparency |
198 | 198 | actor.GetProperty().SetColor(colour) |
199 | 199 | actor.GetProperty().SetOpacity(1-surface.transparency) |
... | ... | @@ -201,28 +201,28 @@ class SurfaceManager(): |
201 | 201 | # Append surface into Project.surface_dict |
202 | 202 | proj = Project() |
203 | 203 | proj.surface_dict[surface.index] = surface |
204 | - | |
204 | + | |
205 | 205 | # Save actor for future management tasks |
206 | 206 | self.actors_dict[surface.index] = actor |
207 | - | |
207 | + | |
208 | 208 | # Send actor by pubsub to viewer's render |
209 | 209 | ps.Publisher().sendMessage('Load surface actor into viewer', (actor)) |
210 | - | |
210 | + | |
211 | 211 | ps.Publisher().sendMessage('Update status text in GUI', |
212 | 212 | "Surface created.") |
213 | - | |
213 | + | |
214 | 214 | # The following lines have to be here, otherwise all volumes disappear |
215 | 215 | measured_polydata = vtk.vtkMassProperties() |
216 | 216 | measured_polydata.SetInput(polydata) |
217 | 217 | volume = measured_polydata.GetVolume() |
218 | 218 | surface.volume = volume |
219 | - | |
219 | + | |
220 | 220 | ps.Publisher().sendMessage('Update surface info in GUI', |
221 | - (surface.index, surface.name, | |
221 | + (surface.index, surface.name, | |
222 | 222 | surface.colour, surface.volume, |
223 | 223 | surface.transparency)) |
224 | - | |
225 | - | |
224 | + | |
225 | + | |
226 | 226 | def RemoveActor(self, index): |
227 | 227 | """ |
228 | 228 | Remove actor, according to given actor index. |
... | ... | @@ -233,17 +233,17 @@ class SurfaceManager(): |
233 | 233 | proj = Project() |
234 | 234 | proj.surface_dict.pop(index) |
235 | 235 | |
236 | - | |
236 | + | |
237 | 237 | def OnChangeSurfaceName(self, pubsub_evt): |
238 | 238 | index, name = pubsub_evt.data |
239 | 239 | proj = Project() |
240 | 240 | proj.surface_dict[index].name = name |
241 | - | |
241 | + | |
242 | 242 | def OnShowSurface(self, pubsub_evt): |
243 | 243 | index, value = pubsub_evt.data |
244 | 244 | print "OnShowSurface", index, value |
245 | 245 | self.ShowActor(index, value) |
246 | - | |
246 | + | |
247 | 247 | def ShowActor(self, index, value): |
248 | 248 | """ |
249 | 249 | Show or hide actor, according to given actor index and value. |
... | ... | @@ -253,7 +253,7 @@ class SurfaceManager(): |
253 | 253 | proj = Project() |
254 | 254 | proj.surface_dict[index].is_shown = value |
255 | 255 | ps.Publisher().sendMessage('Render volume viewer') |
256 | - | |
256 | + | |
257 | 257 | def SetActorTransparency(self, pubsub_evt): |
258 | 258 | """ |
259 | 259 | Set actor transparency (oposite to opacity) according to given actor |
... | ... | @@ -265,7 +265,7 @@ class SurfaceManager(): |
265 | 265 | proj = Project() |
266 | 266 | proj.surface_dict[index].transparency = value |
267 | 267 | ps.Publisher().sendMessage('Render volume viewer') |
268 | - | |
268 | + | |
269 | 269 | def SetActorColour(self, pubsub_evt): |
270 | 270 | """ |
271 | 271 | """ | ... | ... |