From 3e8484532f5a3e62106871eb97be11e6d970950e Mon Sep 17 00:00:00 2001 From: Thiago Franco de Moraes Date: Mon, 15 Aug 2016 16:27:48 -0300 Subject: [PATCH] Using an iter to traverse the voxel neighbourhood --- invesalius/data/floodfill.pyx | 50 ++++++++++++++++++++++++++++---------------------- invesalius/data/styles.py | 31 ++++++++++++++++++++++++++++--- 2 files changed, 56 insertions(+), 25 deletions(-) diff --git a/invesalius/data/floodfill.pyx b/invesalius/data/floodfill.pyx index 4892326..1447456 100644 --- a/invesalius/data/floodfill.pyx +++ b/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 @cython.boundscheck(False) # turn of bounds-checking for entire function @cython.wraparound(False) @cython.nonecheck(False) -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): +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): cdef int to_return = 0 if out is None: @@ -89,6 +89,7 @@ def floodfill_threshold(np.ndarray[image_t, ndim=3] data, list seeds, int t0, in to_return = 1 cdef int x, y, z + cdef int xd, yd, zd cdef int w, h, d cdef int xo, yo, zo @@ -106,33 +107,38 @@ def floodfill_threshold(np.ndarray[image_t, ndim=3] data, list seeds, int t0, in while stack: x, y, z = stack.pop() - xo = x - yo = y - zo = z - 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: - out[zo + 1, yo, xo] = fill - stack.append((x, y, z + 1)) + for xd, yd, zd in neighbor_iter: + xo = x + xd + yo = y + yd + zo = z + zd + 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: + out[zo, yo, xo] = fill + stack.append((xo, yo, zo)) - 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: - out[zo - 1, yo, xo] = fill - stack.append((x, y, z - 1)) + # 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: + # out[zo + 1, yo, xo] = fill + # stack.append((x, y, z + 1)) - 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: - out[zo, yo + 1, xo] = fill - stack.append((x, y + 1, z)) + # 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: + # out[zo - 1, yo, xo] = fill + # stack.append((x, y, z - 1)) - 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: - out[zo, yo - 1, xo] = fill - stack.append((x, y - 1, z)) + # 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: + # out[zo, yo + 1, xo] = fill + # stack.append((x, y + 1, z)) - 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: - out[zo, yo, xo + 1] = fill - stack.append((x + 1, y, z)) + # 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: + # out[zo, yo - 1, xo] = fill + # stack.append((x, y - 1, z)) - 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: - out[zo, yo, xo - 1] = fill - stack.append((x - 1, y, z)) + # 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: + # out[zo, yo, xo + 1] = fill + # stack.append((x + 1, y, z)) + + # 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: + # out[zo, yo, xo - 1] = fill + # stack.append((x - 1, y, z)) if to_return: return out diff --git a/invesalius/data/styles.py b/invesalius/data/styles.py index 70e9b47..5a4d3eb 100644 --- a/invesalius/data/styles.py +++ b/invesalius/data/styles.py @@ -1769,7 +1769,6 @@ class FlooFillMaskInteractorStyle(DefaultInteractorStyle): if (self.viewer.slice_.buffer_slices[self.orientation].mask is None): return - viewer = self.viewer iren = viewer.interactor @@ -1793,9 +1792,35 @@ class FlooFillMaskInteractorStyle(DefaultInteractorStyle): cp_mask = mask.copy() - floodfill.floodfill_threshold(cp_mask, [[x, y, z]], 0, 1, 254, mask) + from_3d = True + if from_3d: + neighbor_iter = ((-1, 0, 0), + (1, 0, 0), + (0, -1, 0), + (0, 1, 0), + (0, 0, -1), + (0, 0, 1)) + else: + neighbor_iter = ((-1, 0, 0), + (1, 0, 0), + (0, -1, 0), + (0, 1, 0)) - viewer.OnScrollBar() + if iren.GetControlKey(): + floodfill.floodfill_threshold(cp_mask, [[x, y, z]], 254, 255, 1, neighbor_iter, mask) + else: + floodfill.floodfill_threshold(cp_mask, [[x, y, z]], 0, 1, 254, neighbor_iter, mask) + + self.viewer.slice_.buffer_slices['AXIAL'].discard_mask() + self.viewer.slice_.buffer_slices['CORONAL'].discard_mask() + self.viewer.slice_.buffer_slices['SAGITAL'].discard_mask() + + self.viewer.slice_.buffer_slices['AXIAL'].discard_vtk_mask() + self.viewer.slice_.buffer_slices['CORONAL'].discard_vtk_mask() + self.viewer.slice_.buffer_slices['SAGITAL'].discard_vtk_mask() + + self.viewer.slice_.current_mask.was_edited = True + Publisher.sendMessage('Reload actual slice') def get_coordinate_cursor(self): # Find position -- libgit2 0.21.2