【问题标题】:Polygonization of detected Contours检测到的轮廓的多边形化
【发布时间】:2021-10-29 05:31:05
【问题描述】:

我想提取给定轮廓的相关点,我使用一些预处理和 opencv 中的findContours() 函数检测到这些点。这是一个例子 contour。线条中的“峰值”应该被平滑掉。目前我使用 Lang 算法来完成这项任务。

def lang(tolerance,p,step):
    mask = np.ones(len(p),dtype='bool')
    start = 0
    end = 2

    marker = np.array([p[start],p[end]],dtype='double')

    if step == -1:
        maxstep = len(p)
    else:
    maxstep = min(step,len(p))

    while end < len(p) and end < maxstep:
        bGreater = False
        for i in range(start,end):
            ldist = point_line_distance(p[i,0],p[i,1],
                                    p[start,0],p[start,1],
                                    p[end,0],p[end,1])
            if ldist>tolerance:
                bGreater = True
                break
        marker = np.array([p[start],p[end]])
        if bGreater:
            mask[start+1:end-1] = False
            start = end-1
            end = start+2
        else:
            end = end+1
    mask[start+1:end-1]=False
 
    return mask,marker

Lang Implementation

通过对公差和步长进行一些调整,它可以很好地发挥作用。主要的缺点是,它还可以平滑轮廓拐角处和其他点的倒角。

有人有更好的建议吗? 以下是示例轮廓的要点:

array([[[ 508, 1659]],
   [[ 507, 1660]],
   [[ 478, 1660]],
   [[ 473, 1665]],
   [[ 473, 1666]],
   [[ 472, 1667]],
   [[ 472, 1724]],
   [[ 471, 1725]],
   [[ 418, 1725]],
   [[ 417, 1724]],
   [[ 417, 1723]],
   [[ 418, 1722]],
   [[ 418, 1718]],
   [[ 419, 1717]],
   [[ 416, 1717]],
   [[ 417, 1718]],
   [[ 417, 1724]],
   [[ 416, 1725]],
   [[ 406, 1725]],
   [[ 471, 1725]],
   [[ 472, 1726]],
   [[ 472, 1772]],
   [[ 476, 1776]],
   [[ 476, 1778]],
   [[ 478, 1778]],
   [[ 479, 1779]],
   [[ 714, 1779]],
   [[ 715, 1780]],
   [[ 716, 1779]],
   [[1594, 1779]],
   [[1595, 1780]],
   [[1595, 2013]],
   [[1594, 2014]],
   [[1593, 2014]],
   [[1594, 2014]],
   [[1595, 2015]],
   [[1595, 2026]],
   [[1595, 1780]],
   [[1596, 1779]],
   [[1766, 1779]],
   [[1767, 1778]],
   [[1768, 1778]],
   [[1771, 1775]],
   [[1772, 1775]],
   [[1772, 1773]],
   [[1773, 1772]],
   [[1773, 1667]],
   [[1772, 1666]],
   [[1772, 1663]],
   [[1770, 1663]],
   [[1767, 1660]],
   [[1685, 1660]],
   [[1684, 1659]],
   [[1683, 1659]],
   [[1682, 1660]],
   [[1124, 1660]],
   [[1123, 1659]],
   [[1122, 1659]],
   [[1121, 1660]],
   [[ 563, 1660]],
   [[ 562, 1659]],
   [[ 561, 1659]],
   [[ 560, 1660]],
   [[ 510, 1660]],
   [[ 509, 1659]]], dtype=int32)

【问题讨论】:

    标签: python opencv contour


    【解决方案1】:

    考虑一个不同的简化器。 Visvalingamwyatt 最大限度地减少了面积变化,并且对我的样本集很有效。在pypi中有实现: https://pypi.org/project/visvalingamwyatt/ 或只是 pip install visvalingamwyatt

    对于你的向量,我做了:vv.simplify(b, threshold=8)。它消除了尖刺,虽然倒角简化了,但拐角仍然准确。

    【讨论】:

      【解决方案2】:

      一种方法是在图像上绘制轮廓(厚度 = -1),对图像进行一些处理以去除峰值线。然后从处理后的图像中找到新的轮廓(这将没有峰值)。

      我已将您的轮廓存储在变量cont 中。剩下的代码是共享的。

      img = np.zeros((2500, 2500, 1), dtype=np.uint8)
      cv2.drawContours(img, [cont], -1, 255, -1)
      
      kernel = np.ones((3, 3), dtype=np.uint8)
      img = cv2.erode(img, kernel, iterations=2)
      img = cv2.dilate(img, kernel, iterations=2)
      
      Contours = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[-2]
      Contour = sorted(Contours, key=lambda x:cv2.contourArea(x))[0]
      

      没有峰的结果轮廓存储在变量Contour中。

      下面是使用厚度 = -1 标志绘制的初始轮廓的图像。

      下面是处理后的图像。

      下图是最终轮廓没有峰的图像。

      【讨论】:

      • 谢谢!成功了!
      猜你喜欢
      • 1970-01-01
      • 2014-05-21
      • 2014-11-24
      • 1970-01-01
      • 2022-07-12
      • 2013-12-29
      • 2013-10-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多