Reputation: 31
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:
Upvotes: 3
Views: 1966
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:
The positional arguments of the cv2.goodFeaturesToTrack()
method are:
image
8-bit or floating-point 32-bit, single-channel imagemaxCorners
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
Reputation: 53081
Here is one way to do that in Python/OpenCV by getting the largest external contour and reducing the vertices.
Input:
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:
Coordinates:
Polygon Points (x,y):
255,12
0,197
97,499
414,499
511,197
256,12
Upvotes: 1