I have a selection mask on an image in cv2 and I want to expand the selection of pixels such that every pixel within a radius R of an already selected pixel can be added to the selection.
I would like for it to work identical to the expand function in Photoshop.
The only way I can imagine to do this is to look at each pixel in the image and if it is in the selection then change every pixel within radius R to be part of the selection.
The big problem with this is that it has runtime O(R^2 * # of pixels).
This is really slow, and I know there must be a better way because the Photoshop expand selection method works almost instantly even for large pictures.
So I would like a way to change my method in cv2 or in numpy to make it faster.
(maybe there’s a way to vectorize it, but I don’t know)
3
Answers
I figured out how to expand a selection the only problem that it can have some bugs at the edge of an image. It's actually quite simple, assuming you have a mask of boolean values. Except it doesn't actually matter too much it still works if the mask is of zeros representing non selected regions and positive numbers representing selected regions.
Here is a quick example that works quite well
This runs much faster, I also believe that it is O(R^2) which is quite fast. It also gives similar to results to the photoshop expand function for selections. I believe that the only difference is that my method selects pixels that fall within a circle of radius R, but Photoshop selects pixels within a hexagon of radius R, this is a slight difference that can be added to the if statement.
Trying the other solution it still felt very slow,
This seems to be much faster, with nearly identical results (8 seconds vs. 0.15 seconds, testing on colab w/ a radius of 30).
This is asking for morphology operations.
cv.dilate
is perfectly happy to enlarge a binary mask’s areas of positive values. Also, it’s fast.For different kernels/structuring elements, there is
getStructuringElement
. It can give you squares/rectangles, circles/ellipses, crosses, …Example input and dilated:
Read more: https://docs.opencv.org/4.x/d9/d61/tutorial_py_morphological_ops.html