Commit 4cb5f69202e96410d0bcc6ba437b1896d5e9ce06

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

Using bin structure as indicative of connectivity

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()
... ...