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 | 16 | # PARTICULAR. Consulte a Licenca Publica Geral GNU para obter mais |
17 | 17 | # detalhes. |
18 | 18 | #-------------------------------------------------------------------------- |
19 | +import heapq | |
19 | 20 | import os |
20 | 21 | import tempfile |
21 | 22 | |
22 | 23 | import numpy |
24 | +from scipy import ndimage | |
25 | +from scipy.ndimage.measurements import label | |
23 | 26 | import vtk |
24 | 27 | from wx.lib.pubsub import pub as Publisher |
25 | 28 | |
... | ... | @@ -162,6 +165,8 @@ class Slice(object): |
162 | 165 | |
163 | 166 | Publisher.subscribe(self._do_boolean_op, 'Do boolean operation') |
164 | 167 | |
168 | + Publisher.subscribe(self._keep_greatest_region, 'Keep greatest component') | |
169 | + | |
165 | 170 | Publisher.subscribe(self.OnExportMask,'Export mask to file') |
166 | 171 | |
167 | 172 | Publisher.subscribe(self.OnCloseProject, 'Close project data') |
... | ... | @@ -1114,6 +1119,7 @@ class Slice(object): |
1114 | 1119 | if mask.matrix[n, 0, 0] == 0: |
1115 | 1120 | m = mask.matrix[n, 1:, 1:] |
1116 | 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 | 1124 | mask.matrix.flush() |
1119 | 1125 | |
... | ... | @@ -1261,6 +1267,28 @@ class Slice(object): |
1261 | 1267 | future_mask.was_edited = True |
1262 | 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 | 1292 | def apply_slice_buffer_to_mask(self, orientation): |
1265 | 1293 | """ |
1266 | 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 | 164 | self.AppendMenu(-1, _("Projection type"), submenu_projection) |
165 | 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 | 172 | # It doesn't work in Linux |
168 | 173 | self.Bind(wx.EVT_MENU, self.OnPopup) |
169 | 174 | # In Linux the bind must be putted in the submenu |
... | ... | @@ -207,86 +212,90 @@ class SliceMenu(wx.Menu): |
207 | 212 | |
208 | 213 | def OnPopup(self, evt): |
209 | 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 | 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 | 300 | def HideClutDialog(self): |
292 | 301 | if self.cdialog: | ... | ... |