5

好吧,这个问题说明了一切

我有一些轮廓,我想从中得到最好的四边形

4

3 回答 3

4

我遇到了圆角卡片的问题,即使我approxPolyDP()只能返回 4 个点/边缘,它也永远不是最好的,因为“角落”经常被选为更接近这些圆角边缘。我的解决方案包括增加返回到拐角处的点数,然后我的问题让我可以相对安全地假设找到的四个最长边代表边。按顺序取这四个最长的边,找到每对相交的位置,你就有了四边形的点。

作为奖励,您已经有了长度,因此您可以以正确的顺序将点输入到您的透视变换中,这样它就不会以错误的方式被挤压和拉伸。

于 2013-11-11T04:51:10.980 回答
3

您必须使用嵌套区间的方法找到一个合适的值epsilon,因为点的数量随着 的减少而增加epsion。但是,可能无法达到 4 个角点的值,因为在某个 epsilon 值下,点的数量可能会从 3 跳到 5。

如果您想排除这种情况,您可能需要自己实现 Ramer-Douglas-Peucker 算法并对其进行修改,因此将返回给定数量的点。(顺便说一句,您要的是“最佳” 4 个角。您必须指定最佳含义。approxPolyDp()不要求最佳解决方案!)

除此之外,我认为没有办法强制approxPolyDP()退回 4 分。

于 2012-10-23T11:25:28.277 回答
3

我相信您可以对值执行二进制搜索epsilon以找到最佳简化。

编码:

def simplify_contour(contour, n_corners=4):
    '''
    Binary searches best `epsilon` value to force contour 
        approximation contain exactly `n_corners` points.

    :param contour: OpenCV2 contour.
    :param n_corners: Number of corners (points) the contour must contain.

    :returns: Simplified contour in successful case. Otherwise returns initial contour.
    '''
    n_iter, max_iter = 0, 100
    lb, ub = 0., 1.

    while True:
        n_iter += 1
        if n_iter > max_iter:
            return contour

        k = (lb + ub)/2.
        eps = k*cv2.arcLength(contour, True)
        approx = cv2.approxPolyDP(contour, eps, True)

        if len(approx) > n_corners:
            lb = (lb + ub)/2.
        elif len(approx) < n_corners:
            ub = (lb + ub)/2.
        else:
            return approx
于 2019-03-25T14:07:14.863 回答