how to use OpenCV and Python to find corners of a trapezoid similar to finding corners of a square?

Question:

I am using the following code to find the corners of the largest square in an image. I want to do the same thing, but if the square happens to be warped (like a trapezoid) it can still find the corners of the shape. How can I do this using Python’s OpenCV module?

importedImage = 'shapes.png'
originalImg = cv.imread(importedImage)

#filters image bilaterally and displays it
bilatImg = cv.bilateralFilter(originalImg, 5, 175, 175)

#finds edges of bilaterally filtered image and displays it
edgeImg = cv.Canny(bilatImg, 75, 200)

#gets contours (outlines) for shapes and sorts from largest area to smallest area
contours, hierarchy = cv.findContours(edgeImg, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)
contours = sorted(contours, key=cv.contourArea, reverse=True)

#boxes in largest rectangle
rectangle = cv.minAreaRect(contours[0])
corners = cv.boxPoints(rectangle).astype(np.int32)
Asked By: helloworld12345

||

Answers:

In order to solve your problem you can go with this snippet. I left comments on the new part to make it more easily understandable

import cv2
import numpy as np

importedImage = 'shapes.png'
originalImg = cv2.imread(importedImage)

#filters image bilaterally and displays it
bilatImg = cv2.bilateralFilter(originalImg, 5, 175, 175)

#finds edges of bilaterally filtered image and displays it
edgeImg = cv2.Canny(bilatImg, 75, 200)

#gets contours (outlines) for shapes and sorts from largest area to smallest area
contours, hierarchy = cv2.findContours(edgeImg, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
contours = sorted(contours, key=cv2.contourArea, reverse=True)

# drawing red contours on the image
for con in contours:
    cv2.drawContours(originalImg, con, -1, (0, 0, 255), 3)

# and double-checking the outcome
cv2.imshow("Contours check",originalImg)
cv2.waitKey()
cv2.destroyWindow("Contours check")

# find the perimeter of the first closed contour
perim = cv2.arcLength(contours[0], True)
# setting the precision
epsilon = 0.02*perim
# approximating the contour with a polygon
approxCorners = cv2.approxPolyDP(contours[0], epsilon, True)
# check how many vertices has the approximate polygon
approxCornersNumber = len(approxCorners)
print("Number of approximated corners: ", approxCornersNumber)

# can also be used to filter before moving on [if needed]
# i.e. if approxCornersNumber== 4:

# printing the position of the calculated corners
print("Coordinates of approximated corners:n", approxCorners)

Bonus: if you want to check which vertex is which you can simply append this last part based on this answer, where (x, y) are the coordinates provided above for each vertex

originalImg = cv2.circle(originalImg, (x,y), radius=10, color=(255, 255, 255), thickness=-1)
cv2.imshow("Vertex position",originalImg)
cv2.waitKey()
cv2.destroyWindow("Vertex position")
Answered By: Antonino
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.