检测并修复GPS轨迹中的异常值


9

我需要找到一种算法或方法,该算法或方法可以 latitude longitude 在后处理过程中检测出轨迹中的异常点,然后可以对其进行修复(根据其邻居将其重新带入轨迹的路径中)。

作为我要检测和修复的异常点的示例,我附加了一个图像,该图像演示:

原始数据以蓝色显示。

我尝试使用无味的Kalman过滤器尽可能地平滑数据,但是对于更极端的异常值(原始数据为蓝色,平滑数据为红色)来说,这似乎还不够有效:

蓝色的原始数据,UKF的红色平滑数据。

我的UKF可能未正确校准(但我相当确定是正确的)。

轨迹是步行者,跑步者,骑自行车者的轨迹-可以启动和停止,但不会迅速或突然急剧改变速度或位置的人力运动。

不依赖时序数据(仅依赖位置数据)的解决方案将非常有用(因为正在处理的数据可能并不总是包含时序数据)。但是,我知道这种解决方案不太可能存在,因此,我同样很高兴拥有任何解决方案!

理想情况下,解决方案将检测异常值,以便将其固定,从而得到正确的轨迹:

校正后的原始数据为绿色。


我筛选的资源:

Answers:


1

作为处理河流网络的工具的一部分,我创建了一个质量控制工具来搜索网络中的“峰值”。虽然我不建议您使用我的工具(因为它用于处理河网),但我还是指向帮助文件,该文件显示了我所做的工作。

我已经围绕余弦定律开发了代码以识别折线的每个线段之间的连续角度。您可以围绕这个想法开发自己的代码,以逐步走线并确定极限角度。


我使用了一种像您描述的方法(使用余弦定律),并包括了点之间的距离,以便更好地确定离群值,并且它似乎工作得很好。谢谢!
JP

8

我使用的算法。

  1. 计算欧几里得最小最小生成树:

在此处输入图片说明

  1. 在此网络上找到彼此相距最远的2点

在此处输入图片说明

  1. 查找它们之间的最短路线:

在此处输入图片说明

可以看到,它可能在急转弯处转弯。

我有以上算法的ArcGIS python实现,它使用networkx模块。让我知道这是否有趣,我将使用脚本更新答案

更新:

# Connects points to make polyline. Makes 1 line at a time
# Tool assumes that 1st layer in Table of Conternt is TARGET polyline feature class,
# second layer in TOC is SOURCE point fc.
# If no selection found in SOURCE layer, works on entire dataset

import arcpy, traceback, os, sys
import itertools as itt
from math import sqrt
sys.path.append(r'C:\Users\felix_pertziger\AppData\Roaming\Python\Python27\site-packages')
import networkx as nx
from networkx import dijkstra_path_length

try:
    def showPyMessage():
        arcpy.AddMessage(str(time.ctime()) + " - " + message)
    def CheckLayerLine(infc):
        d=arcpy.Describe(infc)
        theType=d.shapeType
        if theType!="Polyline":
            arcpy.AddWarning("\nTool designed to work with polylines as TARGET!")
            raise NameError, "Wrong input\n"
        return d
    def CheckLayerPoint(infc):
        d=arcpy.Describe(infc)
        theType=d.shapeType
        if theType!="Point":
            arcpy.AddWarning("\nTool designed to work with points as SOURCE!")
            raise NameError, "Wrong input\n"
        return d
    mxd = arcpy.mapping.MapDocument("CURRENT")
    layers = arcpy.mapping.ListLayers(mxd)
    if len(layers)<=1:
        arcpy.AddWarning("\nNot enough layers in the view!")
        raise NameError, "Wrong input\n"
    destLR, sourceLR=layers[0],layers[1]
    a = CheckLayerPoint(sourceLR);d = CheckLayerLine(destLR)

