大家好,插播一下,最近花了点时间,基于g-sensor,在做一些姿势识别的事情,比如走路,跑步,骑车,起立,坐下,文章还在整理,欢迎关注。周末争取传个apk给大家体验一下。

开始:

最新发现了很多文章将算法直接拿去用,简书上,github上,导致下面有很多疑问。

希望大家转载或者改造的时候,可以注明一下算法的原作者为 finnfu以及原文链接,谢谢。

很多人问源码地址,因为一些原因不能提供,写了个简单的算法demo,以及算法介绍文档。

https://github.com/finnfu/stepcount

如果觉得对你有帮助,请给个star吧!

下面是正文:

目前在计步领域比较领先的有乐动力以及春雨计步器,在做算法的参数调试的时候也是一直拿这两个应用做对比。乐动力当之无愧行业第一,不管是应用的体验还是准确度都是非常棒,春雨计步器的亮点是轻量级,使用以及界面操作都很简单。之前因为一些需求,需要做一个计步器,所以就开始自己研究算法了,各种场景(走路拿在手上,放在口袋,跑步),算法的准确度大概可以达到95.7%,综合起来觉得是比春雨略好,但是赢不了乐动力(可以达到97.7%)在体验和大局观为王的互联网时代,我觉得技术上的差距会越来越小,重要的是体验还有对于产品的定位,所以决定将算法与大家分享,第一是希望可以帮到到家,第二也是希望大家提一些意见,让这个算法可以得到改进。

人在走路时大致分为下面几种场景:

1、正常走路,手机拿在手上(边走边看、甩手、不甩手)

2、慢步走,手机拿在手上(边走边看、甩手、不甩手)

3、快步走,手机拿在手上(甩手、不甩手、走的很快一般不会看手机吧)

4、手机放在裤袋里(慢走、快走、正常走)

5、手机放在上衣口袋里(慢走、快走、正常走)

6、上下楼梯(上面五中场景可以在这个场景中再次适用一遍)

以上,不管出于哪一种场景(其实对应手机不同的运动规律),g-sensor的三轴数据都是有规律可以寻找的。

每一步都有特征点,找到这个特征点,就是识别出来一步。

下面推荐一个工具,叫gsensor-debug,可以观察三轴的曲线,下面是手机上下摆动的曲线

这是很规律曲线只要检测波峰就行了,实际的走路曲线会有很多杂波,算法的作用就是滤除这些杂波(走路的波形可以用工具自己看,可以保存为文件,用excel打开有数据,将数据转换为波形就可以自己看)

//存放三轴数据

float[] oriValues =newfloat[3];

finalintvalueNum =4;

//用于存放计算阈值的波峰波谷差值

float[] tempValue =newfloat[valueNum];

inttempCount =0;

//是否上升的标志位

booleanisDirectionUp =false;

//持续上升次数

intcontinueUpCount =0;

//上一点的持续上升的次数,为了记录波峰的上升次数

intcontinueUpFormerCount =0;

//上一点的状态,上升还是下降

booleanlastStatus =false;

//波峰值

floatpeakOfWave =0;

//波谷值

floatvalleyOfWave =0;

//此次波峰的时间

longtimeOfThisPeak =0;

//上次波峰的时间

longtimeOfLastPeak =0;

//当前的时间

longtimeOfNow =0;

//当前传感器的值

floatgravityNew =0;

//上次传感器的值

floatgravityOld =0;

//动态阈值需要动态的数据,这个值用于这些动态数据的阈值

finalfloatinitialValue = (float)1.3;

//初始阈值

floatThreadValue = (float)2.0;

privateStepListener mStepListeners;

检测步子就是检测波峰,但是要滤除无效的波峰,主要采用了如下三种措施

a、规定曲线连续上升的次数

b、波峰波谷的差值需要大于阈值

c、阈值是动态改变的

另一个是一些参数的初始值,比如initialValue 以及ThreadValue 的初始值,以及averageValue函数的梯度化范围值

需要结合各种场景的波形图来统计,还有几十实际的测试来调试参数,这些参数大概前后调了两个星期,其实总体思路不复杂。

下面贴出核心代码以及一些注释:

(因为一些原因,整个工程我就不传了,后面有时间我可以将app传上来)

/*

* 注册了G-Sensor后一只会调用这个函数

* 对三轴数据进行平方和开根号的处理

* 调用DetectorNewStep检测步子

* */

@Override

