Commit 6d41707629230a8aef06bc33568a79da6e0f4ec5
1 parent
03ed982b
Exists in
fill_holes_auto
2d and 3d holes filling
Showing
4 changed files
with
94 additions
and
36 deletions
Show diff stats
invesalius/data/mask.py
| ... | ... | @@ -342,13 +342,34 @@ class Mask(): |
| 342 | 342 | def clear_history(self): |
| 343 | 343 | self.history.clear_history() |
| 344 | 344 | |
| 345 | - def fill_holes_auto(self, idx): | |
| 346 | - matrix = self.matrix[idx+1, 1:, 1:] | |
| 347 | - matrix = matrix.reshape(1, matrix.shape[0], matrix.shape[1]) | |
| 348 | - imask = (~(matrix > 127)) | |
| 349 | - labels, nlabels = ndimage.label(imask, output=np.uint16) | |
| 345 | + def fill_holes_auto(self, target, conn, orientation, index, size): | |
| 346 | + CON2D = {4: 1, 8: 2} | |
| 347 | + CON3D = {6: 1, 18: 2, 26: 3} | |
| 350 | 348 | |
| 351 | - floodfill.fill_holes_automatically(matrix, labels, nlabels, 100000) | |
| 349 | + if target == '3D': | |
| 350 | + matrix = self.matrix[1:, 1:, 1:] | |
| 351 | + bstruct = ndimage.generate_binary_structure(3, CON3D[conn]) | |
| 352 | + | |
| 353 | + imask = (~(matrix > 127)) | |
| 354 | + labels, nlabels = ndimage.label(imask, bstruct, output=np.uint16) | |
| 355 | + else: | |
| 356 | + bstruct = ndimage.generate_binary_structure(2, CON2D[conn]) | |
| 357 | + | |
| 358 | + if orientation == 'AXIAL': | |
| 359 | + matrix = self.matrix[index+1, 1:, 1:] | |
| 360 | + elif orientation == 'CORONAL': | |
| 361 | + matrix = self.matrix[1:, index+1, 1:] | |
| 362 | + elif orientation == 'SAGITAL': | |
| 363 | + matrix = self.matrix[1:, 1:, index+1] | |
| 364 | + | |
| 365 | + imask = (~(matrix > 127)) | |
| 366 | + labels, nlabels = ndimage.label(imask, bstruct, output=np.uint16) | |
| 367 | + | |
| 368 | + labels = labels.reshape(1, labels.shape[0], labels.shape[1]) | |
| 369 | + matrix = matrix.reshape(1, matrix.shape[0], matrix.shape[1]) | |
| 370 | + | |
| 371 | + | |
| 372 | + floodfill.fill_holes_automatically(matrix, labels, nlabels, size) | |
| 352 | 373 | |
| 353 | 374 | # for l in xrange(nlabels): |
| 354 | 375 | # trues = (labels == l) | ... | ... |
invesalius/data/slice_.py
| ... | ... | @@ -1486,8 +1486,19 @@ class Slice(object): |
| 1486 | 1486 | #iu.Export(imagedata, filename) |
| 1487 | 1487 | |
| 1488 | 1488 | def _fill_holes_auto(self, pubsub_evt): |
| 1489 | - self.do_threshold_to_all_slices() | |
| 1490 | - self.current_mask.fill_holes_auto(self.buffer_slices['AXIAL'].index) | |
| 1489 | + data = pubsub_evt.data | |
| 1490 | + target = data['target'] | |
| 1491 | + conn = data['conn'] | |
| 1492 | + orientation = data['orientation'] | |
| 1493 | + size = data['size'] | |
| 1494 | + | |
| 1495 | + if target == '2D': | |
| 1496 | + index = self.buffer_slices[orientation].index | |
| 1497 | + else: | |
| 1498 | + index = 0 | |
| 1499 | + self.do_threshold_to_all_slices() | |
| 1500 | + | |
| 1501 | + self.current_mask.fill_holes_auto(target, conn, orientation, index, size) | |
| 1491 | 1502 | |
| 1492 | 1503 | self.buffer_slices['AXIAL'].discard_mask() |
| 1493 | 1504 | self.buffer_slices['CORONAL'].discard_mask() | ... | ... |
invesalius/gui/dialogs.py
| ... | ... | @@ -1891,6 +1891,21 @@ class Panel2DConnectivity(wx.Panel): |
| 1891 | 1891 | sizer.Fit(self) |
| 1892 | 1892 | self.Layout() |
| 1893 | 1893 | |
| 1894 | + def GetConnSelected(self): | |
| 1895 | + if self.conect2D_4.GetValue(): | |
| 1896 | + return 4 | |
| 1897 | + else: | |
| 1898 | + return 8 | |
| 1899 | + | |
| 1900 | + def GetOrientation(self): | |
| 1901 | + dic_ori = { | |
| 1902 | + _(u"Axial"): 'AXIAL', | |
| 1903 | + _(u"Coronal"): 'CORONAL', | |
| 1904 | + _(u"Sagital"): 'SAGITAL' | |
| 1905 | + } | |
| 1906 | + | |
| 1907 | + return dic_ori[self.cmb_orientation.GetStringSelection()] | |
| 1908 | + | |
| 1894 | 1909 | |
| 1895 | 1910 | class Panel3DConnectivity(wx.Panel): |
| 1896 | 1911 | def __init__(self, parent, ID=-1, style=wx.TAB_TRAVERSAL|wx.NO_BORDER): |
| ... | ... | @@ -1915,6 +1930,14 @@ class Panel3DConnectivity(wx.Panel): |
| 1915 | 1930 | sizer.Fit(self) |
| 1916 | 1931 | self.Layout() |
| 1917 | 1932 | |
| 1933 | + def GetConnSelected(self): | |
| 1934 | + if self.conect3D_6.GetValue(): | |
| 1935 | + return 6 | |
| 1936 | + elif self.conect3D_18.GetValue(): | |
| 1937 | + return 18 | |
| 1938 | + else: | |
| 1939 | + return 26 | |
| 1940 | + | |
| 1918 | 1941 | |
| 1919 | 1942 | class PanelFFillThreshold(wx.Panel): |
| 1920 | 1943 | def __init__(self, parent, config, ID=-1, style=wx.TAB_TRAVERSAL|wx.NO_BORDER): |
| ... | ... | @@ -2484,7 +2507,7 @@ class CropOptionsDialog(wx.Dialog): |
| 2484 | 2507 | |
| 2485 | 2508 | |
| 2486 | 2509 | class FillHolesAutoDialog(wx.Dialog): |
| 2487 | - def __init__(self, title, config): | |
| 2510 | + def __init__(self, title): | |
| 2488 | 2511 | pre = wx.PreDialog() |
| 2489 | 2512 | pre.Create(wx.GetApp().GetTopWindow(), -1, title, style=wx.DEFAULT_DIALOG_STYLE|wx.FRAME_FLOAT_ON_PARENT) |
| 2490 | 2513 | self.PostCreate(pre) |
| ... | ... | @@ -2522,49 +2545,52 @@ class FillHolesAutoDialog(wx.Dialog): |
| 2522 | 2545 | sizer.AddSpacer(5) |
| 2523 | 2546 | sizer.Add(self.panel3dcon, flag=wx.LEFT|wx.RIGHT|wx.EXPAND, border=7) |
| 2524 | 2547 | sizer.AddSpacer(5) |
| 2525 | - sizer.Add(self.apply_btn, 0, flag=wx.ALIGN_RIGHT|wx.RIGHT, border=7) | |
| 2526 | - sizer.Add(self.close_btn, 0, flag=wx.ALIGN_RIGHT|wx.RIGHT, border=7) | |
| 2548 | + | |
| 2549 | + btn_sizer = wx.BoxSizer(wx.HORIZONTAL) | |
| 2550 | + btn_sizer.Add(self.apply_btn, 0, flag=wx.ALIGN_RIGHT, border=5) | |
| 2551 | + btn_sizer.Add(self.close_btn, 0, flag=wx.LEFT|wx.ALIGN_RIGHT, border=5) | |
| 2552 | + | |
| 2553 | + sizer.AddSizer(btn_sizer, 0, flag=wx.ALIGN_RIGHT|wx.LEFT|wx.RIGHT, border=5) | |
| 2554 | + | |
| 2527 | 2555 | sizer.AddSpacer(5) |
| 2528 | 2556 | |
| 2529 | 2557 | self.SetSizer(sizer) |
| 2530 | 2558 | sizer.Fit(self) |
| 2531 | 2559 | self.Layout() |
| 2532 | 2560 | |
| 2561 | + self.apply_btn.Bind(wx.EVT_BUTTON, self.OnApply) | |
| 2533 | 2562 | self.close_btn.Bind(wx.EVT_BUTTON, self.OnBtnClose) |
| 2534 | 2563 | self.Bind(wx.EVT_RADIOBUTTON, self.OnSetRadio) |
| 2535 | - self.Bind(wx.EVT_CLOSE, self.OnClose) | |
| 2564 | + | |
| 2565 | + def OnApply(self, evt): | |
| 2566 | + if self.panel_target.target_2d.GetValue(): | |
| 2567 | + target = "2D" | |
| 2568 | + conn = self.panel2dcon.GetConnSelected() | |
| 2569 | + orientation = self.panel2dcon.GetOrientation() | |
| 2570 | + else: | |
| 2571 | + target = "3D" | |
| 2572 | + conn = self.panel3dcon.GetConnSelected() | |
| 2573 | + orientation = '' | |
| 2574 | + | |
| 2575 | + data = { | |
| 2576 | + 'target': target, | |
| 2577 | + 'conn': conn, | |
| 2578 | + 'orientation': orientation, | |
| 2579 | + 'size': 1000, | |
| 2580 | + } | |
| 2581 | + | |
| 2582 | + Publisher.sendMessage("Fill holes automatically", data) | |
| 2583 | + | |
| 2536 | 2584 | |
| 2537 | 2585 | def OnBtnClose(self, evt): |
| 2538 | 2586 | self.Close() |
| 2587 | + self.Destroy() | |
| 2539 | 2588 | |
| 2540 | 2589 | def OnSetRadio(self, evt): |
| 2541 | 2590 | # Target |
| 2542 | 2591 | if self.panel_target.target_2d.GetValue(): |
| 2543 | - self.config.target = "2D" | |
| 2544 | 2592 | self.panel2dcon.Enable(1) |
| 2545 | 2593 | self.panel3dcon.Enable(0) |
| 2546 | 2594 | else: |
| 2547 | - self.config.target = "3D" | |
| 2548 | 2595 | self.panel3dcon.Enable(1) |
| 2549 | 2596 | self.panel2dcon.Enable(0) |
| 2550 | - | |
| 2551 | - # 2D | |
| 2552 | - if self.panel2dcon.conect2D_4.GetValue(): | |
| 2553 | - self.config.con_2d = 4 | |
| 2554 | - elif self.panel2dcon.conect2D_8.GetValue(): | |
| 2555 | - self.config.con_2d = 8 | |
| 2556 | - | |
| 2557 | - # 3D | |
| 2558 | - if self.panel3dcon.conect3D_6.GetValue(): | |
| 2559 | - self.config.con_3d = 6 | |
| 2560 | - elif self.panel3dcon.conect3D_18.GetValue(): | |
| 2561 | - self.config.con_3d = 18 | |
| 2562 | - elif self.panel3dcon.conect3D_26.GetValue(): | |
| 2563 | - self.config.con_3d = 26 | |
| 2564 | - | |
| 2565 | - def OnClose(self, evt): | |
| 2566 | - print "ONCLOSE" | |
| 2567 | - if self.config.dlg_visible: | |
| 2568 | - Publisher.sendMessage('Disable style', const.SLICE_STATE_MASK_FFILL) | |
| 2569 | - evt.Skip() | |
| 2570 | - self.Destroy() | ... | ... |
invesalius/gui/frame.py
| ... | ... | @@ -597,7 +597,7 @@ class Frame(wx.Frame): |
| 597 | 597 | |
| 598 | 598 | def OnFillHolesAutomatically(self): |
| 599 | 599 | # Publisher.sendMessage('Fill holes automatically') |
| 600 | - fdlg = dlg.FillHolesAutoDialog() | |
| 600 | + fdlg = dlg.FillHolesAutoDialog(_(u"Fill holes automatically")) | |
| 601 | 601 | fdlg.Show() |
| 602 | 602 | |
| 603 | 603 | def OnRemoveMaskParts(self): | ... | ... |