Wykrywanie i ustalanie wartości odstających na trajektorii GPS

9

Muszę znaleźć algorytm lub metodę, która może wykryć latitude longitude punkty odstające na trajektorii podczas przetwarzania końcowego , które można następnie naprawić (przywrócić na ścieżkę trajektorii na podstawie jej sąsiadów).

Jako przykład rodzaju punktów odstających, które chciałbym wykryć i naprawić, załączam obraz przedstawiający:

Surowe dane w kolorze niebieskim.

Próbowałem użyć bezzapachowego filtra Kalmana, aby jak najlepiej wygładzić dane, ale wydaje się, że nie działa to wystarczająco skutecznie dla bardziej ekstremalnych wartości odstających (surowe dane w kolorze niebieskim, wygładzone dane w kolorze czerwonym):

Surowe dane w kolorze niebieskim, dane wygładzone przez UKF na czerwono.

Mój UKF może nie zostać poprawnie skalibrowany (ale jestem całkiem pewien, że tak jest).

Są to trajektorie pieszych, biegaczy, rowerzystów - ruch napędzany przez człowieka, który może rozpoczynać i zatrzymywać, ale nie może drastycznie zmieniać prędkości ani pozycji tak szybko lub nagle.

Rozwiązanie, które nie opiera się na danych o taktowaniu (i tylko na danych o pozycji) byłoby niezwykle przydatne (ponieważ przetwarzane dane nie zawsze mogą zawierać dane o taktowaniu). Jestem jednak świadomy tego, jak mało prawdopodobne jest istnienie tego rodzaju rozwiązania, dlatego równie chętnie mam jakiekolwiek rozwiązanie!

Idealnie byłoby, gdyby rozwiązanie wykryło wartość odstającą, aby można ją było naprawić, co skutkowałoby poprawioną trajektorią:

Poprawione surowe dane na zielono.


Zasoby, które przeszukałem:

JP
źródło

Odpowiedzi:

1

W ramach narzędzia do przetwarzania sieci rzek stworzyłem narzędzie kontroli jakości do wyszukiwania „szczytów” w sieci. Chociaż nie sugeruję, abyś używał mojego narzędzia (podobnie jak do przetwarzania sieci rzek), wskazuję plik Pomocy, który pokazuje obraz tego, co zrobiłem.

Opracowałem kod przy użyciu prawa cosinusów do identyfikowania kolejnych kątów między każdym segmentem linii polilinii. Możesz opracować własny kod wokół tego pomysłu, aby przejść wzdłuż polilinii i zidentyfikować skrajne kąty.

Hornbydd
źródło
Użyłem metody opisanej przez ciebie (stosując prawo cosinusów) i uwzględniając odległości między punktami, aby lepiej określić wartości odstające, i wydaje się, że działa ona bardzo dobrze. Dziękuję Ci!
JP
8

Algorytm, którego używam.

  1. Oblicz euklidesowe minimalne drzewo rozpinające punktów:

wprowadź opis zdjęcia tutaj

  1. Znajdź 2 punkty najbardziej oddalone od siebie w tej sieci

wprowadź opis zdjęcia tutaj

  1. Znajdź najkrótszą trasę między nimi:

wprowadź opis zdjęcia tutaj

Jak widać, ostro skręca.

Mam implementację powyższego algorytmu w Pythonie ArcGIS, wykorzystuje on moduł networkx. Daj mi znać, jeśli jest to interesujące, a ja zaktualizuję swoją odpowiedź za pomocą skryptu

AKTUALIZACJA:

# 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()            
FelixIP
źródło
Hmmm ciekawe podejście .. dzięki za udostępnienie tego! przykład roboczy byłby cenny Jestem pewien!
nickves
1
Pewne cząstkowe porównanie wyniku tego podejścia z tym, co uzyskasz, postępując zgodnie z danymi wejściowymi, może pozwolić ci ustawić próg, który pozbyłby się „skoków”, ale nadal zachowałby narożniki. Może to być szczególnie przydatne, jeśli masz również informacje o czasie związane z każdym punktem, które naturalnie pochodzą z niektórych dzienników.
Doug McClean,
1
Słusznie. Łatwo jest modyfikować skrypt, nie tworząc połączeń między węzłami, które są n odstępami czasu od siebie. Używam skryptu do innych rzeczy, a nie ścieżek GPS. Istnieją również inne sposoby poprawy, np. Triangulacja, która znacznie zmniejszy liczbę linków na wykresie
FelixIP
2
Ta metoda działa w niektórych przypadkach, jednak kształty niektórych trajektorii oznaczają, że użycie tej metody nie jest możliwe w moim przypadku użycia. (Problemy występują, gdy na przykład trajektoria podwaja się sama, ponieważ wiele węzłów jest ignorowanych i zygzakuje. Podobnie całe sekcje trajektorii można zignorować, jeśli wejście / wyjście z tej sekcji jest wystarczająco blisko siebie).
JP
1
@JP dla ścieżek prowadzących do tyłu może pomóc zagęścić surową linię 1.
FelixIP
4

Jednym z pomysłów jest stworzenie skryptu, który wyszczególnia kąty (i być może także długość) każdego segmentu ścieżki. Teraz możesz porównać wartości każdego segmentu z jego bezpośrednimi sąsiadami (i być może także drugimi sąsiadami, aby zwiększyć dokładność) i wybrać wszystkie te punkty, w których wartości przekraczają daną wartość progową. Na koniec po prostu usuń punkty ze swojej ścieżki.

HimBromBeere
źródło
Użyłem podobnej metody opisanej przez @ Horbydda, która osiąga to, stosując prawo cosinusów do określania kątów, a także uwzględniając odległość między punktami. Dziękuję za sugestię.
JP
2

Warto również przyjrzeć się metodzie Median-5.

Każda współrzędna x (lub y) jest ustawiona na medianę wokół 5 wartości x (lub y) wokół niej w sekwencji (tj. Sama, dwie poprzednie wartości i dwie kolejne wartości).

np. x3 = mediana (x1, x2, x3, x4, x5) y3 = mediana (y1, y2, y3, y4, y5) itd.

Metoda jest szybka i łatwa w użyciu w przypadku przesyłania strumieniowego danych.

Dudnienie
źródło
0

Możesz zaimportować dane do programu Excel lub użyć pand i flag i / lub usunąć wszystkie odległości z poprzedniego punktu, które przekraczają jakiś nierealistyczny próg odległości.

risail
źródło