publicvoidonSensorChanged(SensorEvent event) {

for(inti =0; i <3; i++) {

oriValues[i] = event.values[i];

}

gravityNew = (float) Math.sqrt(oriValues[0] * oriValues[0]

+ oriValues[1] * oriValues[1] + oriValues[2] * oriValues[2]);

DetectorNewStep(gravityNew);

}

/*

* 检测步子,并开始计步

* 1.传入sersor中的数据

* 2.如果检测到了波峰,并且符合时间差以及阈值的条件,则判定为1步

* 3.符合时间差条件,波峰波谷差值大于initialValue,则将该差值纳入阈值的计算中

* */

publicvoidDetectorNewStep(floatvalues) {

if(gravityOld ==0) {

gravityOld = values;

}else{

if(DetectorPeak(values, gravityOld)) {

timeOfLastPeak = timeOfThisPeak;

timeOfNow = System.currentTimeMillis();

if(timeOfNow - timeOfLastPeak >=250

&& (peakOfWave - valleyOfWave >= ThreadValue)) {

timeOfThisPeak = timeOfNow;

/*

* 更新界面的处理,不涉及到算法

* 一般在通知更新界面之前,增加下面处理,为了处理无效运动:

* 1.连续记录10才开始计步

* 2.例如记录的9步用户停住超过3秒,则前面的记录失效,下次从头开始

* 3.连续记录了9步用户还在运动,之前的数据才有效

* */

mStepListeners.onStep();

}

if(timeOfNow - timeOfLastPeak >=250

&& (peakOfWave - valleyOfWave >= initialValue)) {

timeOfThisPeak = timeOfNow;

ThreadValue = Peak_Valley_Thread(peakOfWave - valleyOfWave);

}

}

}

gravityOld = values;

}

/*

* 检测波峰

* 以下四个条件判断为波峰:

* 1.目前点为下降的趋势:isDirectionUp为false

* 2.之前的点为上升的趋势:lastStatus为true

* 3.到波峰为止,持续上升大于等于2次

* 4.波峰值大于20

* 记录波谷值

* 1.观察波形图,可以发现在出现步子的地方,波谷的下一个就是波峰,有比较明显的特征以及差值

* 2.所以要记录每次的波谷值,为了和下次的波峰做对比

* */

publicbooleanDetectorPeak(floatnewValue,floatoldValue) {

lastStatus = isDirectionUp;

if(newValue >= oldValue) {

isDirectionUp =true;

continueUpCount++;

}else{

continueUpFormerCount = continueUpCount;

continueUpCount =0;

isDirectionUp =false;

}

if(!isDirectionUp && lastStatus

&& (continueUpFormerCount >=2|| oldValue >=20)) {

peakOfWave = oldValue;

returntrue;

}elseif(!lastStatus && isDirectionUp) {

valleyOfWave = oldValue;

returnfalse;

}else{

returnfalse;

}

}

/*

* 阈值的计算

* 1.通过波峰波谷的差值计算阈值

* 2.记录4个值,存入tempValue[]数组中

* 3.在将数组传入函数averageValue中计算阈值

* */

publicfloatPeak_Valley_Thread(floatvalue) {

floattempThread = ThreadValue;

if(tempCount

tempValue[tempCount] = value;

tempCount++;

}else{

tempThread = averageValue(tempValue, valueNum);

for(inti =1; i

tempValue[i -1] = tempValue[i];

}

tempValue[valueNum -1] = value;

}

returntempThread;

}

/*

* 梯度化阈值

* 1.计算数组的均值

* 2.通过均值将阈值梯度化在一个范围里

* 3.参数暂时不开放(a,b,c,d,e,f,g,h,i,i,k,l)

* */

