日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

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

發(fā)布時(shí)間:2023/12/20 51 豆豆
生活随笔 收集整理的這篇文章主要介紹了 android 判断手机计步_Android_基于G-Sensor的计步算法 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

大家好,插播一下,最近花了點(diǎn)時(shí)間,基于g-sensor,在做一些姿勢(shì)識(shí)別的事情,比如走路,跑步,騎車(chē),起立,坐下,文章還在整理,歡迎關(guān)注。周末爭(zhēng)取傳個(gè)apk給大家體驗(yàn)一下。

開(kāi)始:

最新發(fā)現(xiàn)了很多文章將算法直接拿去用,簡(jiǎn)書(shū)上,github上,導(dǎo)致下面有很多疑問(wèn)。

希望大家轉(zhuǎn)載或者改造的時(shí)候,可以注明一下算法的原作者為 finnfu以及原文鏈接,謝謝。

很多人問(wèn)源碼地址,因?yàn)橐恍┰虿荒芴峁?#xff0c;寫(xiě)了個(gè)簡(jiǎn)單的算法demo,以及算法介紹文檔。

https://github.com/finnfu/stepcount

如果覺(jué)得對(duì)你有幫助,請(qǐng)給個(gè)star吧!

下面是正文:

目前在計(jì)步領(lǐng)域比較領(lǐng)先的有樂(lè)動(dòng)力以及春雨計(jì)步器,在做算法的參數(shù)調(diào)試的時(shí)候也是一直拿這兩個(gè)應(yīng)用做對(duì)比。樂(lè)動(dòng)力當(dāng)之無(wú)愧行業(yè)第一,不管是應(yīng)用的體驗(yàn)還是準(zhǔn)確度都是非常棒,春雨計(jì)步器的亮點(diǎn)是輕量級(jí),使用以及界面操作都很簡(jiǎn)單。之前因?yàn)橐恍┬枨?#xff0c;需要做一個(gè)計(jì)步器,所以就開(kāi)始自己研究算法了,各種場(chǎng)景(走路拿在手上,放在口袋,跑步),算法的準(zhǔn)確度大概可以達(dá)到95.7%,綜合起來(lái)覺(jué)得是比春雨略好,但是贏不了樂(lè)動(dòng)力(可以達(dá)到97.7%)在體驗(yàn)和大局觀為王的互聯(lián)網(wǎng)時(shí)代,我覺(jué)得技術(shù)上的差距會(huì)越來(lái)越小,重要的是體驗(yàn)還有對(duì)于產(chǎn)品的定位,所以決定將算法與大家分享,第一是希望可以幫到到家,第二也是希望大家提一些意見(jiàn),讓這個(gè)算法可以得到改進(jìn)。

人在走路時(shí)大致分為下面幾種場(chǎng)景:

1、正常走路,手機(jī)拿在手上(邊走邊看、甩手、不甩手)

2、慢步走,手機(jī)拿在手上(邊走邊看、甩手、不甩手)

3、快步走,手機(jī)拿在手上(甩手、不甩手、走的很快一般不會(huì)看手機(jī)吧)

4、手機(jī)放在褲袋里(慢走、快走、正常走)

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

6、上下樓梯(上面五中場(chǎng)景可以在這個(gè)場(chǎng)景中再次適用一遍)

以上,不管出于哪一種場(chǎng)景(其實(shí)對(duì)應(yīng)手機(jī)不同的運(yùn)動(dòng)規(guī)律),g-sensor的三軸數(shù)據(jù)都是有規(guī)律可以尋找的。

每一步都有特征點(diǎn),找到這個(gè)特征點(diǎn),就是識(shí)別出來(lái)一步。

下面推薦一個(gè)工具,叫g(shù)sensor-debug,可以觀察三軸的曲線,下面是手機(jī)上下擺動(dòng)的曲線

這是很規(guī)律曲線只要檢測(cè)波峰就行了,實(shí)際的走路曲線會(huì)有很多雜波,算法的作用就是濾除這些雜波(走路的波形可以用工具自己看,可以保存為文件,用excel打開(kāi)有數(shù)據(jù),將數(shù)據(jù)轉(zhuǎn)換為波形就可以自己看)

//存放三軸數(shù)據(jù)

float[]?oriValues?=newfloat[3];

finalintvalueNum?=4;

//用于存放計(jì)算閾值的波峰波谷差值

float[]?tempValue?=newfloat[valueNum];

inttempCount?=0;

//是否上升的標(biāo)志位

booleanisDirectionUp?=false;

//持續(xù)上升次數(shù)

intcontinueUpCount?=0;

//上一點(diǎn)的持續(xù)上升的次數(shù),為了記錄波峰的上升次數(shù)

