Is there a way to perform a process similar to erosion in OpenCV that retains a given pixel if ANY of its neighbors are non-zero, instead of requiring all of its neighbors to be non-zero?
Here, by neighbors, I mean any pixel with abs(x1-x2)+abs(y1-y2)==1, but that is easy to control via the erosion kernel.
Of course, I can always use for loops and implement this behavior from scratch, but I prefer the speed that OpenCV can provide with its libraries.
Will it work to invert the image, perform an erosion, and then invert it back?
The other idea I had would be to convolve with a kernel with an empty center and then clip all values to the range 0 to 1. I would use scipy.ndimage.convolve for this.
I am working with a binary NumPy array with type np.float32 (i.e., values of 0.0 or 1.0) with shape (512,512).
One easy way to accomplish your goal would be to convolve with a square 3x3 kernel of ones. For each pixel, you now know how many foreground pixels there are in its neighborhood (including itself). Threshold this at 2 (
>= 2) to get all pixels where there are at least 2 foreground pixels in the neighborhood. Finally, the logical AND with the original image will give all foreground pixels that have at least one foreground neighbor.Here's an example:
The output is:
Of course some imaging libraries will have functions designed specifically for this purpose. I don't know if OpenCV or ndimage or scikit-image have such a function, I don't know these libraries well enough. But DIPlib does (disclosure: I'm an author):
The
img > 0part is to convert the floating-point array into a logical array, which DIPlib expects for binary images. This is about 5 times as fast as the other solution for a 512x512 image.