publicfloataverageValue(floatvalue[],intn) {

floatave =0;

for(inti =0; i

ave += value[i];

}

ave = ave / valueNum;

if(ave >= a)

ave = (float) b;

elseif(ave >= c && ave

ave = (float) e;

elseif(ave >= f && ave

ave = (float) h;

elseif(ave >= i && ave

ave = (float) k;

else{

ave = (float) l;

}

returnave;

}

android 判断手机计步_Android_基于G-Sensor的计步算法相关推荐

  1. android 判断miui版本,Android判断手机是否是小米MIUI系统的方法

    易采站长站为您分析Android判断手机是否是小米MIUI系统的方法的相关资料,需要的朋友可以参考下 废话不多说了,直接给大家贴代码了: 具体代码如下所示: public class MIUIUtil ...

  2. android 判断手机为小米

    之前,自己写了获取相册图片的代码,在自己手机上测试没有问题,不过小米手机却出现问题.在网上搜索资料,发现小米手机与其他德 处理不同.所以今天写一下判断手机系统的内容.其实很简单. public sta ...

  3. android+判断小米手机,android 判断手机为小米

    释放双眼,带上耳机,听听看~! 之前,自己写了获取相册图片的代码,在自己手机上测试没有问题,不过小米手机却出现问题.在网上搜索资料,发现小米手机与其他德 处理不同.所以今天写一下判断手机系统的内容.其 ...

  4. RomUtil【Android判断手机ROM,用于判断手机机型】

    参考资料 Android判断手机ROM 正文 有时候需要判断手机系统的ROM,检测ROM是MIUI.EMUI还是Flyme,可以使用getprop命令,去系统build.prop文件查找是否有对应属性 ...

  5. android判断软件是否已root权限,Android应用开发Android 判断手机是否有root权限方法...

    本文将带你了解Android应用开发Android 判断手机是否有root权限方法,希望本文对大家学Android有所帮助. root权限是安卓最高的操作权限,俗称superuser,简称su,一般来 ...

  6. Android 判断手机是32位CPU还是64位CPU android.os.Build类字段含义

    手机cpu分32位与64位,下面介绍如何在所有android版本上判断手机cpu位数是32位还是64位. 1 Android 判断手机是32位CPU还是64位CPU Android从API level ...

  7. android 判断手机是否是国内的手机的方法

    转载:android 判断手机是否是国内的手机的方法(getSimCountryIso和getSimOperator) http://blog.csdn.net/mingli198611/articl ...

  8. android 判断手机是否有物理menu键

    android 判断手机是否有物理menu键 ViewConfiguration.get(getContext()).hasPermanentMenuKey();

  9. Android判断手机ROM

    该方式并不能使用,已经废弃 本篇文章是转自以下链接: https://www.jianshu.com/p/ba9347a5a05a 附加Android build.prop简介: https://ww ...

  10. Android判断手机ROM 手机os

    有时候需要判断手机系统的ROM,检测ROM是MIUI.EMUI还是Flyme,可以使用getprop命令,去系统build.prop文件查找是否有对应属性来判断是什么ROM. build.prop的介 ...

最新文章

  1. 【C++】 64_C++中的异常处理 (上)
  2. 如何架设自己的 SAP UI5 资源服务器
  3. 更改盘符不成功_酷小二资讯:天猫店铺转让后可以更改类目和店铺名吗?
  4. [CTO札记]第1天:认识人、熟悉环境
  5. androidpn的学习研究(七)Androidpn-server的添加其他xmpp相关的协议(如查看好友列表等)...
  6. 无线传感网1-简单介绍
  7. 程序批量将文本文件中的某字符替换
  8. python可视化数据分析交互作用_测试设计功能交互分析
  9. OceanBase数据库大赛
  10. 服务器淘汰cpu组装的电脑,从服务器淘汰下来的至强cpu还可以用多久
  11. docset文件,aviary sdk,一个bug
  12. 叉叉助手开发环境安卓版_按键精灵安卓版零基础系列教程基础环境知识讲解
  13. 前端css中常见的-moz-,-webkit-,-o-分别是什么?
  14. iOS ”打仙人掌“游戏一---游戏玩法实现
  15. 做自媒体怎样开始起步?
  16. C语言 第六章 指针 重点 典型题
  17. Spatio-Temporal Graph Convolutional Networks: A Deep Learning Framework for Traffic
  18. 库乐队安卓版_【浦东小学音乐教研】玩转“酷”乐队
  19. 人见人爱A^B之解题思路
  20. unity 正六边形网格绘制(精简版)-代码可直接复用

热门文章

  1. C语言哈希表uthash的使用方法详解(附下载链接)
  2. php 1---100之间的和 几种方法
  3. DSP学习笔记——基于TMS320F28335
  4. HDMI之DDC通道
  5. Camera 驱动 Bringup
  6. LCD1602字符串显示(STM32F103)
  7. php做一个每天的考勤表,教你做一个酷毙的考勤表!|
  8. 下载的java游戏怎么运行不了_不支持JAVA的手机如何下载运行游戏和QQ
  9. armv6、armv7、armv7s及arm64
  10. teechart的addarray_【TeeChart Pro ActiveX教程】(六):使用系列(下)