简体   繁体   English

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

[英]Fit a smooth curve in binary image

I want to fit a smooth line in a binary image. 我想在二进制图像中插入平滑线。

This image is the result of preprocessing using contrast, contour, skeleton, nearest neighbor, contour separation, etc. Initial image 该图像是使用对比度,轮廓,骨架,最近邻,轮廓分离等进行预处理的结果。初始图像

I thought fitting a curve will be very easier once I will get an array(x,y) of white dots. 我认为一旦我得到一个白色圆点阵列(x,y),拟合曲线会更容易。 But when I try to fit a curve in this image, a zigzag line appears due to the multiple values at a certain x. 但是当我尝试在此图像中拟合曲线时,由于某个x处的多个值,会出现锯齿形线。 I need a generalized solution to my problem. 我需要一个解决我问题的通用解决方案。 My image can vary (I am making an app). 我的图片可能会有所不同(我正在制作应用)。 It can have 4-5 values for a particular x or vice-versa. 对于特定x,它可以具有4-5个值,反之亦然。

Methods I tried: 方法我试过:

  1. ConvexHull image by convex hull(image is not smooth) 凸壳的凸面图像(图像不平滑)

  1. Nearest neighbor connection. 最近邻连接。 (image is not smooth) (图像不顺畅)

  2. scipy interpolate (zig-zag line appear due to multiple y @x) scipy interpolate(由于多个y @x出现之字形线)

  3. matplotlib spline curve matplotlib样条曲线

Suggest me how to fit a smooth curve in such images. 建议我如何在这些图像中拟合平滑曲线。

I understand the question to mean that you want to find the curve through the data as a list of x and y coordinates. 我理解这个问题意味着你想通过数据找到曲线作为x和y坐标的列表。

Pick a point to start, for example, where there is a high density of points at along side or edge of the graph. 选择一个点开始,例如,在图的边或边缘有高密度的点。

Find the median to one side or the other, exclude fliers and find the mean. 找到一方或另一方的中位数,排除传单并找到平均值。 Move over, and do it again. 移过去,再做一次。

For a region with two lines, you might limit the range of points considered in the median to those within some range of the current or previous point. 对于具有两条线的区域,您可以将中位数中考虑的点的范围限制为当前或前一点的某个范围内的点。

The median will avoid overweighting for distant points, and will tend to pull strongly towards the center of the data at that point in x (or y, if you like). 中位数将避免对远点进行超重,并且倾向于在x(或y,如果你愿意)的那一点强烈地朝向数据的中心拉动。

The mean often has a stronger relationship to a physical theory or model that you might be examining. 平均值通常与您可能正在检查的物理理论或模型有更强的关系。

You can repeat this for different clusters of data points, to find all of the lines. 您可以对不同的数据点集群重复此操作,以查找所有行。

Finally compare over all of the curves and prune the duplicates, as detected for example by sum of square differences. 最后比较所有曲线并修剪重复,例如通过平方差的总和检测。

This might be of some use, I cannot say for sure because I do not know characteristics of all your target images. 这可能是有用的,我不能肯定地说,因为我不知道所有目标图像的特征。

  1. Convert image to grayscale 将图像转换为灰度
  2. Apply erosion to your image for some number of steps based on a stopping criteria that you define (based on some metric like connected components, may be) 根据您定义的停止条件(根据某些指标,如连接的组件,可能)对您的图像应用侵蚀以执行一些步骤

Check OpenCV library for relevant API calls in the morphological transformation section. 在形态转换部分中检查OpenCV库以获取相关的API调用。

Here is a sample of applying erosion on your image for a few steps. 以下是几个步骤对图像进行侵蚀的示例。

在此输入图像描述

This can be solved by using following steps and code is provided below: 这可以通过使用以下步骤来解决,代码如下:

  1. First connect all the nearest neighbour points. 首先连接所有最近的邻居点。 This will provide array in the way curve or graph is progressing. 这将以曲线或图形的方式提供数组。

  2. Then use univariateSpline smoothing to make your curve smooth. 然后使用单变量样条平滑来使曲线平滑。

Problem Resolved - The zigzag line will become smooth according to the curve. 问题已解决 - 根据曲线,曲折线将变得平滑。

Code to connect all the nearest neighbour: 用于连接所有最近邻居的代码:

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)

Code to smooth the nearest neighbour points: 平滑最近邻点的代码:

# 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

This is the final image- Smooth Image 这是最终图像 - 平滑图像

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM