2010-07-21 66 views
8

我有一個形成曲線的樣本矢量。我們假設它有1000點。如果我想將其拉伸至1500點,那麼最簡單的算法能給出相當好的結果呢?我正在尋找只是C/C++幾行的東西。伸出陣列

我總是想要增加矢量的大小,新的矢量可以是當前矢量大小的1.1倍到50倍的任何地方。

謝謝!

+0

嗨,你好,你怎麼想,以填補新數據平滑後的數據可能需要編程?樣條曲線(可能會花費相當長的時間) 相當不錯的一個問題,順便說一句! – Barranka 2010-07-21 22:56:17

+1

這真的取決於新數據需要遵循的模型... [Wikipedia:Interpolation](http:// en .wikipedia.org/wiki/Interpolation) – 2010-07-21 22:59:04

回答

6

下面是用於線性和二次插值的C++。
interp1(5.3, a, n)是從[5]到[6]的方式[5] + .3 *(a [6] - a [5]),.3;
interp1array(a, 1000, b, 1500)將延伸ab
interp2(5.3, a, n)通過3個最近點a [4] a [5] a [6]繪製拋物線:比interp1更平滑但仍然很快。
(花鍵使用4個最近點,但更流暢;如果你看過蟒蛇,看 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

我還沒有徹底測試這個代碼,所以我不能保證它的正確性,但這正是我正在尋找的那種答案。謝謝! – twk 2010-07-25 16:08:13

+0

不客氣。如果有效,告訴老闆;如果沒有,告訴我 – denis 2010-07-26 13:15:14

2

什麼是最簡單的算法,可以給出體面的結果?

Catmull-Rom樣條曲線。 (如果你想有一個平滑的曲線)

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

對於每一個新項目計算舊陣列分數位置,使用用小數部分(F - 地板(F))爲內插因子,而「整「(即floor(f))部分來查找最近的元素。

這是假設您正在操作可以數學插值的數據(浮點數)。如果數據不能被內插(字符串),那麼唯一的解決方案是使用舊數組的最近可用元素。

如果數組中的點不均勻分佈,則需要進行一些調整。

我能想到的
0

簡單的辦法就是,基於均值的平均值擴展陣列中的新生力量,所以:

X,Y,Z

成爲

X,AVG(X,Y ),y,avg(y,z),z

如果您需要更多數據點,只需在矢量上多次運行它。

+0

..如果新陣列不是舊的2倍大,結果將是不正確的。它不比線性插值更好 - 你不會得到這樣的光滑曲線 – SigTerm 2010-07-21 23:18:55