Another, similar post called Flood Fill in Python is a very general question on flood fill and the answer only contains a broad pseudo code example. I'm look for an explicit solution with numpy
or scipy
.
Let's take this array for example:
a = np.array([
[0, 1, 1, 1, 1, 0],
[0, 0, 1, 2, 1, 1],
[0, 1, 1, 1, 1, 0]
])
For selecting element 0, 0
and flood fill with value 3
, I'd expect:
[
[3, 1, 1, 1, 1, 0],
[3, 3, 1, 2, 1, 1],
[3, 1, 1, 1, 1, 0]
]
For selecting element 0, 1
and flood fill with value 3
, I'd expect:
[
[0, 3, 3, 3, 3, 0],
[0, 0, 3, 2, 3, 3],
[0, 3, 3, 3, 3, 0]
]
For selecting element 0, 5
and flood fill with value 3
, I'd expect:
[
[0, 1, 1, 1, 1, 3],
[0, 0, 1, 2, 1, 1],
[0, 1, 1, 1, 1, 0]
]
This should be a fairly basic operation, no? Which numpy
or scipy
method am I overlooking?
Approach #1
Module scikit-image
offers the built-in to do the same with skimage.segmentation.flood_fill
-
from skimage.morphology import flood_fill
flood_fill(image, (y, x), newval)
Sample runs -
In [17]: a
Out[17]:
array([[0, 1, 1, 1, 1, 0],
[0, 0, 1, 2, 1, 1],
[0, 1, 1, 1, 1, 0]])
In [18]: flood_fill(a, (0, 0), 3)
Out[18]:
array([[3, 1, 1, 1, 1, 0],
[3, 3, 1, 2, 1, 1],
[3, 1, 1, 1, 1, 0]])
In [19]: flood_fill(a, (0, 1), 3)
Out[19]:
array([[0, 3, 3, 3, 3, 0],
[0, 0, 3, 2, 3, 3],
[0, 3, 3, 3, 3, 0]])
In [20]: flood_fill(a, (0, 5), 3)
Out[20]:
array([[0, 1, 1, 1, 1, 3],
[0, 0, 1, 2, 1, 1],
[0, 1, 1, 1, 1, 0]])
Approach #2
We can use skimage.measure.label
with some array-masking
-
from skimage.measure import label
def floodfill_by_xy(a, pos, newval):
x,y = pos
l = label(a==a[y,x])
a[l==l[y,x]] = newval
return a
To make use of SciPy based label
function - scipy.ndimage.measurements.label
, it would mostly be the same -
from scipy.ndimage.measurements import label
def floodfill_by_xy_scipy(a, pos, newval):
x,y = pos
l = label(a==a[y, x])[0]
a[l==l[y, x]] = newval
return a
Note : These would work as in-situ edits.