【问题标题】:Fit a smooth curve in binary image在二值图像中拟合平滑曲线
【发布时间】:2019-10-18 18:53:08
【问题描述】:

我想在二值图像中拟合一条平滑线。

此图像是使用对比度、轮廓、骨架、最近邻、轮廓分离等预处理的结果。初始图像

我认为一旦我得到一个白点数组(x,y),拟合曲线会非常容易。但是,当我尝试在此图像中拟合曲线时,由于某个 x 处的多个值,会出现一条锯齿线。我需要一个通用的解决方案来解决我的问题。我的形象可能会有所不同(我正在制作一个应用程序)。对于特定的 x,它可以有 4-5 个值,反之亦然。

我尝试过的方法:

  1. ConvexHull 图像由凸包(图像不平滑)

  1. 最近的邻居连接。 (画面不流畅)

  2. scipy interpolate (zig-zag line 由于多个 y @x 出现)

  3. matplotlib 样条曲线

建议我如何在此类图像中拟合平滑曲线。

【问题讨论】:

  • 这是一个很好的问题,提供了一个示例输入,并且说明得很好,可以理解需要做什么。这有点棘手,但我想我知道如何以稳健的方式做到这一点。以后会努力找时间的,
  • @DrM 感谢您的评论。如果你能告诉我如何做到这一点的概述。我也许可以自己实现它。

标签: python matplotlib image-processing scipy


【解决方案1】:

我理解这个问题的意思是你想通过数据找到曲线作为 x 和 y 坐标的列表。

选择一个点作为起点,例如,在图形的一侧或边缘处有高密度点的位置。

找到一侧或另一侧的中位数,排除传单并找到平均值。移动,然后再做一次。

对于有两条线的区域,您可以将考虑中值的点范围限制在当前点或上一个点的某个范围内。

中位数将避免远距离点的权重过大,并倾向于在 x(或 y,如果您愿意)的那个点处强烈拉向数据中心。

平均值通常与您可能正在研究的物理理论或模型有更紧密的关系。

您可以对不同的数据点集群重复此操作,以找到所有线。

最后比较所有曲线并修剪重复项,例如通过平方差之和检测。

【讨论】:

    【解决方案2】:

    这可能有点用,我不能肯定地说,因为我不知道你所有目标图像的特征。

    1. 将图像转换为灰度
    2. 根据您定义的停止标准(可能基于某些指标,例如连接的组件),将腐蚀应用于您的图像若干步骤

    在形态转换部分检查 OpenCV 库中的相关 API 调用。

    以下是对图像应用侵蚀几个步骤的示例。

    【讨论】:

    • 我使用 GIMP 制作了上图
    • OP 已经有一个骨架化的图像(参考第一个)。目标是参数化非零点并通过这些点拟合轮廓或曲线。
    • 是的,我明白了。在他尝试曲线拟合算法之前,我为他提供了一种减少图像噪声的方法。
    【解决方案3】:

    这可以通过以下步骤解决,代码如下:

    1. 首先连接所有最近的邻居点。这将以曲线或图形的前进方式提供数组。

    2. 然后使用单变量样条平滑使您的曲线平滑。

    问题已解决 - 锯齿线将根据曲线变得平滑。

    连接所有最近邻居的代码:

    def distance(P1, P2):
        return ((P1[0] - P2[0])**2 + (P1[1] - P2[1])**2) ** 0.5
    
    def optimized_path(coords, start=None):
        if start is None:
            start = coords[0]
        pass_by = coords
        path_connected = [start]
        pass_by.remove(start)
        while pass_by:
            nearest = min(pass_by, key=lambda x: distance(path_connected[-1], x))
            path_connected.append(nearest)
            pass_by.remove(nearest)
        return path_connected
    
    start = None
        points=[[i,j] for i,j in zip(x_data,y_data)]
        points = optimized_path(points,start)
    

    平滑最近邻点的代码:

    # Smoothing
    distance_smooth = np.cumsum( np.sqrt(np.sum( np.diff(points, axis=0)**2, axis=1 )) )
    distance_smooth = np.insert(distance_smooth, 0, 0)/distance_smooth[-1]
    splines = [UnivariateSpline(distance_smooth, coords, k=5, s=None) for coords in points.T]
    alpha = np.linspace(0, 1, 75)
    points_fitted = np.vstack( spl(alpha) for spl in splines ).T
    

    这是最终的图像-Smooth Image

    【讨论】:

      猜你喜欢
      • 2017-01-02
      • 1970-01-01
      • 2017-08-02
      • 1970-01-01
      • 1970-01-01
      • 2017-08-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多