Math 如何平滑手绘线条?

Math 如何平滑手绘线条?,math,lines,smoothing,Math,Lines,Smoothing,因此,我使用统一的Kinect 使用Kinect,我们可以检测到手势,当它处于活动状态时,我们会在屏幕上画一条线,跟随手的移动方向。位置的每次更新都存储为一行中的最新(也是最后一个)点。然而,这些线条通常看起来很起伏 以下是我想要实现的总体情况: 红色是原始线条,紫色是新的平滑线条。如果用户突然停止并转向,我们认为我们不希望它完全这样做,而是希望它快速转向或循环 我当前的解决方案是使用,并且只使用彼此相距X距离的点(使用立方贝塞尔将Y点放置在两个点之间)。然而,除其他问题外,还有两个问题: 1

因此,我使用统一的Kinect

使用Kinect,我们可以检测到手势,当它处于活动状态时,我们会在屏幕上画一条线,跟随手的移动方向。位置的每次更新都存储为一行中的最新(也是最后一个)点。然而,这些线条通常看起来很起伏

以下是我想要实现的总体情况:

红色是原始线条,紫色是新的平滑线条。如果用户突然停止并转向,我们认为我们不希望它完全这样做,而是希望它快速转向或循环

我当前的解决方案是使用,并且只使用彼此相距X距离的点(使用立方贝塞尔将Y点放置在两个点之间)。然而,除其他问题外,还有两个问题:

1) 它通常不会将曲线保留到用户绘制曲线时向外的距离,例如,如果用户突然停止一条直线并反转方向,则该直线很有可能不会延伸到用户反转方向的点

2) 也有可能选择的“好”点实际上是一个“坏”随机跳转点

所以我考虑了其他的解决方案。一个包括限制点之间的最大角度(0度为直线)。但是,如果该点的角度超出了限制,则在尽可能沿着绘制的线降低角度的数学过程似乎很复杂。但也许不是。不管怎样,我都不知道该怎么办,也不知道该寻求什么帮助


请记住,这需要在用户绘制直线时实时完成。

您可以尝试Ramer-Douglas-Peucker算法来简化曲线:

这是一个简单的算法,参数化相当直观。您可以将其用作预处理步骤,也可以在一个或多个其他算法之后使用。在任何情况下,它都是一个很好的算法

如您所见,使用角度来拒绝“跳跃”点可能很棘手。一种选择是将N条线段的总长度与该N条线段链的端点之间的直线距离进行比较。您可以设定(总长度/直线长度)比率的阈值,以标识要拒绝的线段。这将是一个快速的计算,很容易理解

如果要考虑线段长度和线段到线段的角度,可以将线段视为向量并计算叉积。如果你把这两个向量想象成一个平行四边形,如果知道平行四边形的面积是一个接受/拒绝一个点的方法,那么叉积是另一个简单而快速的计算

如果只有几十个点,可以一次随机消除一个点,生成样条曲线拟合,然后计算所有原始点的点到样条曲线距离。给定所有这些点到样条线的距离,您可以生成一个您希望最小化的度量(例如,平均距离):最佳拟合将通过消除点(Pn、Pn+k…)而产生,从而产生样条线拟合质量S。这种技术不能很好地与更多点进行缩放,但是,如果你把每条线段链分成一组,每组大概有六条线段,可能值得一试

虽然这对于这个问题来说有些过分,但我要提到的是,Euler曲线可以很好地拟合“自然”曲线。Euler曲线的优点在于,可以通过空间中的两点和空间中这两点的切线生成Euler曲线拟合。代码很复杂,但Euler曲线(也称美学曲线,如果我没记错的话)可以生成比Bezier N次样条更好和/或更有用的自然曲线拟合


我想你真正想要的是某种最小二乘拟合。设置三次样条曲线,然后拟合其控制点,以使到曲线的总平方距离最小化。请参见