Reputation: 1221
I want to find all pixels in an image that are grey and that are left of a black pixel.
to find all pixels that have the shades of grey that I'm looking for, I can do:
np.where(np.all(np.abs(img - (80, 71, 71)) < 10, axis=-1))
Is there a way of combining this statement with the condition that the pixel next to the grey pixel must be black? I.e. only return grey pixels that are immediate to the left of a black pixel?
I could do a for loop, loop over all the grey pixels I found in the first step and then check if the pixel next to them is black, but this seems quite inefficient. Is there a more efficient way of doing this in numpy?
Upvotes: 0
Views: 362
Reputation: 32084
For finding gray pixels that are immediate to the left of a black pixel, we may apply the following stages:
True
where pixel is gray and False
otherwise.np.where
: gray_mask = np.all(np.abs(img - (80, 71, 71)) < 10, axis=-1)
True
where pixel is black and False
otherwise. black_mask = np.all(img == 0, axis=-1)
False
values at the right hand size of the mask (for "correcting" the mask size, after cropping). shifted_black_mask = np.pad(black_mask[:, 1:], ((0, 0), (0, 1)), 'constant')
gray_next_to_black = gray_mask & shifted_black_mask
# gray_next_to_black_idx = np.where(gray_next_to_black) # Get the indices if required
Code sample:
import cv2
import numpy as np
# Sample image for testing:
img = np.array([[[0, 100, 0], [0, 100, 0], [0, 100, 0], [0, 0, 0]],
[[0, 100, 0], [80, 80, 80], [80, 80, 80], [0, 0, 0]],
[[0, 100, 0], [80, 80, 80], [80, 80, 80], [0, 100, 0]],
[[0, 100, 0], [80, 80, 80], [0, 0, 0], [0, 100, 0]]], np.uint8)
gray_mask = np.all(np.abs(img - (80, 71, 71)) < 10, axis=-1) # Create a mask with True where pixel is gray and False otherwise.
black_mask = np.all(img == 0, axis=-1) # Create a mask with True where pixel is black and False otherwise.
# Shift the black mask one column to the left
shifted_black_mask = np.pad(black_mask[:, 1:], ((0, 0), (0, 1)), 'constant') # Crop from the second column to the end, and add column of zeros at the right hand side.
# Apply and operation between the gray mask and the shifted black mask
# The result is True where gray pixel has a black pixel from it's right
gray_next_to_black = gray_mask & shifted_black_mask
# Get the indices if required:
# gray_next_to_black_idx = np.where(gray_next_to_black)
# Show image and masks for testing:
cv2.imshow("img", cv2.resize(img, (256, 256), interpolation=cv2.INTER_NEAREST))
cv2.imshow("gray_mask", cv2.resize(gray_mask.astype(np.uint8)*255, (256, 256), interpolation=cv2.INTER_NEAREST))
cv2.imshow("black_mask", cv2.resize(black_mask.astype(np.uint8)*255, (256, 256), interpolation=cv2.INTER_NEAREST))
cv2.imshow("shifted_black_mask", cv2.resize(shifted_black_mask.astype(np.uint8)*255, (256, 256), interpolation=cv2.INTER_NEAREST))
cv2.imshow("gray_next_to_black", cv2.resize(gray_next_to_black.astype(np.uint8)*255, (256, 256), interpolation=cv2.INTER_NEAREST))
cv2.waitKey()
cv2.destroyAllWindows()
Upvotes: 1