【问题标题】:Find point on contour with given y-value在给定 y 值的轮廓上查找点
【发布时间】:2021-01-26 17:15:22
【问题描述】:

我有各种由 cv2.findContours(cv2.CHAINE_APPROX_NONE) 提取的轮廓。之后我还提取了极值点。现在我想找到轮廓中与最左边/最右边相对的点。可以说,轮廓中与最左/最右点具有相同 y 坐标的点。由于大多数函数很难读取坐标的格式,因此诀窍可能是重新排序。

知道怎么解决吗?

    ###contour extraction
    cnts = cv2.findContours(img_thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
    cnts = cnts[0]
    (cnts, _) = contours.sort_contours(cnts)

    cnt_number = 0

    for cnt in cnts:
        if cv2.contourArea(cnt) > 500:
        contour_lenght = cv2.arcLength(cnt, True)
        approx = cv2.approxPolyDP(cnt, 0.005 * contour_lenght, True)
        obj_cor = len(approx)

        if obj_cor > 4:
            cv2.drawContours(blank_image, cnt, -1, (0, 0, 0), 2)
            leftmost = tuple(cnt[cnt[:, :, 0].argmin()][0])
            rightmost = tuple(cnt[cnt[:, :, 0].argmax()][0])

还想进行线轮廓交点(就像 math.coffee 在这里 Line intersecting contour in openCv 建议的那样),但不确定如何...

            ###bounding box
            x, y, w, h = cv2.boundingRect(approx)
            ###end of line from leftmost
            left_y = leftmost[1]
            left_x = leftmost[0] + w
            left_line_endpoint = (left_x, left_y)
            ###line intersect function suggested by mathematical.coffee
            numpy.logical_and(...)

【问题讨论】:

    标签: python opencv line contour point


    【解决方案1】:

    如果我正确理解了你的想法,这将是这样的(请原谅我对线性代数的糟糕掌握)

    import cv2
    import numpy as np
    
    def intersection(l0, l1):   # (origin, drection), (origin, drection) -> point in scene coords
        l0 = np.float32(l0)
        l1 = np.float32(l1)
    
        dOrg = l1[0] -l0[0]
        g1ort = np.float32([-l1[1][1], l1[1][0]])
        g0 = np.float32([l0[1][0], l0[1][1]])
    
        if abs(np.dot(g0, g1ort)) < 1e-32:
            return None
        else:
            t0 = np.dot(dOrg, g1ort)/np.dot(g0, g1ort)
            return l0[0] +l0[1]*t0
    
    img = np.zeros((450, 450, 3), dtype=np.uint8)
    
    # badpoints = [[10,100], [180,250], [380,160], [220,360], [180,360], [70,210]]
    points = [[200,100], [180,250], [380,160], [220,360], [180,360], [70,210]]
    cont = [np.int32(points).reshape(len(points), 1, 2)]  # convert it into this weird format cv so wants
    cv2.drawContours(img, cont, -1, (0,0xff,0), 3)
    
    leftmost = points[np.argmin(np.array(points)[:,0])]
    hor_line = [leftmost, [100, 0]]
    cont_lines = np.float32(list(zip(points, points[1:]+[points[0]])))  # make segment list (scene coords)
    cont_lines = [[segment[0], segment[1]-segment[0]] for segment in cont_lines]    # convert to parametric
    intersections = [intersection(hor_line, line) for line in cont_lines]   # cache intersection results for each segt
    
    for pt in intersections:
        if pt is not None:
            cv2.circle(img, tuple(np.int32(pt)), 7, (0,0,255), 3)
    
    rightmost = None
    for isect, segt in zip(intersections, cont_lines):
        if isect is not None:
            gline = segt[1]
            dOrg = isect -segt[0]
            t = np.dot(gline, dOrg)/np.dot(gline, gline)
            if 0 <= t <= 1:  # check that only those intersection points that lie in boundaries of segments are used
                if rightmost is None:
                    rightmost = isect
                elif rightmost[0] < isect[0]:
                    rightmost = isect
    
    cv2.circle(img, tuple(np.int32(rightmost)), 11, (255,0,0), 3)
    
    cv2.imshow('test', img)
    cv2.waitKey(0)
    

    考虑将points 数组替换为badpoints。这将导致最左边的点也是最上面的,因此它的右边没有匹配的线段相交

    【讨论】:

    • 谢谢,JVod。你的代码运行良好,接近我需要的。我正在尝试将其应用于我的代码。麻烦,因为我不确定如何将我的轮廓插入到您使用这些点的位置。
    • @ArchCode 尝试使用此函数将单个轮廓转换为点数组def cv_cont2points(cont): cont = np.array(cont) return cont.reshape(cont.shape[0], 2)
    • 抱歉回复晚了。我无法得到你的建议为我竞选。我想出了一个更简单的解决方案,我采用已知点 x 值,将边界框的宽度添加到它,运行 cv2.pointPolygontest() 并从 x 值中减去结果。这是代码,如果您有兴趣:leftmost = tuple(cnt[cnt[:, :, 0].argmin()][0]) left_end_x = leftmost[0] + w left_end = (left_end_x, leftmost[1]) dist_to_cnt_left = abs(cv2.pointPolygonTest(cnt, left_end, True)) left_end_new = (int(left_end_x - dist_to_cnt_left), left_end[1])
    猜你喜欢
    • 1970-01-01
    • 2014-10-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-15
    • 1970-01-01
    • 2012-02-25
    相关资源
    最近更新 更多