Commit 3e8484532f5a3e62106871eb97be11e6d970950e
1 parent
ba729de6
Exists in
ff_mask
Using an iter to traverse the voxel neighbourhood
Showing
2 changed files
with
56 additions
and
25 deletions
Show diff stats
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,7 +81,7 @@ def floodfill(np.ndarray[image_t, ndim=3] data, int i, int j, int k, int v, int | ||
81 | @cython.boundscheck(False) # turn of bounds-checking for entire function | 81 | @cython.boundscheck(False) # turn of bounds-checking for entire function |
82 | @cython.wraparound(False) | 82 | @cython.wraparound(False) |
83 | @cython.nonecheck(False) | 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 | cdef int to_return = 0 | 86 | cdef int to_return = 0 |
87 | if out is None: | 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,6 +89,7 @@ def floodfill_threshold(np.ndarray[image_t, ndim=3] data, list seeds, int t0, in | ||
89 | to_return = 1 | 89 | to_return = 1 |
90 | 90 | ||
91 | cdef int x, y, z | 91 | cdef int x, y, z |
92 | + cdef int xd, yd, zd | ||
92 | cdef int w, h, d | 93 | cdef int w, h, d |
93 | cdef int xo, yo, zo | 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,33 +107,38 @@ def floodfill_threshold(np.ndarray[image_t, ndim=3] data, list seeds, int t0, in | ||
106 | while stack: | 107 | while stack: |
107 | x, y, z = stack.pop() | 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 | if to_return: | 143 | if to_return: |
138 | return out | 144 | return out |
invesalius/data/styles.py
@@ -1769,7 +1769,6 @@ class FlooFillMaskInteractorStyle(DefaultInteractorStyle): | @@ -1769,7 +1769,6 @@ class FlooFillMaskInteractorStyle(DefaultInteractorStyle): | ||
1769 | if (self.viewer.slice_.buffer_slices[self.orientation].mask is None): | 1769 | if (self.viewer.slice_.buffer_slices[self.orientation].mask is None): |
1770 | return | 1770 | return |
1771 | 1771 | ||
1772 | - | ||
1773 | viewer = self.viewer | 1772 | viewer = self.viewer |
1774 | iren = viewer.interactor | 1773 | iren = viewer.interactor |
1775 | 1774 | ||
@@ -1793,9 +1792,35 @@ class FlooFillMaskInteractorStyle(DefaultInteractorStyle): | @@ -1793,9 +1792,35 @@ class FlooFillMaskInteractorStyle(DefaultInteractorStyle): | ||
1793 | 1792 | ||
1794 | cp_mask = mask.copy() | 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 | def get_coordinate_cursor(self): | 1825 | def get_coordinate_cursor(self): |
1801 | # Find position | 1826 | # Find position |