19

我正在编写一个应用程序,我的目标是检测用户何时行走。我正在使用这样的卡尔曼滤波器:

float kFilteringFactor=0.6f;

        gravity[0] = (accelerometer_values[0] * kFilteringFactor) + (gravity[0] * (1.0f - kFilteringFactor));
        gravity[1] = (accelerometer_values[1] * kFilteringFactor) + (gravity[1] * (1.0f - kFilteringFactor));
        gravity[2] = (accelerometer_values[2] * kFilteringFactor) + (gravity[2] * (1.0f - kFilteringFactor));

        linear_acceleration[0] = (accelerometer_values[0] - gravity[0]);
        linear_acceleration[1] = (accelerometer_values[1] - gravity[1]);
        linear_acceleration[2] = (accelerometer_values[2] - gravity[2]);

        float magnitude = 0.0f;
        magnitude = (float)Math.sqrt(linear_acceleration[0]*linear_acceleration[0]+linear_acceleration[1]*linear_acceleration[1]+linear_acceleration[2]*linear_acceleration[2]);
        magnitude = Math.abs(magnitude);
if(magnitude>0.2)
  //walking

数组gravity[]初始化为0。

我可以检测到用户何时行走(查看加速度矢量的大小值),但我的问题是,当用户不行走并且他移动手机时,他似乎在行走。

我使用了正确的过滤器吗?

只看向量的大小是正确的还是让我看单个值?

4

5 回答 5

24

谷歌为此提供了一个 API DetectedActivity,可以使用ActivityRecognitionApi. 可以在此处此处访问这些文档。

DetectedActivity具有public int getType()获取用户当前活动的方法,并且public int getConfidence()返回一个从0到100的值。返回的值越高getConfidence(),API越确定用户正在执行返回的活动。

以下是对返回内容的不断总结getType()

  • int IN_VEHICLE 设备在车辆中,例如汽车。
  • int ON_BICYCLE 设备在自行车上。
  • int ON_FOOT 设备在行走或跑步的用户身上。
  • int RUNNING 设备位于正在运行的用户上。
  • int STILL 设备静止(不移动)。
  • int TILTING 设备相对于重力的角度发生了显着变化。
  • int UNKNOWN 无法检测到当前活动。
  • int WALKING 设备在行走的用户身上。
于 2015-07-16T15:25:19.650 回答
5

我的第一个直觉是对传感器历史进行 FFT 分析,并查看行走时哪些频率具有高幅度。

它本质上是看到行走“听起来像”,将加速度计传感器输入视为麦克风,并查看行走时响亮的频率(换句话说,最大加速度发生的频率)。

我猜你会在一些低频(如脚步率)或其他东西上寻找高幅度。看看数据会很有趣。

我的猜测是您运行 FFT 并寻找某个频率的幅度大于某个阈值,或者两个频率的幅度之间的差异大于某个数量。同样,实际数据将决定您如何尝试检测它。

于 2013-01-03T17:35:29.567 回答
4

对于步行检测,我使用应用于来自加速度计的平滑信号的导数。当导数大于阈值时,我可以建议这是一个步骤。但我想这不是最好的做法,而且它只在手机放在裤子口袋里时才有效。

此应用程序中使用了以下代码https://play.google.com/store/apps/details?id=com.tartakynov.robotnoise

    @Override
    public void onSensorChanged(SensorEvent event) {
        if (event.sensor.getType() != Sensor.TYPE_ACCELEROMETER){
            return;
        }
        final float z = smooth(event.values[2]); // scalar kalman filter                               
        if (Math.abs(z - mLastZ) > LEG_THRSHOLD_AMPLITUDE)
        {
            mInactivityCount = 0;
            int currentActivity = (z > mLastZ) ? LEG_MOVEMENT_FORWARD : LEG_MOVEMENT_BACKWARD;                  
            if (currentActivity != mLastActivity){
                mLastActivity = currentActivity;
                notifyListeners(currentActivity);
            }                   
        } else {
            if (mInactivityCount > LEG_THRSHOLD_INACTIVITY) {
                if (mLastActivity != LEG_MOVEMENT_NONE){
                    mLastActivity = LEG_MOVEMENT_NONE;
                    notifyListeners(LEG_MOVEMENT_NONE);                                 
                }
            } else {
                mInactivityCount++;
            }
        }
        mLastZ = z;
    }
于 2012-10-03T05:40:32.767 回答
0

编辑:我认为它不够准确,因为当正常行走时,平均加速度将接近 0。测量加速度最多可以检测某人何时开始行走或停止(但正如您所说,很难从设备被站在一个地方的人移动)

所以......我之前写的,可能无论如何都行不通:

您可以通过在用户不移动时丢弃来“预测”用户是否在移动(很明显),我想到的前两个选项是:
检查手机是否“隐藏”,使用接近和光传感器(可选)。这种方法不太准确,但更容易。
控制动作的连续性,如果手机在移动超过... 10秒并且动作不卑鄙,那么你认为他在走路。我知道也不完美,但是不使用任何定位都很难,顺便说一句……你为什么不直接使用LocationManager

于 2011-02-14T16:23:30.883 回答
0

尝试检测上下摆动、前后摆动以及每个摆动的频率,并确保它们保持在平均范围内对齐,因为你会检测到步行,特别是那个人的步态风格,应该一次保持相对恒定的几个步骤有资格移动。只要最后 3 次振荡在合理范围内排列,那么只要这也是正确的,就可以得出结论:-

您测量水平加速度并用它更新速度值。速度会随时间漂移,但你需要保持一个移动平均速度在一个步骤的时间内平滑,只要它的漂移不超过每 3 次振荡行走速度的一半,那么它就是行走,但前提是它最初在很短的时间内(即半秒或 2 次振荡)内上升到步行速度。
所有这些都应该涵盖它。当然,如果您将所有这些都视为 NN 的输入,那么一点点 AI 将有助于使事情变得更简单或同样复杂但惊人的准确。即预处理。

于 2019-01-24T16:00:19.123 回答