Rilevamento e correzione di valori anomali in una traiettoria GPS


9

Ho bisogno di trovare un algoritmo o un metodo in grado di rilevare i latitude longitude punti anomali in una traiettoria durante la post-elaborazione , che può quindi essere risolto (riportato nel percorso della traiettoria in base ai suoi vicini).

Come esempio del tipo di punti anomali che vorrei rilevare e correggere, ho allegato un'immagine che dimostra:

Dati grezzi in blu.

Ho provato a usare un filtro Kalman inodore per appianare i dati nel miglior modo possibile, ma questo non sembra funzionare abbastanza efficacemente per valori anomali più estremi (dati grezzi in blu, dati levigati in rosso):

Dati non elaborati in blu, dati uniformi di UKF in rosso.

Il mio UKF potrebbe non essere calibrato correttamente (ma sono abbastanza sicuro che lo sia).

Le traiettorie sono quelle di deambulatori, corridori, ciclisti: movimento a propulsione umana che può iniziare e fermarsi, ma non cambiare drasticamente la velocità o la posizione in modo rapido o improvviso.

Una soluzione che non si basa su dati di temporizzazione (e solo su dati di posizione) sarebbe estremamente utile (poiché i dati elaborati potrebbero non contenere sempre dati di temporizzazione). Tuttavia, sono consapevole di quanto improbabile esista questo tipo di soluzione, quindi sono altrettanto felice di avere qualsiasi soluzione!

Idealmente, la soluzione rileverà il valore anomalo in modo da poterlo correggere, risultando in una traiettoria corretta:

Dati grezzi corretti in verde.


Risorse che ho setacciato:

Risposte:


1

Come parte di uno strumento per l'elaborazione delle reti fluviali, ho creato uno strumento di controllo della qualità per cercare "picchi" nella rete. Mentre non sto suggerendo di usare il mio strumento (come è per l'elaborazione delle reti fluviali), vi rimando al file Help che mostra un'immagine di ciò che avevo fatto.

Avevo sviluppato il codice usando la legge dei coseni per identificare gli angoli successivi tra ogni segmento di linea di una polilinea. Potresti sviluppare il tuo codice attorno a questa idea per fare un passo lungo una polilinea e identificare angoli estremi.


Ho usato un metodo come hai descritto (usando la legge dei coseni) e includendo le distanze tra i punti per determinare meglio i valori anomali, e sembra funzionare molto bene. Grazie!
JP

8

Algoritmo che uso.

  1. Calcola l'albero dei punti minimo euclideo:

inserisci qui la descrizione dell'immagine

  1. Trova 2 punti più distanti tra loro su questa rete

inserisci qui la descrizione dell'immagine

  1. Trova il percorso più breve tra loro:

inserisci qui la descrizione dell'immagine

Come si può vedere, si potrebbe tagliare l'angolo in una curva a gomito.

Ho l'implementazione di ArcGIS python dell'algoritmo sopra, usa il modulo networkx. Fammi sapere se questo è interessante e aggiornerò la mia risposta con lo script

AGGIORNARE:

# 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()            

Hmmm approccio interessante .. grazie per averlo condiviso! un esempio funzionante sarebbe valutato sono sicuro!
nickves

1
Una sorta di confronto a tratti tra il risultato di questo approccio e ciò che otterresti semplicemente seguendo i dati di input potrebbe consentire di impostare una soglia che eliminerebbe i "picchi" ma mantenga comunque gli angoli. Ciò potrebbe essere particolarmente utile se si dispone anche di informazioni temporali associate a ciascun punto, che derivano naturalmente da alcuni registri.
Doug McClean,

1
Giusto. È facile modificare lo script non creando collegamenti tra nodi distanti tra loro in intervalli di tempo. Sto usando lo script per altre cose, non i percorsi GPS. Esistono anche altri modi per migliorare, ad esempio la triangolazione, che ridurrà enormemente il numero di collegamenti nel grafico
FelixIP

2
Questo metodo funziona in alcuni casi, tuttavia le forme di alcune traiettorie indicano che l'utilizzo di questo metodo non è fattibile nel mio caso d'uso. (I problemi si verificano quando, ad esempio, una traiettoria raddoppia su se stessa, poiché molti nodi vengono ignorati e zig-zag. Allo stesso modo, intere sezioni di una traiettoria possono essere ignorate se l'entrata / uscita di quella sezione sono abbastanza vicine tra loro).
JP

1
@JP per i percorsi che vanno indietro potrebbe aiutare a densificare la linea grezza 1 °
FelixIP

4

Un'idea è quella di creare uno script che elenca gli angoli (e forse anche la lunghezza) di ogni segmento del tuo percorso. Ora puoi confrontare i valori di ogni segmento con i suoi vicini diretti (e possibilmente anche i secondi vicini per aumentare la precisione) e selezionare tutti quei punti in cui i valori superano un dato valore di soglia. Infine, elimina semplicemente i punti dal tuo percorso.


Ho usato un metodo simile descritto da @Hornbydd che realizza questo usando la legge dei coseni per determinare gli angoli, incorporando anche la distanza tra i punti. Grazie per il suggerimento
JP

2

Vale anche la pena guardare il metodo Median-5.

Ciascuna coordinata x (o y) è impostata sulla mediana dei 5 valori x (o y) attorno ad essa in sequenza (cioè se stessa, i due valori precedenti e i due valori successivi).

ad es. x3 = mediana (x1, x2, x3, x4, x5) y3 = mediana (y1, y2, y3, y4, y5) ecc.

Il metodo è rapido ed è anche facile da usare sui dati di streaming.



0

È possibile importare i dati in Excel o utilizzare i panda e la bandiera e / o eliminare tutte le distanze dal punto precedente che superano una soglia di distanza non realistica.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.