如何连接曲线的两部分并获得连接曲线的点位置?

时间:2016-01-20 08:21:07

标签: c++ opencv curve-fitting bezier

我有曲线的两个部分。曲线的点位置(x,y)是已知的。如何连接它们并获得连接曲线的位置?这是一个类似的问题。similar question 他说要使用Bezier曲线。但在我看来,通常,拟合曲线不会通过控制点。因此,如果我从曲线的两个部分中选择一些点作为控制点,则拟合结果可以如下图所示。那不是我的目标。有人可以给我一些建议吗?

enter image description here

enter image description here

3 个答案:

答案 0 :(得分:3)

使用Catmull-Rom曲线,该曲线与Bezier曲线相关并且易于转换为Bezier形式,其优点是“通过”点,而不仅仅是由它们控制。有关详细信息,请参阅http://pomax.github.io/bezierinfo/#catmullconv,但我们基本上需要这两个端点,以及曲线外部的两个点,以确保我们在两个曲线点上具有正确的切线:

enter image description here

p2和p3是“你的”点,而p1和p4有些随意:我们只需要确保线SparkConf与p2处的切线平行(切线及其平行线以蓝色表示)紫色),类似地,线p1--p3平行于p3处的切线(切线,其平行线以粉红色表示)。通常简单的方法是project points p2 and p3 onto the parallel lines

只要我们确保这是真的,我们就可以将连接段形成为具有曲线坐标(p1,p2,p3,p4)的Catmull-Rom段。但是,如果没有Catmull-Rom绘图基元,我们可以通过使用以下三次贝塞尔曲线坐标将其简单地绘制为贝塞尔曲线:

  1. 起点:p2
  2. 控制点1:p2 +(p3-p1)/(6 * t)
  3. 控制点2:p3 - (p4-p2)/(6 * t)
  4. 终点:p3
  5. 这里的p2--p4值是Catmull-Rom曲线的张力;你做得越高,连接看起来越“紧密”(大多数图形上下文中支持Catmull-Rom的默认张力只是1)。

    一些示例值:

    enter image description here

    请注意,在每个示例中,保留了点p2和p3处的切线方向,但是切线矢量的长度是不同的,从而导致非常紧密,很好,太松散的配件。

答案 1 :(得分:0)

正如我所评论的,在这种情况下,Spline可能是比Bezier更好的解决方案。但是,您也可以使用更简单的一个。你有4分(红色)。尝试使用以下公式将它们放入多项式(第3度,因为你只有4):

A x^3 + B x^2 + C x + D = y

你有4点(P0,P1,P2,P3):

A x0^3 + B x0^2 + C x0 + D = y0
A x1^3 + B x1^2 + C x1 + D = y1
A x2^3 + B x2^2 + C x2 + D = y2
A x3^3 + B x3^2 + C x3 + D = y3

求解这个线性方程组将给出A,B,C,D的值。

获取缺少的曲线部分:

for(auto x=P1.x; x<P2.x; ++x){
    auto y=A*x*x*x + B*x*x + C*x + D;
    cv::circle(image,cv::Point(x,y),.......);
}

答案 2 :(得分:0)

不排除Bezier曲线。你是正确的,曲线通常不与控制点相交,但是端点会这样做,你可以用它来约束曲线的形式。

更具体地说,您可以通过构造新的二次贝塞尔曲线来连接线 - 使用两条线的端点作为曲线的端点,中点是从两条线延伸的两条假想直线段的交点。当前行的结尾。

Bezier

在上面的例子中,红色圆圈是曲线的固定端点,绿色线是延长线,蓝色圆圈是它们的交点(用作控制点),蓝色线是近似曲线你最终会得到。

编辑:在考虑了这一点之后,您可能想要使用三次曲线,并且有两个蓝色控制点,每个绿线一个。将每个 L / 2 距离端点定位,其中 L 是红色端点之间的直线距离,可能会产生良好的结果。二次曲线的问题在于,当绿线接近平行时,二次曲线将在控制点附近形成一个尖角。平行时,它们实际上根本不相交。使用三次曲线将产生更圆的线,并且对平行切线没有任何问题。例如,在下图中,顶部曲线使用二次(一个控制点),底部曲线使用三次(两个控制点)。

Bezier2