Janson Joseph
Janson Joseph

Reputation: 31

Is there a Python function to get coordinates from an image?

I was wondering if there's a way to take an image like the Pentagon below and translate it into an array of points (x,y,x1,y1,x2,y2...) like:

(1,3,
2,6,
6,6,
7,3,
4,1)

With a coordinate system rooted in the top left. I know you can convert an image into array using opencv but that would translate each pixel into an element of the array. I'm looking to get just the non white elements and only the critical points of them (i.e. where they change direction).

Pentagon:

enter image description here

Upvotes: 3

Views: 1966

Answers (2)

Red
Red

Reputation: 27567

You can use the cv2.goodFeaturesToTrack() method to detect the corners of an image:

import cv2

img = cv2.imread("image.png", 0)

for (x, y) in cv2.goodFeaturesToTrack(img, 5, 0.01, 20)[:, 0].astype("int0"):
    cv2.circle(img, (x, y), 27, 127, -1)

cv2.imshow("Image", img)
cv2.waitKey(0)

Output:

enter image description here

The positional arguments of the cv2.goodFeaturesToTrack() method are:

  • image 8-bit or floating-point 32-bit, single-channel image
  • maxCorners Maximum number of corners to return. If there are more corners than are found, the strongest of them is returned. maxCorners <= 0 implies that no limit on the maximum is set and all detected corners are returned.
  • qualityLevel Parameter characterizing the minimal accepted quality of image corners. The parameter value is multiplied by the best corner quality measure, which is the minimal eigenvalue or the Harris function response. The corners with the quality measure less than the product are rejected.
  • minDistance Minimum possible Euclidean distance between the returned corners.

Upvotes: 2

fmw42
fmw42

Reputation: 53081

Here is one way to do that in Python/OpenCV by getting the largest external contour and reducing the vertices.

Input:

enter image description here

import cv2
import numpy as np

# load image
img = cv2.imread("pentagon.png")

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

# threshold and invert
thresh = cv2.threshold(gray, 128, 255, cv2.THRESH_BINARY_INV)[1]

# get the largest external contour
contours = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]
big_contour = max(contours, key=cv2.contourArea)
peri = cv2.arcLength(big_contour, True)

# reduce to fewer vertices on polygon
poly = cv2.approxPolyDP(big_contour, 0.01 * peri, False)

# list polygon points
result = img.copy()
print("Polygon Points:")
for p in poly:
    x = p[0][0]
    y = p[0][1]
    pt = str(x) + "," + str(y)
    print(pt)
    cv2.circle(result,(x,y),3,(0,0,255),-1)

# save result
cv2.imwrite("pentagon_corners.png", result)

# display it
cv2.imshow("thresh", thresh)
cv2.imshow("result", result)
cv2.waitKey(0)

Result:

enter image description here

Coordinates:

Polygon Points (x,y):
255,12
0,197
97,499
414,499
511,197
256,12

Upvotes: 1

Related Questions