Commit 4cb5f69202e96410d0bcc6ba437b1896d5e9ce06
1 parent
1cc92f96
Exists in
ff_mask
Using bin structure as indicative of connectivity
Showing
2 changed files
with
43 additions
and
32 deletions
Show diff stats
invesalius/data/floodfill.pyx
... | ... | @@ -90,7 +90,7 @@ def floodfill(np.ndarray[image_t, ndim=3] data, int i, int j, int k, int v, int |
90 | 90 | @cython.boundscheck(False) # turn of bounds-checking for entire function |
91 | 91 | @cython.wraparound(False) |
92 | 92 | @cython.nonecheck(False) |
93 | -def floodfill_threshold(np.ndarray[image_t, ndim=3] data, list seeds, int t0, int t1, int fill, vector[vector[int]] neighbor_iter, np.ndarray[mask_t, ndim=3] out): | |
93 | +def floodfill_threshold(np.ndarray[image_t, ndim=3] data, list seeds, int t0, int t1, int fill, np.ndarray[mask_t, ndim=3] strct, np.ndarray[mask_t, ndim=3] out): | |
94 | 94 | |
95 | 95 | cdef int to_return = 0 |
96 | 96 | if out is None: |
... | ... | @@ -98,18 +98,27 @@ def floodfill_threshold(np.ndarray[image_t, ndim=3] data, list seeds, int t0, in |
98 | 98 | to_return = 1 |
99 | 99 | |
100 | 100 | cdef int x, y, z |
101 | - cdef int xd, yd, zd | |
102 | - cdef int w, h, d | |
101 | + cdef int dx, dy, dz | |
102 | + cdef int odx, ody, odz | |
103 | 103 | cdef int xo, yo, zo |
104 | - cdef int i | |
104 | + cdef int i, j, k | |
105 | + cdef int offset_x, offset_y, offset_z | |
105 | 106 | |
106 | - d = data.shape[0] | |
107 | - h = data.shape[1] | |
108 | - w = data.shape[2] | |
107 | + dz = data.shape[0] | |
108 | + dy = data.shape[1] | |
109 | + dx = data.shape[2] | |
110 | + | |
111 | + odz = strct.shape[0] | |
112 | + ody = strct.shape[1] | |
113 | + odx = strct.shape[2] | |
109 | 114 | |
110 | 115 | cdef cdeque[coord] stack |
111 | 116 | cdef coord c |
112 | 117 | |
118 | + offset_z = odz / 2 | |
119 | + offset_y = ody / 2 | |
120 | + offset_x = odx / 2 | |
121 | + | |
113 | 122 | for i, j, k in seeds: |
114 | 123 | if data[k, j, i] >= t0 and data[k, j, i] <= t1: |
115 | 124 | c.x = i |
... | ... | @@ -129,17 +138,20 @@ def floodfill_threshold(np.ndarray[image_t, ndim=3] data, list seeds, int t0, in |
129 | 138 | |
130 | 139 | out[z, y, x] = fill |
131 | 140 | |
132 | - for i in xrange(neighbor_iter.size()): | |
133 | - xo = x + neighbor_iter[i][0] | |
134 | - yo = y + neighbor_iter[i][1] | |
135 | - zo = z + neighbor_iter[i][2] | |
136 | - | |
137 | - if 0 <= xo < w and 0 <= yo < h and 0 <= zo < d and out[zo, yo, xo] != fill and t0 <= data[zo, yo, xo] <= t1: | |
138 | - out[zo, yo, xo] = fill | |
139 | - c.x = xo | |
140 | - c.y = yo | |
141 | - c.z = zo | |
142 | - stack.push_back(c) | |
141 | + for k in xrange(odz): | |
142 | + for j in xrange(ody): | |
143 | + for i in xrange(odx): | |
144 | + if strct[k, j, i]: | |
145 | + xo = x + i - offset_x | |
146 | + yo = y + j - offset_y | |
147 | + zo = z + k - offset_z | |
148 | + | |
149 | + if 0 <= xo < dx and 0 <= yo < dy and 0 <= zo < dz and out[zo, yo, xo] != fill and t0 <= data[zo, yo, xo] <= t1: | |
150 | + out[zo, yo, xo] = fill | |
151 | + c.x = xo | |
152 | + c.y = yo | |
153 | + c.z = zo | |
154 | + stack.push_back(c) | |
143 | 155 | |
144 | 156 | if to_return: |
145 | 157 | return out | ... | ... |
invesalius/data/styles.py
... | ... | @@ -1803,24 +1803,23 @@ class FloodFillMaskInteractorStyle(DefaultInteractorStyle): |
1803 | 1803 | |
1804 | 1804 | x, y, z = self.calcultate_scroll_position(position) |
1805 | 1805 | |
1806 | - from_3d = True | |
1807 | 1806 | if self.config.target == "3D": |
1808 | - print "DOING 3D, manolo!" | |
1809 | - neighbor_iter = ((-1, 0, 0), | |
1810 | - (1, 0, 0), | |
1811 | - (0, -1, 0), | |
1812 | - (0, 1, 0), | |
1813 | - (0, 0, -1), | |
1814 | - (0, 0, 1)) | |
1807 | + bstruct = generate_binary_structure(3, 1) | |
1815 | 1808 | self.viewer.slice_.do_threshold_to_all_slices() |
1816 | 1809 | else: |
1817 | - neighbor_iter = ((-1, 0, 0), | |
1818 | - (1, 0, 0), | |
1819 | - (0, -1, 0), | |
1820 | - (0, 1, 0)) | |
1810 | + _bstruct = generate_binary_structure(2, 1) | |
1811 | + if self.orientation == 'AXIAL': | |
1812 | + bstruct = np.zeros((1, 3, 3), dtype='uint8') | |
1813 | + bstruct[0] = _bstruct | |
1814 | + elif self.orientation == 'CORONAL': | |
1815 | + bstruct = np.zeros((3, 1, 3), dtype='uint8') | |
1816 | + bstruct[:, 0, :] = _bstruct | |
1817 | + elif self.orientation == 'SAGITAL': | |
1818 | + bstruct = np.zeros((3, 3, 1), dtype='uint8') | |
1819 | + bstruct[:, :, 0] = _bstruct | |
1821 | 1820 | |
1822 | 1821 | mask = self.viewer.slice_.current_mask.matrix[1:, 1:, 1:] |
1823 | - cp_mask = mask.copy() | |
1822 | + cp_mask = mask | |
1824 | 1823 | |
1825 | 1824 | # neighbor_iter = [] |
1826 | 1825 | # for i in xrange(-1, 2): |
... | ... | @@ -1837,7 +1836,7 @@ class FloodFillMaskInteractorStyle(DefaultInteractorStyle): |
1837 | 1836 | t1 = 1 |
1838 | 1837 | fill = 254 |
1839 | 1838 | |
1840 | - floodfill.floodfill_threshold(cp_mask, [[x, y, z]], t0, t1, fill, neighbor_iter, mask) | |
1839 | + floodfill.floodfill_threshold(cp_mask, [[x, y, z]], t0, t1, fill, bstruct, mask) | |
1841 | 1840 | |
1842 | 1841 | self.viewer.slice_.buffer_slices['AXIAL'].discard_mask() |
1843 | 1842 | self.viewer.slice_.buffer_slices['CORONAL'].discard_mask() | ... | ... |