在 Windows Phone 8.1 中使用加速度计传感器数据在画布上绘制线条

2024-01-21

我正在根据设备移动在画布上绘图,我想根据移动移动在画布上绘制不同的字符。

目前它正在工作,但我想找到时间差,并且我想检测暂停,暂停意味着用户没有尝试绘制并且用户没有移动手机,因此应用程序可以假设现在用户想要绘制下一个字符。

如何找到加速度计值的暂停。有逻辑吗?还告诉我如何平滑加速度计值,以便用户可以绘制没有噪音的线条。


我无法帮助加速器部分,但对于数据中的噪音,这是一种使用的方法加权移动平均线 https://en.wikipedia.org/wiki/Moving_average#Weighted_moving_average.

基础知识很简单:

  • 找出当前之前要使用多少个点进行平滑
  • 根据长度计算重量,f.ex。如果长度为 5,则重量 = 1+2+3+4+5 = 15
  • 从权重长度开始迭代每个数据点(您可以从 1 开始并缩短权重 - 下面我将演示后一种方法)
  • 对于电流点 - 5 乘以 1/15,对于电流点 - 4 乘以 2/15,依此类推。总和存储为该点的值,对下一个值点重复

现场演示

下面是一个演示(进入整页查看所有图形)。我用 JavaScript 编写了它,这样它就可以在答案中实时显示。我认为将其转换为您正在使用的语言(未说明)应该没什么问题。

移动滑块以增加权重点数。您可以通过多次传递来运行数据以更加平滑。原始数据是带有噪声抖动的正弦曲线。通过许多点,您可以看到曲线平滑以复制这一点。只需在 2 次传递中使用 9-10 点长度即可获得良好的结果,并且几乎没有时间延迟:

var ctx = document.querySelector("canvas").getContext("2d"),
    rng = document.querySelector("input"),
    val = document.querySelector("span"),
    data = [], scale = 30;

// generate sinus wave with noise jitters
for(var i = 0; i < ctx.canvas.width; i += 2)
    data.push(Math.sin(i*0.1) * Math.random() + Math.random())

// draw initial smoothed curve (length=1, no smoothing)
drawWMA();

// calculate moving average
function drawWMA() {
    var len = +rng.value,        // get smoothing length (number of previous points)
        dataa = [], datab = [],  // pass A and B arrays
        weight = 0;              // calc weight based on length
  
  val.innerHTML = len;
  
  ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
  ctx.beginPath();
  
  // calc weight
  for(var i = 1; i <= len; i++) weight += i;  // add range together [1, length]
  
  // plot original data at top of canvas
  plot(data, 30);

  // PASS 1: Calc new smoothed array
  dataa = calcWMA(data, len, weight);
  
  // plot smoothed curve
  ctx.fillText("FIRST PASS:", 0, 100);
  plot(dataa, 120);
    
  // PASS 2 (optional)
  datab = calcWMA(dataa, len, weight);
  ctx.fillText("SECOND PASS:", 0, 190);
  plot(datab, 210);
  
  ctx.stroke();  // render plots
}

function calcWMA(data, len, weight) {
  var i, t, datao = [];
  
  // calc new smoothed array 
  for(i = 0; i < data.length; i++) {       // iterate from length to end of data
    var v = 0;                             // calc average value for this position
    for(t = 0; t < len; t++) {             // [1, len]
      if (i-t >= 0)
        v += data[i-t] * ((t+1) / weight); // weight previous values based on -delta
    }
    datao.push(v);                         // store new value
  }
  return datao
}

function plot(data, y) {
  ctx.moveTo(0, y + data[0]*scale);
  for(i = 1; i < data.length; i++) ctx.lineTo(i * 2, y + data[i]*scale);
}

rng.onchange = rng.oninput = drawWMA;
<label>Points to consider: <input type="range" min=1 max=50 value=1></label><span>1</span><br>
<canvas width=600 height=300></canvas>

另一种方法是使用萨维茨基-戈莱滤波器 https://en.wikipedia.org/wiki/Savitzky%E2%80%93Golay_filter这给出了类似的结果,但不会“牺牲”最后的任何点(移动平均线将在最后推动或裁剪)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 Windows Phone 8.1 中使用加速度计传感器数据在画布上绘制线条 的相关文章

随机推荐