I've got a binary image where I need to select the nearest white pixel to a given set of pixel coordinates.
For example, if I click on a pixel I need to have Python search for the nearest pixel with a value greater than 0 then return that pixel's coordinates.
Any thoughts?
I figured I should add what I've done so far.
import cv2
import numpy as np
img = cv.imread('depth.png', 0) # reads image as grayscale
edges = cv2.Canny(img, 10, 50)
white_coords = np.argwhere(edges == 255) # finds all of the white pixel coordinates in the image and places them in a list.
# this is where I'm stuck
First use cv2.findNonZero
to get a numpy array of coordinates of all the white pixels.
Next, calculate distance from the clicked target point (Pythagoras theorem)
Use numpy.argmin
to find the position of the lowest distance.
Return the coordinates of the corresponding nonzero pixel.
Example script:
import cv2
import numpy as np
# Create a test image
img = np.zeros((1024,1024), np.uint8)
# Fill it with some white pixels
img[10,10] = 255
img[20,1000] = 255
img[:,800:] = 255
TARGET = (255,255)
def find_nearest_white(img, target):
nonzero = cv2.findNonZero(img)
distances = np.sqrt((nonzero[:,:,0] - target[0]) ** 2 + (nonzero[:,:,1] - target[1]) ** 2)
nearest_index = np.argmin(distances)
return nonzero[nearest_index]
print find_nearest_white(img, TARGET)
Which prints:
[[10 10]]
and takes around 4ms to complete, since it takes advantage of optimized cv2
and numpy
functions.
Alternatively, you could go for a pure numpy
solution, and as you have already attempted, use numpy.argwhere
instead of cv2.findNonZero
:
def find_nearest_white(img, target):
nonzero = np.argwhere(img == 255)
distances = np.sqrt((nonzero[:,0] - TARGET[0]) ** 2 + (nonzero[:,1] - TARGET[1]) ** 2)
nearest_index = np.argmin(distances)
return nonzero[nearest_index]
Which prints:
[10 10]
However, for me this is slightly slower, at around 9 ms per run.
Thoughts, yes! Start looping from the given pixel, in first iteration check for all the pixels surrounding the given pixel, if a white pixel is not found, increment the distance by 1 and check if any pixel in the circumscribing perimeter of the given pixel is white, continue looping until you find a white pixel or go out of bounds.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With