2013-01-15 11 views
12

Supponiamo di disporre di un insieme di coordinate x, y che contrassegnano i punti lungo il contorno. C'è un modo in cui posso costruire una rappresentazione spline del contorno che posso valutare in una posizione particolare lungo la sua lunghezza e recuperare le coordinate x, y interpolate?Rappresentazione spline uniforme di un contorno arbitrario, f (lunghezza) -> x, y

Spesso non è presente una corrispondenza 1: 1 tra i valori X e Y, quindi le spline univariate non mi sono utili. Le spline bivariate andrebbero bene, ma per quanto posso dire tutte le funzioni per la valutazione delle spline bivariate in scipy.interpolate prendono i valori x, y e restituiscono z, mentre ho bisogno di dare z e restituire x, y (poiché x, y sono punti su una linea, ogni z si associa ad un unico x, y).

Ecco un abbozzo di quello che mi piacerebbe essere in grado di fare:

import numpy as np 
from matplotlib.pyplot import plot 

# x,y coordinates of contour points, not monotonically increasing 
x = np.array([ 2., 1., 1., 2., 2., 4., 4., 3.]) 
y = np.array([ 1., 2., 3., 4., 2., 3., 2., 1.]) 

# f: X --> Y might not be a 1:1 correspondence 
plot(x,y,'-o') 

# get the cumulative distance along the contour 
dist = [0] 
for ii in xrange(x.size-1): 
    dist.append(np.sqrt((x[ii+1]-x[ii])**2 + (y[ii+1]-y[ii])**2)) 
d = np.array(dist) 

# build a spline representation of the contour 
spl = ContourSpline(x,y,d) 

# resample it at smaller distance intervals 
interp_d = np.linspace(d[0],d[-1],1000) 
interp_x,interp_y = spl(interp_d) 
+0

Non capisco come il vostro '' x' e gli array y' non può avere un 1: 1 corrispondenza e ancora definire i punti su una curva ... Potresti provare a spiegare quello che hai in mente con un esempio? – Jaime

+0

prova a tracciare le mie coordinate di esempio - in questo caso la linea curva su se stessa, quindi non ci può essere una mappatura univoca da X -> Y o da Y -> X –

risposta

22

si desidera utilizzare una spline parametrico, dove invece di interpolazione y dai valori x, si configura un nuovo parametro , t e interpola sia e x dai valori di t, utilizzando spline univariate per entrambi. Come si assegnano t valori per ogni punto influenza il risultato, e l'utilizzo di distanza, come la tua domanda suggerisce, potrebbe essere una buona idea:

from __future__ import division 
import numpy as np 
import matplotlib.pyplot as plt 
import scipy.interpolate 

x = np.array([ 2., 1., 1., 2., 2., 4., 4., 3.]) 
y = np.array([ 1., 2., 3., 4., 2., 3., 2., 1.]) 
plt.plot(x,y, label='poly') 

t = np.arange(x.shape[0], dtype=float) 
t /= t[-1] 
nt = np.linspace(0, 1, 100) 
x1 = scipy.interpolate.spline(t, x, nt) 
y1 = scipy.interpolate.spline(t, y, nt) 
plt.plot(x1, y1, label='range_spline') 

t = np.zeros(x.shape) 
t[1:] = np.sqrt((x[1:] - x[:-1])**2 + (y[1:] - y[:-1])**2) 
t = np.cumsum(t) 
t /= t[-1] 
x2 = scipy.interpolate.spline(t, x, nt) 
y2 = scipy.interpolate.spline(t, y, nt) 
plt.plot(x2, y2, label='dist_spline') 

plt.legend(loc='best') 
plt.show() 

enter image description here

+1

ZOMG così facile in Python, ho dovuto scrivere il mio Implementazione Catmull-Rom in Ruby ...:/roba buona – aledalgrande

+0

@Jaime Questa è una tecnica molto interessante, grazie! Quali potrebbero essere altri valori ragionevoli per t, oltre a dist_spline? Dove posso leggere di più? Per qualche motivo il metodo spline non è documentato in scipy: http://docs.scipy.org/doc/scipy-0.16.1/reference/interpolate.html – baltazar

+1

@ baltazar Si potrebbe fare qualche lettura su [equazioni parametriche] (https: //en.wikipedia.org/wiki/Parametric_equation) delle curve. Nel contesto della geometria differenziale delle curve, la parametrizzazione per la lunghezza della curva, che è simile alla distanza, ha alcune proprietà speciali che portano ad essere chiamata la [parametrizzazione naturale] (https://en.wikipedia.org/ wiki/Differential_geometry_of_curves # Length_and_natural_parametrization). Un'altra opzione ovvia per un parametro sarebbe l'angolo attorno a un punto centrale, se il set di dati ha la geometria giusta. – Jaime

1

Ecco un esempio utilizzando splprep e splev:

import numpy as np 
import scipy.interpolate 
from matplotlib.pyplot import plot 

# x,y coordinates of contour points, not monotonically increasing 
x = np.array([2., 1., 1., 2., 2., 4., 4., 3.]) 
y = np.array([1., 2., 3., 4., 2., 3., 2., 1.]) 

# f: X --> Y might not be a 1:1 correspondence 
plot(x, y, '-o') 

# get the cumulative distance along the contour 
dist = np.sqrt((x[:-1] - x[1:])**2 + (y[:-1] - y[1:])**2) 
dist_along = np.concatenate(([0], dist.cumsum())) 

# build a spline representation of the contour 
spline, u = scipy.interpolate.splprep([x, y], u=dist_along, s=0) 

# resample it at smaller distance intervals 
interp_d = np.linspace(dist_along[0], dist_along[-1], 50) 
interp_x, interp_y = scipy.interpolate.splev(interp_d, spline) 
plot(interp_x, interp_y, '-o') 

Parametric spline example