平滑数组的值

rob*_*nnn 12 javascript arrays smoothing

如果我有一个数组,如[3,5,0,8,4,2,6],有没有办法"平滑"这些值,使它们彼此更接近,并显示更少的方差?

我已经研究了使用高斯函数对一个1维案例进行窗口化数据,这是我的数组,但是在实现它时遇到了麻烦.这个线程似乎正好解决了我的需要,但我不明白用户naschilling(第二篇文章)如何提出高斯矩阵值.

背景:我正在研究音乐波形发生器(借用SoundCloud的设计),它在时间t映射歌曲的振幅到相应的条形高度.不幸的是,有很多噪音,当程序映射出微小的振幅导致高度突然下降时,它看起来特别难看.我基本上想要平滑酒吧高度,所以他们不是那么多样化.

我正在使用的语言是Javascript.

编辑:对不起,让我更具体地说"平滑"值.根据上面链接的线程,用户采用了一个数组

[10.00, 13.00, 7.00, 11.00, 12.00, 9.00, 6.00, 5.00]
Run Code Online (Sandbox Code Playgroud)

并使用高斯函数将其映射到

[ 8.35,  9.35, 8.59,  8.98,  9.63, 7.94, 5.78, 7.32]
Run Code Online (Sandbox Code Playgroud)

注意这些数字是如何彼此更接近的.

编辑2:它工作了!感谢用户Awal Garg的算法,结果如下:

没有平滑 一些平滑 最大平滑度

编辑3:这是我在JS的最终代码.我调整它,以便数组的第一个和最后一个元素能够通过环绕数组来找到它的邻居,而不是调用它自己.

var array = [10, 13, 7, 11, 12, 9, 6, 5];

function smooth(values, alpha) {
    var weighted = average(values) * alpha;
    var smoothed = [];
    for (var i in values) {
        var curr = values[i];
        var prev = smoothed[i - 1] || values[values.length - 1];
        var next = curr || values[0];
        var improved = Number(this.average([weighted, prev, curr, next]).toFixed(2));
        smoothed.push(improved);
    }
    return smoothed;
}

function average(data) {
    var sum = data.reduce(function(sum, value) {
        return sum + value;
    }, 0);
    var avg = sum / data.length;
    return avg;
}

smooth(array, 0.85);
Run Code Online (Sandbox Code Playgroud)

use*_*110 7

有趣的问题!

平滑值的算法显然可能会有很大不同,但这是我的看法:

"use strict";
var array = [10, 13, 7, 11, 12, 9, 6, 5];

function avg (v) {
  return v.reduce((a,b) => a+b, 0)/v.length;
}

function smoothOut (vector, variance) {
  var t_avg = avg(vector)*variance;
  var ret = Array(vector.length);
  for (var i = 0; i < vector.length; i++) {
    (function () {
      var prev = i>0 ? ret[i-1] : vector[i];
      var next = i<vector.length ? vector[i] : vector[i-1];
      ret[i] = avg([t_avg, avg([prev, vector[i], next])]);
    })();
  }
  return ret;
}

function display (x, y) {
  console.clear();
  console.assert(x.length === y.length);
  x.forEach((el, i) => console.log(`${el}\t\t${y[i]}`));
}

display(array, smoothOut(array, 0.85));
Run Code Online (Sandbox Code Playgroud)

NOTE: It uses some ES6 features like fat-arrow functions and template strings. Firefox 35+ and Chrome 45+ should work fine. Please use the babel repl otherwise.

My method basically computes the average of all the elements in the array in advance, and uses that as a major factor to compute the new value along with the current element value, the one prior to it, and the one after it. I am also using the prior value as the one newly computed and not the one from the original array. Feel free to experiment and modify according to your needs. You can also pass in a "variance" parameter to control the difference between the elements. Lowering it will bring the elements much closer to each other since it decreases the value of the average.

稍微改变以放松平滑将是这样的:

"use strict";
var array = [10, 13, 7, 11, 12, 9, 6, 5];

function avg (v) {
  return v.reduce((a,b) => a+b, 0)/v.length;
}

function smoothOut (vector, variance) {
  var t_avg = avg(vector)*variance;
  var ret = Array(vector.length);
  for (var i = 0; i < vector.length; i++) {
    (function () {
      var prev = i>0 ? ret[i-1] : vector[i];
      var next = i<vector.length ? vector[i] : vector[i-1];
      ret[i] = avg([t_avg, prev, vector[i], next]);
    })();
  }
  return ret;
}

function display (x, y) {
  console.clear();
  console.assert(x.length === y.length);
  x.forEach((el, i) => console.log(`${el}\t\t${y[i]}`));
}

display(array, smoothOut(array, 0.85));
Run Code Online (Sandbox Code Playgroud)

它没有将平均值作为主要因素.

随意试验,希望有所帮助!


cop*_*peg 6

您描述的技术听起来像是高斯模糊的一维版本.将1D高斯数组的值乘以数组中给定窗口的时间并对结果求和.例如

  1. 假设高斯数组{.242,.399,.242}
  2. 计算输入数组位置n的新值 - 将输入数组的n-1,n和n + 1处的值乘以(1)中的值,并对结果求和.例如[3,5,7,8,4,2,6],n = 1:

    n1 = 0.242*3 + 0.399*5 + 0.242*0 = 2.721

您可以更改高斯的方差以增加或减少模糊的影响.

  • 它们是高斯​​函数的离散值,其(平均值0,sd = 1)为-1、0和1。 (2认同)