2010-07-21 14 views
8

Tengo un vector de muestras que forman una curva. Imaginemos que hay 1000 puntos en él. Si quiero estirarlo para llenar 1500 puntos, ¿cuál es el algoritmo más simple que da resultados decentes? Estoy buscando algo que sea solo unas líneas de C/C++.Extender una matriz

Siempre querré aumentar el tamaño del vector, y el nuevo vector puede estar entre 1.1x y 50x del tamaño del vector actual.

Gracias!

+0

Hola ... ¿cómo se quiere rellenar los datos nuevos datos suavizados Es posible que necesite para programar un?? spline (y puede ser un esfuerzo bastante largo). ¡Muy buena pregunta, por cierto! – Barranka

+1

Realmente depende del modelo que los nuevos datos se desean seguir ... [Wikipedia: Interpolación] (http: // es .wikipedia.org/wiki/Interpolation) –

Respuesta

6

Aquí hay C++ para la interpolación lineal y cuadrática.
interp1(5.3, a, n) es un [5] + .3 * (a [6] - a [5]), .3 del camino de a [5] a a [6];
interp1array(a, 1000, b, 1500) se estiraría a a b.
interp2(5.3, a, n) dibuja una parábola a través de los 3 puntos más cercanos a [4] a [5] a [6]: más suave que interp1 pero aún más rápido.
(splines usan 4 puntos más próximos, sin embargo, más suave;. Si lee pitón, ver basic-spline-interpolation-in-a-few-lines-of-numpy

// linear, quadratic interpolation in arrays 
// from interpol.py denis 2010-07-23 July 

#include <stdio.h> 
#include <stdlib.h> 

    // linear interpolate x in an array 
// inline 
float interp1(float x, float a[], int n) 
{ 
    if(x <= 0) return a[0]; 
    if(x >= n - 1) return a[n-1]; 
    int j = int(x); 
    return a[j] + (x - j) * (a[j+1] - a[j]); 
} 

    // linear interpolate array a[] -> array b[] 
void inter1parray(float a[], int n, float b[], int m) 
{ 
    float step = float(n - 1)/(m - 1); 
    for(int j = 0; j < m; j ++){ 
     b[j] = interp1(j*step, a, n); 
    } 
} 

//.............................................................................. 
    // parabola through 3 points, -1 < x < 1 
float parabola(float x, float f_1, float f0, float f1) 
{ 
    if(x <= -1) return f_1; 
    if(x >= 1) return f1; 
    float l = f0 - x * (f_1 - f0); 
    float r = f0 + x * (f1 - f0); 
    return (l + r + x * (r - l))/2; 
} 

    // quadratic interpolate x in an array 
float interp2(float x, float a[], int n) 
{ 
    if(x <= .5 || x >= n - 1.5) 
     return interp1(x, a, n); 
    int j = int(x + .5); 
    float t = 2 * (x - j); // -1 .. 1 
    return parabola(t, (a[j-1] + a[j])/2, a[j], (a[j] + a[j+1])/2); 
} 

    // quadratic interpolate array a[] -> array b[] 
void interp2array(float a[], int n, float b[], int m) 
{ 
    float step = float(n - 1)/(m - 1); 
    for(int j = 0; j < m; j ++){ 
     b[j] = interp2(j*step, a, n); 
    } 
} 

int main(int argc, char* argv[]) 
{ 
     // a.out [n m] -- 
    int n = 10, m = 100; 
    int *ns[] = { &n, &m, 0 }, 
     **np = ns; 
    char* arg; 
    for(argv ++; (arg = *argv) && *np; argv ++, np ++) 
     **np = atoi(arg); 
    printf("n: %d m: %d\n", n, m); 

    float a[n], b[m]; 
    for(int j = 0; j < n; j ++){ 
     a[j] = j * j; 
    } 
    interp2array(a, n, b, m); // a[] -> b[] 

    for(int j = 0; j < m; j ++){ 
     printf("%.1f ", b[j]); 
    } 
    printf("\n"); 
} 
+0

No he probado completamente He aquí este código, por lo que no puedo garantizar su corrección, pero este es exactamente el tipo de respuesta que estaba buscando. ¡Gracias! – twk

+0

De nada. Si funciona, díselo al jefe; si no, dime – denis

2

¿Cuál es el algoritmo más simple que da resultados decentes?

Catmull-Rom splines. (Si desea una curva suave)

http://www.mvps.org/directx/articles/catmull/
http://en.wikipedia.org/wiki/Cubic_Hermite_spline

Para cada nuevo elemento de calcular la posición fraccional en matriz de edad, el uso de utilizar una parte fraccional (f - piso (f)) como factor de interpolación, y "número entero "(es decir, piso (f)) parte para encontrar los elementos más cercanos.

Eso supone que está operando en datos que se pueden interpolar matemáticamente (flotantes). Si los datos no se pueden interpolar (cadenas), entonces la única solución es usar el elemento disponible más cercano de la matriz anterior.

Necesitará algunos ajustes si los puntos en la matriz no se distribuyen uniformemente.

0

opción más simple que puedo pensar es sólo un fn que se expande la matriz basado en promedios intermedios, así:

x, y, z

convierte

x, avg (x, y), y, avg (y, z), z

Si necesita más puntos de datos, simplemente ejecútelo varias veces en el vector.

+0

.. Y si la nueva matriz no es 2 veces más grande que la anterior, los resultados serán incorrectos. No es mucho mejor que la interpolación lineal: no obtendrá una curva suave de esta manera – SigTerm