Commit 0d8808847e10d4128b91b388a0ec58fbe550218a

Authored by Thiago Franco de Moraes
1 parent 071dff96
Exists in floodfill

Added floodfill code to InVesalius

Showing 2 changed files with 194 additions and 0 deletions   Show diff stats
invesalius/data/floodfill.pyx 0 → 100644
... ... @@ -0,0 +1,183 @@
  1 +import numpy as np
  2 +cimport numpy as np
  3 +cimport cython
  4 +
  5 +from collections import deque
  6 +
  7 +from libc.math cimport floor, ceil
  8 +
  9 +DTYPE = np.uint8
  10 +ctypedef np.uint8_t DTYPE_t
  11 +
  12 +DTYPE16 = np.int16
  13 +ctypedef np.int16_t DTYPE16_t
  14 +
  15 +@cython.boundscheck(False) # turn of bounds-checking for entire function
  16 +def floodfill(np.ndarray[DTYPE_t, ndim=3] data, int i, int j, int k, int v, int fill, np.ndarray[DTYPE_t, ndim=3] out):
  17 +
  18 + cdef int to_return = 0
  19 + if out is None:
  20 + out = np.zeros_like(data)
  21 + to_return = 1
  22 +
  23 + cdef int x, y, z
  24 + cdef int w, h, d
  25 +
  26 + d = data.shape[0]
  27 + h = data.shape[1]
  28 + w = data.shape[2]
  29 +
  30 + stack = [(i, j, k), ]
  31 + out[k, j, i] = fill
  32 +
  33 + while stack:
  34 + x, y, z = stack.pop()
  35 +
  36 + if z + 1 < d and data[z + 1, y, x] == v and out[z + 1, y, x] != fill:
  37 + out[z + 1, y, x] = fill
  38 + stack.append((x, y, z + 1))
  39 +
  40 + if z - 1 >= 0 and data[z - 1, y, x] == v and out[z - 1, y, x] != fill:
  41 + out[z - 1, y, x] = fill
  42 + stack.append((x, y, z - 1))
  43 +
  44 + if y + 1 < h and data[z, y + 1, x] == v and out[z, y + 1, x] != fill:
  45 + out[z, y + 1, x] = fill
  46 + stack.append((x, y + 1, z))
  47 +
  48 + if y - 1 >= 0 and data[z, y - 1, x] == v and out[z, y - 1, x] != fill:
  49 + out[z, y - 1, x] = fill
  50 + stack.append((x, y - 1, z))
  51 +
  52 + if x + 1 < w and data[z, y, x + 1] == v and out[z, y, x + 1] != fill:
  53 + out[z, y, x + 1] = fill
  54 + stack.append((x + 1, y, z))
  55 +
  56 + if x - 1 >= 0 and data[z, y, x - 1] == v and out[z, y, x - 1] != fill:
  57 + out[z, y, x - 1] = fill
  58 + stack.append((x - 1, y, z))
  59 +
  60 + if to_return:
  61 + return out
  62 +
  63 +
  64 +@cython.boundscheck(False) # turn of bounds-checking for entire function
  65 +@cython.wraparound(False)
  66 +@cython.nonecheck(False)
  67 +def floodfill_threshold(np.ndarray[DTYPE16_t, ndim=3] data, int i, int j, int k, int t0, int t1, int fill, np.ndarray[DTYPE_t, ndim=3] out):
  68 +
  69 + cdef int to_return = 0
  70 + if out is None:
  71 + out = np.zeros_like(data)
  72 + to_return = 1
  73 +
  74 + cdef int x, y, z
  75 + cdef int w, h, d
  76 + cdef int xo, yo, zo
  77 +
  78 + d = data.shape[0]
  79 + h = data.shape[1]
  80 + w = data.shape[2]
  81 +
  82 + stack = deque()
  83 + if data[k, j, i] >= t0 and data[k, j, i] <= t1:
  84 + stack.append((i, j, k))
  85 + out[k, j, i] = fill
  86 +
  87 + while stack:
  88 + x, y, z = stack.pop()
  89 +
  90 + xo = x + 1
  91 + yo = y + 1
  92 + zo = z + 1
  93 +
  94 + 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:
  95 + out[zo + 1, yo, xo] = fill
  96 + stack.append((x, y, z + 1))
  97 +
  98 + 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:
  99 + out[zo - 1, yo, xo] = fill
  100 + stack.append((x, y, z - 1))
  101 +
  102 + 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:
  103 + out[zo, yo + 1, xo] = fill
  104 + stack.append((x, y + 1, z))
  105 +
  106 + 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:
  107 + out[zo, yo - 1, xo] = fill
  108 + stack.append((x, y - 1, z))
  109 +
  110 + 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:
  111 + out[zo, yo, xo + 1] = fill
  112 + stack.append((x + 1, y, z))
  113 +
  114 + 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:
  115 + out[zo, yo, xo - 1] = fill
  116 + stack.append((x - 1, y, z))
  117 +
  118 + if to_return:
  119 + return out
  120 +
  121 +
  122 +@cython.boundscheck(False) # turn of bounds-checking for entire function
  123 +@cython.wraparound(False)
  124 +@cython.nonecheck(False)
  125 +def floodfill_auto_threshold(np.ndarray[DTYPE16_t, ndim=3] data, int i, int j, int k, float p, int fill, np.ndarray[DTYPE_t, ndim=3] out):
  126 +
  127 + cdef int to_return = 0
  128 + if out is None:
  129 + out = np.zeros_like(data)
  130 + to_return = 1
  131 +
  132 + cdef int x, y, z
  133 + cdef int w, h, d
  134 + cdef int xo, yo, zo
  135 + cdef int t0, t1
  136 +
  137 + d = data.shape[0]
  138 + h = data.shape[1]
  139 + w = data.shape[2]
  140 +
  141 + stack = deque()
  142 + t0 = <int>floor(data[k, j, i] * (1 - p))
  143 + t1 = <int>floor(data[k, j, i] * (1 + p))
  144 + #if data[k, j, i] >= t0 and data[k, j, i] <= t1:
  145 + stack.append((i, j, k))
  146 + out[k, j, i] = fill
  147 +
  148 + while stack:
  149 + x, y, z = stack.pop()
  150 +
  151 + xo = x + 1
  152 + yo = y + 1
  153 + zo = z + 1
  154 +
  155 + t0 = <int>floor(data[z, y, x] * (1 - p))
  156 + t1 = <int>floor(data[z, y, x] * (1 + p))
  157 +
  158 + 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:
  159 + out[zo + 1, yo, xo] = fill
  160 + stack.append((x, y, z + 1))
  161 +
  162 + 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:
  163 + out[zo - 1, yo, xo] = fill
  164 + stack.append((x, y, z - 1))
  165 +
  166 + 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:
  167 + out[zo, yo + 1, xo] = fill
  168 + stack.append((x, y + 1, z))
  169 +
  170 + 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:
  171 + out[zo, yo - 1, xo] = fill
  172 + stack.append((x, y - 1, z))
  173 +
  174 + 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:
  175 + out[zo, yo, xo + 1] = fill
  176 + stack.append((x + 1, y, z))
  177 +
  178 + 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:
  179 + out[zo, yo, xo - 1] = fill
  180 + stack.append((x - 1, y, z))
  181 +
  182 + if to_return:
  183 + return out
... ...
setup.py 0 → 100644
... ... @@ -0,0 +1,11 @@
  1 +from distutils.core import setup
  2 +from distutils.extension import Extension
  3 +from Cython.Distutils import build_ext
  4 +
  5 +import numpy
  6 +
  7 +setup(
  8 + cmdclass = {'build_ext': build_ext},
  9 + ext_modules = [Extension("invesalius/data/floodfill", ["invesalius/data/floodfill.pyx"],
  10 + include_dirs = [numpy.get_include()])]
  11 +)
... ...