Generally speaking, you're looking for an edge detection filter.
There's more than one way to handle this, but the basic idea is that you convolve a simple filter such as [-1, 1]
or [-1, 0, 1]
with your data. scipy.ndimage
and scikit-image are good places to start for this. Keep in mind that there's more than one way to handle the general case.
However, if you're wanting the simplest possible case, you can use basic numpy operations:
import numpy as np
x = np.array([[1,1,1,2,2],
[1,1,1,2,2],
[1,2,2,2,2]])
edges = np.abs(np.diff(x, axis=1)) > 0
This yields:
array([[False, False, True, False],
[False, False, True, False],
[ True, False, False, False]], dtype=bool)
If you'd like the output to have the same shape as the input, you have a few different options. You could pad the input array by the left or right hand edge values:
# Pad the right-hand side with the edge values
# Use [(0, 0), (1, 0)] to pad the left instead.
xpad = np.pad(x, [(0, 0), (0, 1)], mode='edge')
edges = np.abs(np.diff(xpad, axis=1)) > 0
Which would yield:
array([[False, False, True, False, False],
[False, False, True, False, False],
[ True, False, False, False, False]], dtype=bool)
In this specific case, you could use np.gradient
instead of padding the array. gradient
will use a different algorithm at the edges to ensure that the array size is maintained:
dy, dx = np.gradient(x)
edges = np.abs(dx) > 0
Which yields a slightly thicker border, as it uses a slightly different algorithm than simply subtracting adjacent elements:
array([[False, False, True, True, False],
[False, False, True, True, False],
[ True, True, False, False, False]], dtype=bool)
Finally, depending on what you meant by "double border", you might try a more complex edge filter than a simple one-sided difference. For example:
In [4]: import scipy.ndimage
In [5]: abs(scipy.ndimage.laplace(x)) > 0
Out[5]:
array([[False, False, True, True, False],
[False, True, True, True, False],
[ True, True, True, False, False]], dtype=bool)