#  copy all points to manageable list
    g=arcpy.Geometry()
    geometryList=arcpy.CopyFeatures_management(sourceLR,g)
    nPoints=len(geometryList)
    arcpy.AddMessage('Computing minimum spanning tree')
    list2connect=[p.firstPoint for p in geometryList]
#  create network    
    p=list(itt.combinations(range(nPoints), 2))
    arcpy.SetProgressor("step", "", 0, len(p),1)
    G=nx.Graph()
    for f,t in p:
        p1=list2connect[f]
        p2=list2connect[t]
        dX=p2.X-p1.X;dY=p2.Y-p1.Y
        lenV=sqrt(dX*dX+dY*dY)
        G.add_edge(f,t,weight=lenV)
        arcpy.SetProgressorPosition()
    arcpy.AddMessage(len(G.edges()))
    mst=nx.minimum_spanning_tree(G)
    del G

#  find remotest pair
    arcpy.AddMessage(len(mst.edges()))
    length0=nx.all_pairs_dijkstra_path_length(mst)
    lMax=0
    for f,t in p:
        lCur=length0[f][t]
        if lCur>lMax:
            lMax=lCur
            best=(f,t)
    gL=nx.dijkstra_path(mst,best[0],best[1])
    del mst
    nPoints=len(gL)
    ordArray=arcpy.Array()
    for i in gL: ordArray.add(list2connect[i])

#  append line to TARGET
    curT = arcpy.da.InsertCursor(destLR,"SHAPE@")
    curT.insertRow((arcpy.Polyline(ordArray),))
    arcpy.RefreshActiveView()
    del curT

except:
    message = "\n*** PYTHON ERRORS *** "; showPyMessage()
    message = "Python Traceback Info: " + traceback.format_tb(sys.exc_info()[2])[0]; showPyMessage()
    message = "Python Error Info: " +  str(sys.exc_type)+ ": " + str(sys.exc_value) + "\n"; showPyMessage()            

嗯,有趣的方法..谢谢分享!我敢肯定一个有效的例子!
尼克

1
在此方法的结果与仅跟踪输入数据所得到的结果之间进行某种分段的比较,可能会允许您设置一个阈值,该阈值可以消除“峰值”,但仍会保留弯道。如果您还具有与每个点关联的时间信息(这自然来自某些日志),这可能特别有用。
Doug McClean 2015年

1
很公平。通过不在彼此相隔n个时间间隔的节点之间创建链接,可以轻松修改脚本。我将脚本用于其他事情,而不是GPS路径。还有其他改进方法,例如三角剖分,它将大大减少图中的链接数量
FelixIP 2015年

2
该方法在某些情况下可行,但是某些轨迹的形状意味着在我的用例中使用此方法不可行。(例如,由于许多节点被忽略并且它呈锯齿形,因此轨迹自身再次加倍时会出现问题。类似地,如果轨迹的整个入口/出口靠得足够近,则可以忽略轨迹的整个部分)。
JP

1
@JP用于后退的路径可能有助于使第一行原始线致密
FelixIP 2015年

4

一种想法是创建一个脚本,该脚本列出路径的每个段的角度(也许还有长度)。现在,您可以将每个线段的值与其直接相邻的值(可能还有第二个相邻的值也可以提高准确性)进行比较,并选择所有值超过给定阈值的点。最后,只需删除路径中的点即可。


我使用了@Hornbydd描述的类似方法,该方法使用余弦定律确定角度,该方法还包含了点之间的距离。感谢您的建议。
JP

2

同样值得一提的是Median-5方法。

每个x(或y)坐标被依次设置为围绕它的5个x(或y)值的中值(即本身,两个先前值和两个后续值)。

例如x3 =中位数(x1,x2,x3,x4,x5)y3 =中位数(y1,y2,y3,y4,y5)等

该方法快速,并且易于在流数据上使用。



0

您可以将数据导入excel或使用pandas和flag和/或删除到上一个点的所有距离,这些距离超过了一些不切实际的距离阈值。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.