测量梯形OpenCV的中心宽度

时间:2018-10-16 03:33:10

标签: c++ opencv contour

我正在尝试测量以下梯形的中心宽度(w3),但没有成功。
反正有什么可以衡量的?

此刻我可以测量中心点并打印每个轮廓点。

这是我的代码:

 Mat gray;
    cvtColor(inputImage, gray, CV_BGR2GRAY);

    cv::findContours(gray, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_NONE);
    vector<Moments>mu(contours.size());
    for(int i=0; i < contours.size(); i++)
    {
        mu[i] = moments(contours[i],false);
    }


    vector<Point2f>mc(contours.size());
    for(int i=0; i < contours.size(); i++)
    {
        mc[i] = Point2f(mu[i].m10/mu[i].m00, mu[i].m01/mu[i].m00);
        //cout << mu[i].m01/mu[i].m00 <<endl;
        for(size_t cP=0; cP < contours[i].size(); cP++)
            {
                cv::Point currentContourPixel = contours[i][cP];

                //cout <<currentContourPixel<<endl;
            }

    }

trapezoid

1 个答案:

答案 0 :(得分:0)

这可以通过使用基本数学函数来完成。

  1. 正确准备图像(色彩空间转换,阈值...)并搜索轮廓,然后选择梯形。

  2. 计算最高点和最低点。

  3. 为梯形的每一侧(a,b,c,d)制作4个列表,为临时(b + d)制作一个列表

  4. 遍历轮廓并附加到a,c和临时b + d。 a中的点应具有与最低点y轴相同的y轴。 c中的点应具有与最高点y轴相同的y轴。 b + d中的点应具有所有其他点。

  5. 按a和c的x轴排序-从最小到最大。

  6. 遍历b + d并追加b和d。 d中的点应与c中的第一个元素具有相同或更小的x轴。 b中的点应与c中的最后一个元素具有相同或更大的x轴。

  7. 计算所有边的中间点。每边X,Y = ((x2+x1)/2, (y2+y1)/2)

  8. 的中间点的公式
  9. 您的宽度等于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()

结果:

enter image description here