您可以基于原点的拐角距离和相对拐角位置来选择排序。
Find contours and hierarchy.
保持轮廓无子(基于层次结构)。
Find corners of bounding rectangles.
根据以下条件分析拐角(或更简单的条件):
Top left contours is the one with the minimum distance of top left corner.Bottom right contours is the one with the maximum distance of top left corner.Other two contours can be separated by maximum x and maximum y (after eliminating the top left and bottom right).
以下解决方案以颜色绘制边界矩形以进行测试:
RedGreenBlueYellow
这是一个工作代码示例(请阅读注释):
import numpy as np
import cv2
# Read input image as Grayscale
img = cv2.imread('img.png', cv2.IMREAD_GRAYSCALE)
# Convert img to uint8 binary image with values 0 and 255
# All black pixels goes to 0, and other pixels goes to 255
ret, thresh_gray = cv2.threshold(img, 1, 255, cv2.THRESH_BINARY)
# Find contours in thresh_gray.
cnts, hiers = cv2.findContours(thresh_gray, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)[-2:] # [-2:] indexing takes return value before last (due to OpenCV compatibility issues).
corners = [] # List of corners
dist = np.array([]) # Array of distance from axes origin
# Iterate cnts and hiers, find bounding rectangles, and add corners to a list
for c, h in zip(cnts, hiers[0]):
# If contours has no child
if h[2] == -1:
# Get bounding rectangle
x, y, w, h = cv2.boundingRect(c)
# Append corner to list of corners - format is corners[i] holds a tuple: ((x0, y0), (x1, y1))
p0 = (x, y)
p1 = (x+w, y+h)
corners.append((p0, p1))
# Distance of corners from origin
d = np.array([np.linalg.norm(p0), np.linalg.norm(p1)])
if dist.size == 0:
dist = d
else:
dist = np.vstack((dist, d))
top_left = np.argmin(dist[:,0]) # Index of top left corner (assume minimum distance from origin)
bottom_right = np.argmax(dist[:,1]) # Index of top bottom right corner (assume maximum distance from origin)
tmp_corners = np.array(corners)
tmp_corners[top_left, :, :] = np.array(((0,0), (0,0))) #Ignore top_left corners
tmp_corners[bottom_right, :, :] = np.array(((0,0), (0,0))) #Ignore bottom_right corners
bottom_left = np.argmax(tmp_corners[:,1,1]) #Maximum y is bottom left
tmp_corners[bottom_left, :, :] = np.array(((0,0), (0,0))) #Ignore bottom_left corners
top_right = np.argmax(tmp_corners[:,1,0]) #Maximum x is top right
# Convert Grayscale to BGR (just for testing - for drawing rectangles in green color).
out = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
# Draw rectangles (for testing)
# 1. Red
# 2. Green
# 3. Blue
# 4. Yellow
cv2.rectangle(out, corners[top_left][0], corners[top_left][1], (0, 0, 255), thickness = 2)
cv2.rectangle(out, corners[bottom_left][0], corners[bottom_left][1], (0, 255, 0), thickness = 2)
cv2.rectangle(out, corners[top_right][0], corners[top_right][1], (255, 0, 0), thickness = 2)
cv2.rectangle(out, corners[bottom_right][0], corners[bottom_right][1], (0, 255, 255), thickness = 2)
cv2.imwrite('out.png', out) #Save out to file (for testing).
# Show result (for testing).
cv2.imshow('thresh_gray', thresh_gray)
cv2.imshow('out', out)
cv2.waitKey(0)
cv2.destroyAllWindows()
结果:
回答来源:stackoverflow