【问题标题】:measure center width of Trapezoid OpenCV测量梯形 OpenCV 的中心宽度
【发布时间】:2019-03-20 12:33:08
【问题描述】:

我正在尝试测量以下梯形的中心宽度 (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

【问题讨论】:

    标签: c++ opencv contour


    【解决方案1】:

    这可以通过使用初等数学函数来完成。

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

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

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

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

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

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

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

    8. 你的宽度等于 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()
    

    结果:

    【讨论】:

      猜你喜欢
      • 2016-02-14
      • 1970-01-01
      • 1970-01-01
      • 2015-12-30
      • 1970-01-01
      • 2016-03-18
      • 1970-01-01
      • 2016-06-02
      • 2013-08-01
      相关资源
      最近更新 更多