intcontinueUpFormerCount?=0;

//上一點(diǎn)的狀態(tài),上升還是下降

booleanlastStatus?=false;

//波峰值

floatpeakOfWave?=0;

//波谷值

floatvalleyOfWave?=0;

//此次波峰的時(shí)間

longtimeOfThisPeak?=0;

//上次波峰的時(shí)間

longtimeOfLastPeak?=0;

//當(dāng)前的時(shí)間

longtimeOfNow?=0;

//當(dāng)前傳感器的值

floatgravityNew?=0;

//上次傳感器的值

floatgravityOld?=0;

//動(dòng)態(tài)閾值需要?jiǎng)討B(tài)的數(shù)據(jù),這個(gè)值用于這些動(dòng)態(tài)數(shù)據(jù)的閾值

finalfloatinitialValue?=?(float)1.3;

//初始閾值

floatThreadValue?=?(float)2.0;

privateStepListener?mStepListeners;

檢測(cè)步子就是檢測(cè)波峰,但是要濾除無(wú)效的波峰,主要采用了如下三種措施

a、規(guī)定曲線連續(xù)上升的次數(shù)

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

c、閾值是動(dòng)態(tài)改變的

另一個(gè)是一些參數(shù)的初始值,比如initialValue 以及ThreadValue 的初始值,以及averageValue函數(shù)的梯度化范圍值

需要結(jié)合各種場(chǎng)景的波形圖來(lái)統(tǒng)計(jì),還有幾十實(shí)際的測(cè)試來(lái)調(diào)試參數(shù),這些參數(shù)大概前后調(diào)了兩個(gè)星期,其實(shí)總體思路不復(fù)雜。

下面貼出核心代碼以及一些注釋:

(因?yàn)橐恍┰?#xff0c;整個(gè)工程我就不傳了,后面有時(shí)間我可以將app傳上來(lái))

/*

*?注冊(cè)了G-Sensor后一只會(huì)調(diào)用這個(gè)函數(shù)

*?對(duì)三軸數(shù)據(jù)進(jìn)行平方和開(kāi)根號(hào)的處理

*?調(diào)用DetectorNewStep檢測(cè)步子

*?*/

@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);

}

/*

*?檢測(cè)步子,并開(kāi)始計(jì)步

*?1.傳入sersor中的數(shù)據(jù)

*?2.如果檢測(cè)到了波峰,并且符合時(shí)間差以及閾值的條件,則判定為1步

*?3.符合時(shí)間差條件,波峰波谷差值大于initialValue,則將該差值納入閾值的計(jì)算中

*?*/

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;

/*

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

*?一般在通知更新界面之前,增加下面處理,為了處理無(wú)效運(yùn)動(dòng):

*?1.連續(xù)記錄10才開(kāi)始計(jì)步

*?2.例如記錄的9步用戶停住超過(guò)3秒,則前面的記錄失效,下次從頭開(kāi)始

*?3.連續(xù)記錄了9步用戶還在運(yùn)動(dòng),之前的數(shù)據(jù)才有效

*?*/

mStepListeners.onStep();

}

if(timeOfNow?-?timeOfLastPeak?>=250

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

timeOfThisPeak?=?timeOfNow;

ThreadValue?=?Peak_Valley_Thread(peakOfWave?-?valleyOfWave);

}

}

}

gravityOld?=?values;

}

/*

*?檢測(cè)波峰

*?以下四個(gè)條件判斷為波峰:

*?1.目前點(diǎn)為下降的趨勢(shì):isDirectionUp為false

*?2.之前的點(diǎn)為上升的趨勢(shì):lastStatus為true

*?3.到波峰為止,持續(xù)上升大于等于2次

*?4.波峰值大于20

*?記錄波谷值

*?1.觀察波形圖,可以發(fā)現(xiàn)在出現(xiàn)步子的地方,波谷的下一個(gè)就是波峰,有比較明顯的特征以及差值

*?2.所以要記錄每次的波谷值,為了和下次的波峰做對(duì)比

*?*/

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;

}

}

/*

*?閾值的計(jì)算

*?1.通過(guò)波峰波谷的差值計(jì)算閾值

*?2.記錄4個(gè)值,存入tempValue[]數(shù)組中

*?3.在將數(shù)組傳入函數(shù)averageValue中計(jì)算閾值

*?*/

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.計(jì)算數(shù)組的均值

*?2.通過(guò)均值將閾值梯度化在一個(gè)范圍里

*?3.參數(shù)暫時(shí)不開(kāi)放(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;

}

總結(jié)

以上是生活随笔為你收集整理的android 判断手机计步_Android_基于G-Sensor的计步算法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。