Commit 516b0f05ceca0b92fd94ea19091e5fc719d753ff

Authored by Thiago Franco de Moraes
1 parent f17e9109

Tool to keep the greatest component from the mask

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: