Android_基于G-Sensor的計(jì)步算法

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

基于g-sensor的起立坐下的的識(shí)別:

http://blog.csdn.net/finnfu/article/details/78543693

基于g-sensor的走路跑步騎車的識(shí)別:

http://blog.csdn.net/finnfu/article/details/78543622


開始:

一浪藻、寫在分享之前

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

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

很多人問源碼地址,因?yàn)橐恍┰虿荒芴峁┡ǖ桑瑢懥藗€(gè)簡(jiǎn)單的算法demo懈玻,以及算法介紹文檔。

https://github.com/finnfu/stepcount

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

下面是正文:

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

計(jì)步器apk下載地址

http://download.csdn.net/detail/finnfu/9534158

二贼急、計(jì)步器算法的總體思路以及輔助調(diào)試的工具

人在走路時(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í)別出來一步扼菠。

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

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

三、算法的介紹(貼出核心代碼)

1柑船、變量的定義

[java]view plaincopy

//存放三軸數(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;

2. 代碼亏拉,結(jié)合注釋看

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

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

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

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

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

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

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

(因?yàn)橐恍┰虿凼唬麄€(gè)工程我就不傳了,后面有時(shí)間我可以將app傳上來)

[java]view plaincopy

/*

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

*?對(duì)三軸數(shù)據(jù)進(jìn)行平方和開根號(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è)步子鸳兽,并開始計(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;

/*

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

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

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

*?2.例如記錄的9步用戶停住超過3秒,則前面的記錄失效戚嗅,下次從頭開始

*?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.通過波峰波谷的差值計(jì)算閾值

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

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

*?*/

publicfloatPeak_Valley_Thread(floatvalue)?{

floattempThread?=?ThreadValue;

if(tempCount?<?valueNum)?{

tempValue[tempCount]?=?value;

tempCount++;

}else{

tempThread?=?averageValue(tempValue,?valueNum);

for(inti?=1;?i?<?valueNum;?i++)?{

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

}

tempValue[valueNum?-1]?=?value;

}

returntempThread;

}

[java]view plaincopy

/*

*?梯度化閾值

*?1.計(jì)算數(shù)組的均值

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

*?3.參數(shù)暫時(shí)不開放(a,b,c,d,e,f,g,h,i,i,k,l)

*?*/

publicfloataverageValue(floatvalue[],intn)?{

floatave?=0;

for(inti?=0;?i?<?n;?i++)?{

ave?+=?value[i];

}

ave?=?ave?/?valueNum;

if(ave?>=?a)

ave?=?(float)?b;

elseif(ave?>=?c?&&?ave?<?d)

ave?=?(float)?e;

elseif(ave?>=?f?&&?ave?<?g)

ave?=?(float)?h;

elseif(ave?>=?i?&&?ave?<?j)

ave?=?(float)?k;

else{

ave?=?(float)?l;

}

returnave;

}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末后众,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子颅拦,更是在濱河造成了極大的恐慌蒂誉,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,113評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件距帅,死亡現(xiàn)場(chǎng)離奇詭異右锨,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)碌秸,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門绍移,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人哮肚,你說我怎么就攤上這事登夫。” “怎么了允趟?”我有些...
    開封第一講書人閱讀 153,340評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵恼策,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我潮剪,道長(zhǎng)涣楷,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,449評(píng)論 1 279
  • 正文 為了忘掉前任抗碰,我火速辦了婚禮狮斗,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘弧蝇。我一直安慰自己碳褒,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評(píng)論 5 374
  • 文/花漫 我一把揭開白布看疗。 她就那樣靜靜地躺著沙峻,像睡著了一般。 火紅的嫁衣襯著肌膚如雪两芳。 梳的紋絲不亂的頭發(fā)上摔寨,一...
    開封第一講書人閱讀 49,166評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音怖辆,去河邊找鬼是复。 笑死删顶,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的淑廊。 我是一名探鬼主播逗余,決...
    沈念sama閱讀 38,442評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼蒋纬!你這毒婦竟也來了猎荠?” 一聲冷哼從身側(cè)響起坚弱,我...
    開封第一講書人閱讀 37,105評(píng)論 0 261
  • 序言:老撾萬榮一對(duì)情侶失蹤蜀备,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后荒叶,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體碾阁,經(jīng)...
    沈念sama閱讀 43,601評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評(píng)論 2 325
  • 正文 我和宋清朗相戀三年些楣,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了脂凶。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,161評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡愁茁,死狀恐怖蚕钦,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情鹅很,我是刑警寧澤嘶居,帶...
    沈念sama閱讀 33,792評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站促煮,受9級(jí)特大地震影響邮屁,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜菠齿,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評(píng)論 3 307
  • 文/蒙蒙 一佑吝、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧绳匀,春花似錦芋忿、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至陋桂,卻和暖如春逆趣,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背嗜历。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評(píng)論 1 261
  • 我被黑心中介騙來泰國(guó)打工宣渗, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留抖所,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,618評(píng)論 2 355
  • 正文 我出身青樓痕囱,卻偏偏與公主長(zhǎng)得像田轧,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子鞍恢,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評(píng)論 2 344

推薦閱讀更多精彩內(nèi)容

  • 在市面上瀏覽過眾多的計(jì)步軟件傻粘,可惜沒有開源的代碼,而github上的幾個(gè)開源的計(jì)步代碼帮掉,要么就是記得不準(zhǔn)弦悉,要么就是...
    xbase閱讀 36,049評(píng)論 63 57
  • 不同圖像灰度不同,邊界處一般會(huì)有明顯的邊緣蟆炊,利用此特征可以分割圖像稽莉。需要說明的是:邊緣和物體間的邊界并不等同,邊緣...
    大川無敵閱讀 13,823評(píng)論 0 29
  • 二值化是圖像分割的一種方法涩搓。在二值化圖象的時(shí)候把大于某個(gè)臨界灰度值的像素灰度設(shè)為灰度極大值污秆,把小于這個(gè)值的像素灰度...
    木夜溯閱讀 13,015評(píng)論 0 10
  • 計(jì)算機(jī)二級(jí)C語言上機(jī)題庫(kù)(南開版) 1.m個(gè)人的成績(jī)存放在score數(shù)組中,請(qǐng)編寫函數(shù)fun,它的功能是:將低于平...
    MrSunbeam閱讀 6,323評(píng)論 1 42
  • 總是會(huì)憶起兒時(shí)的自己昧甘,那時(shí)候的自己良拼,沒有手機(jī),沒有電腦充边,每天也不會(huì)熬夜庸推,不會(huì)為任何事煩惱的睡不著。卻擁有快樂的童年...
    何目兮閱讀 613評(píng)論 1 4