Commit 3e8484532f5a3e62106871eb97be11e6d970950e

Authored by Thiago Franco de Moraes
1 parent ba729de6
Exists in ff_mask

Using an iter to traverse the voxel neighbourhood

invesalius/data/floodfill.pyx
... ... @@ -81,7 +81,7 @@ def floodfill(np.ndarray[image_t, ndim=3] data, int i, int j, int k, int v, int
81 81 @cython.boundscheck(False) # turn of bounds-checking for entire function
82 82 @cython.wraparound(False)
83 83 @cython.nonecheck(False)
84   -def floodfill_threshold(np.ndarray[image_t, ndim=3] data, list seeds, int t0, int t1, int fill, np.ndarray[mask_t, ndim=3] out):
  84 +def floodfill_threshold(np.ndarray[image_t, ndim=3] data, list seeds, int t0, int t1, int fill, tuple neighbor_iter, np.ndarray[mask_t, ndim=3] out):
85 85  
86 86 cdef int to_return = 0
87 87 if out is None:
... ... @@ -89,6 +89,7 @@ def floodfill_threshold(np.ndarray[image_t, ndim=3] data, list seeds, int t0, in
89 89 to_return = 1
90 90  
91 91 cdef int x, y, z
  92 + cdef int xd, yd, zd
92 93 cdef int w, h, d
93 94 cdef int xo, yo, zo
94 95  
... ... @@ -106,33 +107,38 @@ def floodfill_threshold(np.ndarray[image_t, ndim=3] data, list seeds, int t0, in
106 107 while stack:
107 108 x, y, z = stack.pop()
108 109  
109   - xo = x
110   - yo = y
111   - zo = z
112 110  
113   - if z + 1 < d and data[z + 1, y, x] >= t0 and data[z + 1, y, x] <= t1 and out[zo + 1, yo, xo] != fill:
114   - out[zo + 1, yo, xo] = fill
115   - stack.append((x, y, z + 1))
  111 + for xd, yd, zd in neighbor_iter:
  112 + xo = x + xd
  113 + yo = y + yd
  114 + zo = z + zd
  115 + if 0 <= (x + xd) < w and 0 <= (y + yd) < h and 0 <= (z + zd) < d and out[zo, yo, xo] != fill and t0 <= data[zo, yo, xo] <= t1:
  116 + out[zo, yo, xo] = fill
  117 + stack.append((xo, yo, zo))
116 118  
117   - if z - 1 >= 0 and data[z - 1, y, x] >= t0 and data[z - 1, y, x] <= t1 and out[zo - 1, yo, xo] != fill:
118   - out[zo - 1, yo, xo] = fill
119   - stack.append((x, y, z - 1))
  119 + # if z + 1 < d and data[z + 1, y, x] >= t0 and data[z + 1, y, x] <= t1 and out[zo + 1, yo, xo] != fill:
  120 + # out[zo + 1, yo, xo] = fill
  121 + # stack.append((x, y, z + 1))
120 122  
121   - if y + 1 < h and data[z, y + 1, x] >= t0 and data[z, y + 1, x] <= t1 and out[zo, yo + 1, xo] != fill:
122   - out[zo, yo + 1, xo] = fill
123   - stack.append((x, y + 1, z))
  123 + # if z - 1 >= 0 and data[z - 1, y, x] >= t0 and data[z - 1, y, x] <= t1 and out[zo - 1, yo, xo] != fill:
  124 + # out[zo - 1, yo, xo] = fill
  125 + # stack.append((x, y, z - 1))
124 126  
125   - if y - 1 >= 0 and data[z, y - 1, x] >= t0 and data[z, y - 1, x] <= t1 and out[zo, yo - 1, xo] != fill:
126   - out[zo, yo - 1, xo] = fill
127   - stack.append((x, y - 1, z))
  127 + # if y + 1 < h and data[z, y + 1, x] >= t0 and data[z, y + 1, x] <= t1 and out[zo, yo + 1, xo] != fill:
  128 + # out[zo, yo + 1, xo] = fill
  129 + # stack.append((x, y + 1, z))
128 130  
129   - if x + 1 < w and data[z, y, x + 1] >= t0 and data[z, y, x + 1] <= t1 and out[zo, yo, xo + 1] != fill:
130   - out[zo, yo, xo + 1] = fill
131   - stack.append((x + 1, y, z))
  131 + # if y - 1 >= 0 and data[z, y - 1, x] >= t0 and data[z, y - 1, x] <= t1 and out[zo, yo - 1, xo] != fill:
  132 + # out[zo, yo - 1, xo] = fill
  133 + # stack.append((x, y - 1, z))
132 134  
133   - if x - 1 >= 0 and data[z, y, x - 1] >= t0 and data[z, y, x - 1] <= t1 and out[zo, yo, xo - 1] != fill:
134   - out[zo, yo, xo - 1] = fill
135   - stack.append((x - 1, y, z))
  135 + # if x + 1 < w and data[z, y, x + 1] >= t0 and data[z, y, x + 1] <= t1 and out[zo, yo, xo + 1] != fill:
  136 + # out[zo, yo, xo + 1] = fill
  137 + # stack.append((x + 1, y, z))
  138 +
  139 + # if x - 1 >= 0 and data[z, y, x - 1] >= t0 and data[z, y, x - 1] <= t1 and out[zo, yo, xo - 1] != fill:
  140 + # out[zo, yo, xo - 1] = fill
  141 + # stack.append((x - 1, y, z))
136 142  
137 143 if to_return:
138 144 return out
... ...
invesalius/data/styles.py
... ... @@ -1769,7 +1769,6 @@ class FlooFillMaskInteractorStyle(DefaultInteractorStyle):
1769 1769 if (self.viewer.slice_.buffer_slices[self.orientation].mask is None):
1770 1770 return
1771 1771  
1772   -
1773 1772 viewer = self.viewer
1774 1773 iren = viewer.interactor
1775 1774  
... ... @@ -1793,9 +1792,35 @@ class FlooFillMaskInteractorStyle(DefaultInteractorStyle):
1793 1792  
1794 1793 cp_mask = mask.copy()
1795 1794  
1796   - floodfill.floodfill_threshold(cp_mask, [[x, y, z]], 0, 1, 254, mask)
  1795 + from_3d = True
  1796 + if from_3d:
  1797 + neighbor_iter = ((-1, 0, 0),
  1798 + (1, 0, 0),
  1799 + (0, -1, 0),
  1800 + (0, 1, 0),
  1801 + (0, 0, -1),
  1802 + (0, 0, 1))
  1803 + else:
  1804 + neighbor_iter = ((-1, 0, 0),
  1805 + (1, 0, 0),
  1806 + (0, -1, 0),
  1807 + (0, 1, 0))
1797 1808  
1798   - viewer.OnScrollBar()
  1809 + if iren.GetControlKey():
  1810 + floodfill.floodfill_threshold(cp_mask, [[x, y, z]], 254, 255, 1, neighbor_iter, mask)
  1811 + else:
  1812 + floodfill.floodfill_threshold(cp_mask, [[x, y, z]], 0, 1, 254, neighbor_iter, mask)
  1813 +
  1814 + self.viewer.slice_.buffer_slices['AXIAL'].discard_mask()
  1815 + self.viewer.slice_.buffer_slices['CORONAL'].discard_mask()
  1816 + self.viewer.slice_.buffer_slices['SAGITAL'].discard_mask()
  1817 +
  1818 + self.viewer.slice_.buffer_slices['AXIAL'].discard_vtk_mask()
  1819 + self.viewer.slice_.buffer_slices['CORONAL'].discard_vtk_mask()
  1820 + self.viewer.slice_.buffer_slices['SAGITAL'].discard_vtk_mask()
  1821 +
  1822 + self.viewer.slice_.current_mask.was_edited = True
  1823 + Publisher.sendMessage('Reload actual slice')
1799 1824  
1800 1825 def get_coordinate_cursor(self):
1801 1826 # Find position
... ...