这可以通过使用初等数学函数来完成。
正确准备图像(空间转换、阈值...)并搜索轮廓,然后选择梯形。
计算最高点和最低点。
为梯形的每一边(a、b、c、d)制作 4 个列表,为临时(b+d)制作一个列表
遍历轮廓并附加到 a、c 和临时 b+d。 a 中的点应与最低点 y 轴具有相同的 y 轴。 c 中的点应与最高点 y 轴具有相同的 y 轴。 b+d 中的点应该包含所有其他点。
按 x 轴对 a 和 c 排序 - 从小到大。
遍历 b+d 并附加 b 和 d。 d 中的点应与 c 中的第一个元素具有相同或更小的 x 轴。 b 中的点应与 c 中的最后一个元素具有相同或更大的 x 轴。
计算所有边的中点。每边的中点公式X,Y = ((x2+x1)/2, (y2+y1)/2)
你的宽度等于 d 的中点到 b 的中点之间的距离。两点之间的距离公式sqrt((x2-x1)^2 + (y2-y1)^2)。
我在 Python 中做了一个示例(我不知道 C++ 语法),但它应该很容易翻译成 C++。希望它有点帮助。干杯!
例子:
import cv2
import numpy as np
# Read the image
img = cv2.imread('trapez.png')
# Transform to gray colorspace and invert Otsu threshold the image
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
_, thresh = cv2.threshold(gray,0,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)
# Search for contours and select the biggest
_, contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
cnt = max(contours, key=cv2.contourArea)
# Calclate the higest and lowest point
top = tuple(cnt[cnt[:, :, 1].argmin()][0])
bottom = tuple(cnt[cnt[:, :, 1].argmax()][0])
# Make 4 lists for every side of trapezoid and one for temporary bd
a = []
b = []
c = []
d = []
bd_temp = []
# Iterate through contour and append to a, c and temporary list
## Points in a should have the same y axis as the lowest point y axis
## Points in c should have the same y axis as the highest point y axis
## Temporary should have all others (b and d)
for i in cnt:
if i[0][1] == top[1]:
c.append(tuple(i[0]))
if i[0][1] == bottom[1]:
a.append(tuple(i[0]))
else:
bd_temp.append(tuple(i[0]))
# Sort a and c by their x axis - smallest to biggest
a.sort(key = lambda x: x[0])
c.sort(key = lambda x: x[0])
# Itterate through bd_temp and append b and d
## Points in d should have the same or smaller x axis as the first element in c
## Points in b should have the same or bigger x axis as the last element in c
for i in bd_temp:
if i[0] <= c[0][0]:
d.append(i)
if i[0] >= c[-1][0]:
b.append(i)
# Sort b and d by their x axis - smallest to biggest
b.sort(key = lambda x: x[1])
d.sort(key = lambda x: x[1])
# Calculate middle points for all sides ((x2+x1)/2, (y2+y1)/2)
half_line_a = tuple([int((a[0][0]+a[-1][0])/2), int((a[0][1]+a[-1][1])/2)])
half_line_c = tuple([int((c[0][0]+c[-1][0])/2), int((c[0][1]+c[-1][1])/2)])
half_line_b = tuple([int((b[0][0]+b[-1][0])/2), int((b[0][1]+b[-1][1])/2)])
half_line_d = tuple([int((d[0][0]+d[-1][0])/2), int((d[0][1]+d[-1][1])/2)])
# Optional integers for calculating the width
x2 = half_line_b[0]
x1 = half_line_d[0]
y2 = half_line_b[1]
y1 = half_line_d[1]
# Width equals to distance between middle point of d to middle point of b
## Formula for distance between two points sqrt((x2-x1)^2 + (y2-y1)^2)
width = np.sqrt(((x2-x1)**2)+((y2-y2)**2))
center = tuple([half_line_c[0], y1])
# Optional drawing on the image
cv2.arrowedLine(img, half_line_b, half_line_d, (0,0,255), 1)
cv2.arrowedLine(img, half_line_d, half_line_b, (0,0,255), 1)
cv2.circle(img, center, 2, (255,0,0), -1)
cv2.putText(img,'Width = '+str(width),(20,20), cv2.FONT_HERSHEY_SIMPLEX, 0.5,(0,0,0),1,cv2.LINE_AA)
# Display the image
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
结果: