Language agnostic 如何从有噪声的X,Y数据确定路径

Language agnostic 如何从有噪声的X,Y数据确定路径,language-agnostic,math,geometry,2d,Language Agnostic,Math,Geometry,2d,我有一个未排序的噪音X,Y点列表。然而,它们确实形成了一条穿越世界的道路。我想要一个算法来画一个近似的数据使用线段 这类似于使用直线拟合算法拾取线性数据的近似值。我的问题更难,因为这条路绕着世界弯弯曲曲。 有人知道有什么标准的/健壮的/易于理解的算法来实现这一点吗 问答: 你所说的噪声是什么意思?如果我对路径有一个理想的实现,那么我的点集将从理想路径中采样,并将高斯噪声添加到X和Y元素中。我不知道噪音的平均值或标准偏差。我也许能猜到性病的发展 这些点是否靠近但不在您试图近似的理想但复杂的路径上

我有一个未排序的噪音X,Y点列表。然而,它们确实形成了一条穿越世界的道路。我想要一个算法来画一个近似的数据使用线段

这类似于使用直线拟合算法拾取线性数据的近似值。我的问题更难,因为这条路绕着世界弯弯曲曲。

有人知道有什么标准的/健壮的/易于理解的算法来实现这一点吗

问答

你所说的噪声是什么意思?如果我对路径有一个理想的实现,那么我的点集将从理想路径中采样,并将高斯噪声添加到X和Y元素中。我不知道噪音的平均值或标准偏差。我也许能猜到性病的发展

这些点是否靠近但不在您试图近似的理想但复杂的路径上?


你有关于路径形状的先验信息吗?是否有其他方法获取此类信息?不幸的是,没有。

如果您的点彼此靠近,您可以使用标准的“直线”(正交线)。使用普通的。你可以看到世界是平的

如果它们相距很远,则需要使用从一点到另一点的导航来补偿地球的圆度。否则你的直线会走得更远

如果点太远而无法创建直线,则由您选择

此外,您还必须知道是否需要“访问”每个点,或者只是需要走近,以及距离有多近

如果您需要将课程发送给飞机、轮船或其他旅行者,您可能需要访问每个点。如果你从一个物体上获取GPS数据,你可能只想在屏幕上绘制一条路线,并消除噪音


查看您的编辑后: 如果这是移动要打印的某个轨迹的对象,则可能需要平滑方向和速度,而不是x/y值。(使测量值(x)具有固定且不断增加的Y间隔可以使平滑更容易。)

可能适合您的问题

但是,这并不能解决路径中点的顺序问题;有许多方法需要考虑:

  • 任何“最优”路径类型(例如路径上每个点的最小方向变化,*通过所有点的最短路径)都可能归结为NP完全(TSP)
  • 一个“合理”的路径来对节点进行集群,然后在集群之间和集群内进行路由。当然,集群越大,或者集群数量越大,这个较小的问题看起来就越像一个大的n TSP
  • 按一个轴对点进行排序。如果有两个以上的轴,一些策略可能是有用的。e、 g.独立成分分析

对于未排序的列表,您无法真正知道每个段中包含哪些点,因此我想您可以选择最近的点

一种方法是随机选择一个起点,然后在每个步骤中选择最近的点作为下一个点。将前两点添加到集合S

将直线拟合到S中的点,直到RMS超过某个值,然后清除S并开始新的直线


连续直线的交点将是线段的端点。

这里有一个启发式方法,可以解决数据的排序问题,如果

  • 你有足够的分数
  • 与路径预期的最小曲率半径相比,点之间的平均距离较小
  • 与噪声的标准偏差相比,点之间的平均距离不大
  • 这条路不是自动穿越的(你可能会幸运,但没有保证)
这样做:

  • 选择一个起点,p1(希望是通过有意义的而不是随机的方式)
  • 找到位于某个聚类距离内的所有点,r\u cp1。选择r_c与预期转弯半径相比较小,但与散射半径相比较大
  • 将此群集称为C1
  • 查找点q1C1中位置的平均值
  • 将一条线拟合到C1中的点,并投影到簇的边缘(或刚好超出),然后在原始数据中找到最近的点。标记该点p2
  • 重复步骤2-5,直到数据用完
  • 现在,您有了一个新的点列表q1qn

    在我的头顶上,非常粗糙,只有在相当好的条件下才能工作



    通过在步骤(5)中要求新的投影线位于前一条投影线的某个最大角度内,可能可以改善自交行为。

    从您对问题的回答中,您似乎知道“黄金曲线”,我建议找到@jamesh建议的“黄金曲线”的贝塞尔曲线并绘制它。

    我的方法是首先对点列表排序,然后使用贝塞尔曲线

    诀窍当然是排序。从一个随机点开始,找到最近的点。假设这两个是连接的。使用这两个端点,找到离它们最近的点。假设到其端点的距离较小的一个连接到该点。重复此操作,直到所有点都已连接

    我假设这种方法仍然存在一些问题,但也许您可以将其作为一个起点(双关语)


    编辑:您可以使用不同的起点多次进行编辑,然后查看结果的差异。这至少给了你一些信心,这些点是相互联系的

    你得了多少分?
    如前所述,如果你有比较少的点,贝塞尔曲线是个好主意。如果你有很多观点,b
    #lang scheme
    
    (require (only-in srfi/1 iota))
    
    ; a bunch of trig
    (define (deg->rad d)
      (* pi (/ d 180)))
    
    (define (rad->deg r)
      (* 180 (/ r pi)))
    
    (define (euclidean-length v)
      (sqrt (apply + (map (lambda (x) (expt x 2)) v))))
    
    (define (dot a b)
      (apply + (map * a b)))
    
    (define (angle-ratio a b)
      (/ (dot a b)
         (* (euclidean-length a) (euclidean-length b))))
    
    ; given a list of 3 points, calculate the likelihood of the
    ; angle they represent. straight is better.
    (define (probability-triple a b c)
      (let ([av (map - a b)]
            [bv (map - c b)])
        (cos (/ (- pi (abs (acos (angle-ratio av bv)))) 2))))
    
    ; makes a random 2d point. uncomment the bit for a 3d point
    (define (random-point . x)
      (list (/ (random 1000) 100)
            (/ (random 1000) 100)
            #;(/ (random 1000) 100)))
    
    ; calculate the likelihood of an entire list of points
    (define (point-order-likelihood lst)
      (if (null? (cdddr lst))
          1
          (* (probability-triple (car lst)
                                 (cadr lst)
                                 (caddr lst))
             (point-order-likelihood (cdr lst)))))
    
    ; just print a list of points
    (define (print-points lst)
      (for ([p (in-list lst)])
        (printf "~a~n"
                (string-join (map number->string
                                  (map exact->inexact p))
                             " "))))
    
    ; attempts to improve upon a list
    (define (find-better-arrangement start
                                     ; by default, try only 10 times to find something better
                                     [tries 10]
                                     ; if we find an arrangement that is as good as one where
                                     ; every segment bends by 22.5 degrees (which would be
                                     ; reasonably gentle) then call it good enough. higher
                                     ; cut offs are more demanding.
                                     [cut-off (expt (cos (/ pi 8))
                                                    (- (length start) 2))])
      (let ([vec (list->vector start)]
            ; evaluate what we've started with
            [eval (point-order-likelihood start)])
        (let/ec done
          ; if the current list exceeds the cut off, we're done
          (when (> eval cut-off)
            (done start))
          ; otherwise, try no more than 'tries' times...
          (for ([x (in-range tries)])
            ; pick two random points in the list
            (let ([ai (random (vector-length vec))]
                  [bi (random (vector-length vec))])
              ; if they're the same...
              (when (= ai bi)
                ; increment the second by 1, wrapping around the list if necessary
                (set! bi (modulo (add1 bi) (vector-length vec))))
              ; take the values from the two positions...
              (let ([a  (vector-ref vec ai)]
                    [b  (vector-ref vec bi)])
                ; swap them
                (vector-set! vec bi a)
                (vector-set! vec ai b)
                ; make a list out of the vector
                (let ([new (vector->list vec)])
                  ; if it evaluates to better
                  (when (> (point-order-likelihood new) eval)
                    ; start over with it
                    (done (find-better-arrangement new tries cut-off)))))))
          ; we fell out the bottom of the search. just give back what we started with
          start)))
    
    ; evaluate, display, and improve a list of points, five times
    (define points (map random-point (iota 10)))
    (define tmp points)
    (printf "~a~n" (point-order-likelihood tmp))
    (print-points tmp)
    (set! tmp (find-better-arrangement tmp 10))
    (printf "~a~n" (point-order-likelihood tmp))
    (print-points tmp)
    (set! tmp (find-better-arrangement tmp 100))
    (printf "~a~n" (point-order-likelihood tmp))
    (print-points tmp)
    (set! tmp (find-better-arrangement tmp 1000))
    (printf "~a~n" (point-order-likelihood tmp))
    (print-points tmp)
    (set! tmp (find-better-arrangement tmp 10000))
    (printf "~a~n" (point-order-likelihood tmp))
    (print-points tmp)