Skip to content
Advertisement

Find all coordinates of black / grey pixels in image using python

I’m trying to find a way to read any any .png, .jpg or .tiff, and return the coordinates of all black or grey pixels in that image.

I’m thinking of having a certain threshold grey color, and writing out the coordinates of every pixel that is darker than that. I’m not sure how to manage the aspect of reading the image, however. I’m aiming to have my result be lists of all black pixels in the image, as such:

[x-coord, y-coord, black]

I’ve looked into using cv.imread to read out the coordinates of pixels, but as far as I’ve been able to tell, it works exactly opposite to the way I want it – it takes coordinates as a parameter, and returns the RGB values. Does anyone have tips / methods of making this work?

For anyone with similar questions, I solved this using the answer below, then I turned the numpy-array into a list using np.ndarray.tolist(). Additionally, since I only got a truncated version of the results, i used:

import sys

np.set_printoptions(threshold=sys.maxsize)

Now it was simple to print any element from the list using indices.

Advertisement

Answer

You can use np.column_stack() + np.where(). The idea is to convert the image to grayscale then find the coordinates of all pixels below a certain threshold. Note in grayscale, the image has one channel with pixel values [0 ... 255]


Using this input image with a threshold_level = 20

We color in all pixels below this threshold level in blue

All pixel coordinates can be determined from the mask using np.where() and stacked into (x, y) format with np.column_stack(). Here are all coordinates of pixels lower than the threshold

coords = np.column_stack(np.where(gray < threshold_level))
[[ 88 378]
 [ 89 378]
 [ 90 378]
 ...
 [474 479]
 [474 480]
 [474 481]]

With threshold_level = 50:

[[ 21 375]
 [ 22 375]
 [ 23 376]
 ...
 [474 681]
 [474 682]
 [474 683]]

Code

import cv2
import numpy as np

image = cv2.imread('1.jpg')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# Set threshold level
threshold_level = 50

# Find coordinates of all pixels below threshold
coords = np.column_stack(np.where(gray < threshold_level))

print(coords)

# Create mask of all pixels lower than threshold level
mask = gray < threshold_level

# Color the pixels in the mask
image[mask] = (204, 119, 0)

cv2.imshow('image', image)
cv2.waitKey()

With your input image and threshold_level = 10

[[  59  857]
 [  59  858]
 [  59  859]
 ...
 [1557  859]
 [1557  860]
 [1557  861]]
User contributions licensed under: CC BY-SA
1 People found this is helpful
Advertisement