Extract x,y coordinates of each pixel from an image in Python

15,049

Solution 1

Since the format you're showing seems to be pandas, I'll present the output with pandas, but you could just use a mere print. :)

I even included a n-dimension solution to your problem as comments.

import numpy as np
from itertools import product

arr = np.array([
    list(range(300))
    for _ in range(200)
])

print(arr.shape)
# (200, 300)

pixels = arr.reshape(-1)

""" n-dimension solution
    coords = map(range, arr.shape)
    indices = np.array(list( product(*coords) ))
"""
xs = range(arr.shape[0])
ys = range(arr.shape[1])
indices = np.array(list(product(xs, ys)))

import pandas as pd
pd.options.display.max_rows = 20

index = pd.Series(pixels, name="pixels")
df = pd.DataFrame({
    "x" : indices[:, 0],
    "y" : indices[:, 1]
}, index=index)
print(df)
#           x    y
# pixels          
# 0         0    0
# 1         0    1
# 2         0    2
# 3         0    3
# 4         0    4
# 5         0    5
# 6         0    6
# 7         0    7
# 8         0    8
# 9         0    9
# ...     ...  ...
# 290     199  290
# 291     199  291
# 292     199  292
# 293     199  293
# 294     199  294
# 295     199  295
# 296     199  296
# 297     199  297
# 298     199  298
# 299     199  299

# [60000 rows x 2 columns]

Solution 2

Here is one very simple way to do that using Python/OpenCV, assuming I understand your question. Convert the image to grayscale and then use np.where().

import cv2
import numpy as np

# create red image
img = np.full((10,10,3), (0,0,255), dtype=np.uint8)

# convert to grayscale
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

# get coordinates (y,x) --- alternately see below for (x,y)
yx_coords = np.column_stack(np.where(gray >= 0))
print (yx_coords)

print ('')

# get coordinates (x,y)
xy_coords = np.flip(np.column_stack(np.where(gray >= 0)), axis=1)
print (xy_coords)


Returns for (x,y):

[[0 0]
 [1 0]
 [2 0]
 [3 0]
 [4 0]
 [5 0]
 [6 0]
 [7 0]
 [8 0]
 [9 0]
 [0 1]
 [1 1]
 [2 1]
 [3 1]
 [4 1]
 [5 1]
 [6 1]
 [7 1]
 [8 1]
 [9 1]
 [0 2]
 [1 2]
 [2 2]
 [3 2]
 [4 2]
 [5 2]
 [6 2]
 [7 2]
 [8 2]
 [9 2]
 [0 3]
 [1 3]
 [2 3]
 [3 3]
 [4 3]
 [5 3]
 [6 3]
 [7 3]
 [8 3]
 [9 3]
 [0 4]
 [1 4]
 [2 4]
 [3 4]
 [4 4]
 [5 4]
 [6 4]
 [7 4]
 [8 4]
 [9 4]
 [0 5]
 [1 5]
 [2 5]
 [3 5]
 [4 5]
 [5 5]
 [6 5]
 [7 5]
 [8 5]
 [9 5]
 [0 6]
 [1 6]
 [2 6]
 [3 6]
 [4 6]
 [5 6]
 [6 6]
 [7 6]
 [8 6]
 [9 6]
 [0 7]
 [1 7]
 [2 7]
 [3 7]
 [4 7]
 [5 7]
 [6 7]
 [7 7]
 [8 7]
 [9 7]
 [0 8]
 [1 8]
 [2 8]
 [3 8]
 [4 8]
 [5 8]
 [6 8]
 [7 8]
 [8 8]
 [9 8]
 [0 9]
 [1 9]
 [2 9]
 [3 9]
 [4 9]
 [5 9]
 [6 9]
 [7 9]
 [8 9]
 [9 9]]


Solution 3

In your example, the pixel index order indicates row-major ordering. Given this, you can get the x and y values for any arbitrary pixel using the following function:

def idx_to_xy(idx):
    '''
    Assumes idx starts at one, as in the provided example
    '''
    x = (idx - 1) % 300
    y = (idx - 1) // 300

    return x, y

for px in [1, 2, 301, 302, 60000]:
    x, y = idx_to_xy(px)
    print("%5d    %3d  %3d" %(px, x, y))

# pixels     x    y
#      1      0    0
#      2      1    0
#    301      0    1
#    302      1    1
#  60000    299  199
Share:
15,049

Related videos on Youtube

fastlanes
Author by

fastlanes

Updated on June 04, 2022

Comments

  • fastlanes
    fastlanes almost 2 years

    Let's say I have a color image that I've loaded into a numpy array of dimensions (200 x 300 x 3). In total, there are 60,000 pixels in the image. I'm trying to extract the width,height (x,y) coordinates of each pixel starting from the upper left top corner representing pixel 1 such that:

    pixel#   x    y
    1        0    0
    2        1    0
    .
    .
    301      0    1
    302      1    1
    .
    .
    60,000   299 199   
    

    I'm tempted to use a for loop to do this in a more manual-nature but are there libraries or more effective ways to get those coordinate values for each pixel as such?

    • ALollz
      ALollz about 4 years
      It's unclear to me where this begins. What exactly are you extracting? It seems like the above DataFrame could be created with 2 simple numbers X=300 and Y=200 and basically no other information. Is that the case?