在二进制图像中拟合平滑曲线

时间:2019-06-03 08:26:29

标签: python matplotlib image-processing scipy

我想在二进制图像中填充一条平滑线。

此图像是使用对比度,轮廓线,骨架,最近邻,轮廓分离等进行预处理的结果。

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

我尝试过的方法:

  1. 通过凸包显示的ConvexHull图像(图像不平滑)

  1. 最近的邻居连接。 (图像不平滑)

  2. scipy插值(由于多个y @x而出现锯齿线)

  3. matplotlib样条曲线

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

3 个答案:

答案 0 :(得分:0)

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

选择一个点作为起点,例如,在图形的侧面或边缘上存在高密度的点。

找到中位数到一侧或另一侧,排除飞行物并找到均值。移过去,然后再做一次。

对于具有两行的区域,您可以将中位数中考虑的点范围限制为当前点或上一个点的某个范围内。

中位数将避免对遥远点进行超重,并且倾向于在x(或y,如果您愿意)的那个点向数据中心强烈拉动。

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

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

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

答案 1 :(得分:0)

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

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

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

以下是在图像上进行侵蚀几步的示例。

enter image description here

答案 2 :(得分:0)

可以使用以下步骤解决此问题,下面提供了代码:

  1. 首先连接所有最近的邻居点。这将在曲线或图形进行的过程中提供阵列。

  2. 然后使用univariateSpline平滑使曲线平滑。

已解决的问题-之字形线将根据曲线变得平滑。

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

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