Commit 516b0f05ceca0b92fd94ea19091e5fc719d753ff
1 parent
f17e9109
Exists in
mask_greatest_component
Tool to keep the greatest component from the mask
Showing
2 changed files
with
115 additions
and
78 deletions
Show diff stats
invesalius/data/slice_.py
@@ -16,10 +16,13 @@ | @@ -16,10 +16,13 @@ | ||
16 | # PARTICULAR. Consulte a Licenca Publica Geral GNU para obter mais | 16 | # PARTICULAR. Consulte a Licenca Publica Geral GNU para obter mais |
17 | # detalhes. | 17 | # detalhes. |
18 | #-------------------------------------------------------------------------- | 18 | #-------------------------------------------------------------------------- |
19 | +import heapq | ||
19 | import os | 20 | import os |
20 | import tempfile | 21 | import tempfile |
21 | 22 | ||
22 | import numpy | 23 | import numpy |
24 | +from scipy import ndimage | ||
25 | +from scipy.ndimage.measurements import label | ||
23 | import vtk | 26 | import vtk |
24 | from wx.lib.pubsub import pub as Publisher | 27 | from wx.lib.pubsub import pub as Publisher |
25 | 28 | ||
@@ -162,6 +165,8 @@ class Slice(object): | @@ -162,6 +165,8 @@ class Slice(object): | ||
162 | 165 | ||
163 | Publisher.subscribe(self._do_boolean_op, 'Do boolean operation') | 166 | Publisher.subscribe(self._do_boolean_op, 'Do boolean operation') |
164 | 167 | ||
168 | + Publisher.subscribe(self._keep_greatest_region, 'Keep greatest component') | ||
169 | + | ||
165 | Publisher.subscribe(self.OnExportMask,'Export mask to file') | 170 | Publisher.subscribe(self.OnExportMask,'Export mask to file') |
166 | 171 | ||
167 | Publisher.subscribe(self.OnCloseProject, 'Close project data') | 172 | Publisher.subscribe(self.OnCloseProject, 'Close project data') |
@@ -1114,6 +1119,7 @@ class Slice(object): | @@ -1114,6 +1119,7 @@ class Slice(object): | ||
1114 | if mask.matrix[n, 0, 0] == 0: | 1119 | if mask.matrix[n, 0, 0] == 0: |
1115 | m = mask.matrix[n, 1:, 1:] | 1120 | m = mask.matrix[n, 1:, 1:] |
1116 | mask.matrix[n, 1:, 1:] = self.do_threshold_to_a_slice(self.matrix[n-1], m, mask.threshold_range) | 1121 | mask.matrix[n, 1:, 1:] = self.do_threshold_to_a_slice(self.matrix[n-1], m, mask.threshold_range) |
1122 | + mask.matrix[n, 0, 0] = 1 | ||
1117 | 1123 | ||
1118 | mask.matrix.flush() | 1124 | mask.matrix.flush() |
1119 | 1125 | ||
@@ -1261,6 +1267,28 @@ class Slice(object): | @@ -1261,6 +1267,28 @@ class Slice(object): | ||
1261 | future_mask.was_edited = True | 1267 | future_mask.was_edited = True |
1262 | self._add_mask_into_proj(future_mask) | 1268 | self._add_mask_into_proj(future_mask) |
1263 | 1269 | ||
1270 | + def _keep_greatest_region(self, pubsub_evt): | ||
1271 | + self.keep_greatest_region(self.current_mask) | ||
1272 | + | ||
1273 | + def keep_greatest_region(self, mask): | ||
1274 | + self.do_threshold_to_all_slices(mask) | ||
1275 | + mask.matrix[0, :, :] = 1 | ||
1276 | + mask.matrix[:, 0, :] = 1 | ||
1277 | + mask.matrix[:, :, 0] = 1 | ||
1278 | + | ||
1279 | + m= mask.matrix[1:, 1:, 1:] | ||
1280 | + m[:] = (m > 128) * 255 | ||
1281 | + | ||
1282 | + labeled_array, num_features = label(m) | ||
1283 | + sizes = ndimage.sum(m,labeled_array,range(1,num_features+1)) | ||
1284 | + sl = zip(range(1, num_features + 1), sizes) | ||
1285 | + sl.sort(key=lambda x: x[1]) | ||
1286 | + tag = sl[-1][0] | ||
1287 | + m[labeled_array!=tag]=0 | ||
1288 | + | ||
1289 | + mask.was_edited = True | ||
1290 | + self.discard_all_buffers() | ||
1291 | + | ||
1264 | def apply_slice_buffer_to_mask(self, orientation): | 1292 | def apply_slice_buffer_to_mask(self, orientation): |
1265 | """ | 1293 | """ |
1266 | Apply the modifications (edition) in mask buffer to mask. | 1294 | Apply the modifications (edition) in mask buffer to mask. |
invesalius/gui/widgets/slice_menu.py
@@ -164,6 +164,11 @@ class SliceMenu(wx.Menu): | @@ -164,6 +164,11 @@ class SliceMenu(wx.Menu): | ||
164 | self.AppendMenu(-1, _("Projection type"), submenu_projection) | 164 | self.AppendMenu(-1, _("Projection type"), submenu_projection) |
165 | ###self.AppendMenu(-1, _("Image Tiling"), submenu_image_tiling) | 165 | ###self.AppendMenu(-1, _("Image Tiling"), submenu_image_tiling) |
166 | 166 | ||
167 | + self.kgc_id = new_id = wx.NewId() | ||
168 | + item = wx.MenuItem(self, new_id, u"Keep greatest component") | ||
169 | + self.AppendItem(item) | ||
170 | + | ||
171 | + | ||
167 | # It doesn't work in Linux | 172 | # It doesn't work in Linux |
168 | self.Bind(wx.EVT_MENU, self.OnPopup) | 173 | self.Bind(wx.EVT_MENU, self.OnPopup) |
169 | # In Linux the bind must be putted in the submenu | 174 | # In Linux the bind must be putted in the submenu |
@@ -207,86 +212,90 @@ class SliceMenu(wx.Menu): | @@ -207,86 +212,90 @@ class SliceMenu(wx.Menu): | ||
207 | 212 | ||
208 | def OnPopup(self, evt): | 213 | def OnPopup(self, evt): |
209 | id = evt.GetId() | 214 | id = evt.GetId() |
210 | - item = self.ID_TO_TOOL_ITEM[evt.GetId()] | ||
211 | - key = item.GetLabel() | ||
212 | - if(key in const.WINDOW_LEVEL.keys()): | ||
213 | - window, level = const.WINDOW_LEVEL[key] | ||
214 | - Publisher.sendMessage('Bright and contrast adjustment image', | ||
215 | - (window, level)) | ||
216 | - Publisher.sendMessage('Update window level value',\ | ||
217 | - (window, level)) | ||
218 | - Publisher.sendMessage('Update window and level text',\ | ||
219 | - "WL: %d WW: %d"%(level, window)) | ||
220 | - Publisher.sendMessage('Update slice viewer') | ||
221 | - | ||
222 | - #Necessary update the slice plane in the volume case exists | ||
223 | - Publisher.sendMessage('Render volume viewer') | ||
224 | - | ||
225 | - elif(key in const.SLICE_COLOR_TABLE.keys()): | ||
226 | - values = const.SLICE_COLOR_TABLE[key] | ||
227 | - Publisher.sendMessage('Change colour table from background image', values) | ||
228 | - Publisher.sendMessage('Update slice viewer') | ||
229 | - | ||
230 | - if sys.platform == 'linux2': | ||
231 | - for i in self.pseudo_color_items: | ||
232 | - it = self.pseudo_color_items[i] | ||
233 | - if it.IsChecked(): | ||
234 | - it.Toggle() | ||
235 | - | ||
236 | - item.Toggle() | ||
237 | - self.HideClutDialog() | ||
238 | - self._gen_event = True | ||
239 | - | ||
240 | - elif key in self.plist_presets: | ||
241 | - values = presets.get_wwwl_preset_colours(self.plist_presets[key]) | ||
242 | - Publisher.sendMessage('Change colour table from background image from plist', values) | ||
243 | - Publisher.sendMessage('Update slice viewer') | ||
244 | - | ||
245 | - if sys.platform == 'linux2': | ||
246 | - for i in self.pseudo_color_items: | ||
247 | - it = self.pseudo_color_items[i] | ||
248 | - if it.IsChecked(): | ||
249 | - it.Toggle() | ||
250 | - | ||
251 | - item.Toggle() | ||
252 | - self.HideClutDialog() | ||
253 | - self._gen_event = True | ||
254 | - | ||
255 | - elif(key in const.IMAGE_TILING.keys()): | ||
256 | - values = const.IMAGE_TILING[key] | ||
257 | - Publisher.sendMessage('Set slice viewer layout', values) | ||
258 | - Publisher.sendMessage('Update slice viewer') | ||
259 | - | ||
260 | - elif key in PROJECTIONS_ID: | ||
261 | - print 'Key', key | ||
262 | - pid = PROJECTIONS_ID[key] | ||
263 | - Publisher.sendMessage('Set projection type', pid) | ||
264 | - Publisher.sendMessage('Reload actual slice') | ||
265 | 215 | ||
266 | - elif key == _('Custom'): | ||
267 | - if self.cdialog is None: | ||
268 | - slc = sl.Slice() | ||
269 | - histogram = slc.histogram | ||
270 | - init = slc.matrix.min() | ||
271 | - end = slc.matrix.max() | ||
272 | - nodes = slc.nodes | ||
273 | - self.cdialog = ClutImagedataDialog(histogram, init, end, nodes) | ||
274 | - self.cdialog.Show() | ||
275 | - else: | ||
276 | - self.cdialog.Show(self._gen_event) | ||
277 | - | ||
278 | - if sys.platform == 'linux2': | ||
279 | - for i in self.pseudo_color_items: | ||
280 | - it = self.pseudo_color_items[i] | ||
281 | - if it.IsChecked(): | ||
282 | - it.Toggle() | ||
283 | - | ||
284 | - item.Toggle() | 216 | + if id == self.kgc_id: |
217 | + Publisher.sendMessage('Keep greatest component') | ||
218 | + Publisher.sendMessage('Reload actual slice') | ||
219 | + else: | ||
285 | item = self.ID_TO_TOOL_ITEM[evt.GetId()] | 220 | item = self.ID_TO_TOOL_ITEM[evt.GetId()] |
286 | - item.Check(True) | ||
287 | - self._gen_event = False | ||
288 | - | ||
289 | - evt.Skip() | 221 | + key = item.GetLabel() |
222 | + if(key in const.WINDOW_LEVEL.keys()): | ||
223 | + window, level = const.WINDOW_LEVEL[key] | ||
224 | + Publisher.sendMessage('Bright and contrast adjustment image', | ||
225 | + (window, level)) | ||
226 | + Publisher.sendMessage('Update window level value',\ | ||
227 | + (window, level)) | ||
228 | + Publisher.sendMessage('Update window and level text',\ | ||
229 | + "WL: %d WW: %d"%(level, window)) | ||
230 | + Publisher.sendMessage('Update slice viewer') | ||
231 | + | ||
232 | + #Necessary update the slice plane in the volume case exists | ||
233 | + Publisher.sendMessage('Render volume viewer') | ||
234 | + | ||
235 | + elif(key in const.SLICE_COLOR_TABLE.keys()): | ||
236 | + values = const.SLICE_COLOR_TABLE[key] | ||
237 | + Publisher.sendMessage('Change colour table from background image', values) | ||
238 | + Publisher.sendMessage('Update slice viewer') | ||
239 | + | ||
240 | + if sys.platform == 'linux2': | ||
241 | + for i in self.pseudo_color_items: | ||
242 | + it = self.pseudo_color_items[i] | ||
243 | + if it.IsChecked(): | ||
244 | + it.Toggle() | ||
245 | + | ||
246 | + item.Toggle() | ||
247 | + self.HideClutDialog() | ||
248 | + self._gen_event = True | ||
249 | + | ||
250 | + elif key in self.plist_presets: | ||
251 | + values = presets.get_wwwl_preset_colours(self.plist_presets[key]) | ||
252 | + Publisher.sendMessage('Change colour table from background image from plist', values) | ||
253 | + Publisher.sendMessage('Update slice viewer') | ||
254 | + | ||
255 | + if sys.platform == 'linux2': | ||
256 | + for i in self.pseudo_color_items: | ||
257 | + it = self.pseudo_color_items[i] | ||
258 | + if it.IsChecked(): | ||
259 | + it.Toggle() | ||
260 | + | ||
261 | + item.Toggle() | ||
262 | + self.HideClutDialog() | ||
263 | + self._gen_event = True | ||
264 | + | ||
265 | + elif(key in const.IMAGE_TILING.keys()): | ||
266 | + values = const.IMAGE_TILING[key] | ||
267 | + Publisher.sendMessage('Set slice viewer layout', values) | ||
268 | + Publisher.sendMessage('Update slice viewer') | ||
269 | + | ||
270 | + elif key in PROJECTIONS_ID: | ||
271 | + print 'Key', key | ||
272 | + pid = PROJECTIONS_ID[key] | ||
273 | + Publisher.sendMessage('Set projection type', pid) | ||
274 | + Publisher.sendMessage('Reload actual slice') | ||
275 | + | ||
276 | + elif key == _('Custom'): | ||
277 | + if self.cdialog is None: | ||
278 | + slc = sl.Slice() | ||
279 | + histogram = slc.histogram | ||
280 | + init = slc.matrix.min() | ||
281 | + end = slc.matrix.max() | ||
282 | + nodes = slc.nodes | ||
283 | + self.cdialog = ClutImagedataDialog(histogram, init, end, nodes) | ||
284 | + self.cdialog.Show() | ||
285 | + else: | ||
286 | + self.cdialog.Show(self._gen_event) | ||
287 | + | ||
288 | + if sys.platform == 'linux2': | ||
289 | + for i in self.pseudo_color_items: | ||
290 | + it = self.pseudo_color_items[i] | ||
291 | + if it.IsChecked(): | ||
292 | + it.Toggle() | ||
293 | + | ||
294 | + item.Toggle() | ||
295 | + item = self.ID_TO_TOOL_ITEM[evt.GetId()] | ||
296 | + item.Check(True) | ||
297 | + self._gen_event = False | ||
298 | + evt.Skip() | ||
290 | 299 | ||
291 | def HideClutDialog(self): | 300 | def HideClutDialog(self): |
292 | if self.cdialog: | 301 | if self.cdialog: |