1、聊一聊
其實(shí)每個(gè)人在無助的時(shí)候都需要一句“Cry On My Shoulder!” 今天跟大家介紹一種波峰波谷的檢測(cè)方法,不是很難,不過能夠凸顯數(shù)學(xué)在編程算法中的重要作用。
2、正文部分
1波峰波谷用處
對(duì)于信號(hào)波峰波谷識(shí)別在嵌入式領(lǐng)域應(yīng)該是非常廣泛的,因?yàn)榇蟛糠值男盘?hào)都處于一種時(shí)變的狀態(tài),信號(hào)在時(shí)域上處于一種類似于正弦波的波動(dòng)狀態(tài)。比如計(jì)步軟件就是通過IMU模塊所采集的變化的波形狀態(tài)來識(shí)別波峰波谷,最終估算你所走過步數(shù);
上圖顯示了一個(gè)典型的x-, y-和z-測(cè)量模式,對(duì)應(yīng)于一個(gè)跑步者的垂直,向前和側(cè)面加速度。無論如何佩戴計(jì)步器,至少有一個(gè)軸會(huì)有相對(duì)較大的周期性加速度變化,因此通過檢測(cè)其波峰波谷等算法即可對(duì)于檢測(cè)步行或跑步的單位周期至關(guān)重要。
還有在電力系統(tǒng)中的交流電壓電流,我們需要通過檢測(cè)波峰波谷來確定電壓電流在交流周期中的最大最小值,從而動(dòng)態(tài)調(diào)節(jié)系統(tǒng)參數(shù)來達(dá)到自適應(yīng)的目的,所以波峰波谷的檢測(cè)是非常有用的。
2比較法識(shí)別
常規(guī)的設(shè)計(jì)辦法為比較法 : 其中x表示當(dāng)前采樣點(diǎn)波峰:f(x) 》 f(x?1) 且 f(x) 》 f(x+1)波谷:f(x) 《 f(x?1) 且 f(x) 《 f(x+1)
然而這樣識(shí)別對(duì)于沒有什么噪聲,且每個(gè)采樣點(diǎn)為不同的信號(hào)來說還是合適的,但在嚴(yán)苛的環(huán)境中還需要構(gòu)造更多的判斷條件來進(jìn)行一些錯(cuò)誤判斷的規(guī)避,終究還是麻煩了一些,并且容易遺漏。
3差分識(shí)別
在學(xué)生階段我們就學(xué)習(xí)了導(dǎo)數(shù)的概念,如果一個(gè)函數(shù)一階導(dǎo)數(shù)左右異號(hào),那分別就是波峰或者波谷。而對(duì)于數(shù)字信號(hào)的處理通過采樣都會(huì)變成離散信號(hào),信號(hào)對(duì)時(shí)間的微分在離散域內(nèi)即為差分。在進(jìn)行波形識(shí)別之前數(shù)據(jù)采集是必不可少的,其中最重要的是采樣速率和精度,以便從采樣信號(hào)中不失真的恢復(fù)原連續(xù)信號(hào)。(香農(nóng)采樣)采樣的過程中由于電子器件的雜訊等,數(shù)據(jù)難免會(huì)引入噪聲,為了簡(jiǎn)化識(shí)別算法一般都會(huì)進(jìn)行濾波處理,比如一些平滑處理等,然后才開始波峰波谷識(shí)別。
A
識(shí)別算法過程
1、獲得采樣點(diǎn)序列
2、進(jìn)行差分處理
3、由于不在乎具體的差分幅值,把所有數(shù)據(jù)歸一到-1,0,1
4、差分值為0的點(diǎn)即為相同點(diǎn),如果使用比較法則峰值檢測(cè)可能失效,便需要更多的條件,而這里我們直接把相同點(diǎn)0置為前一個(gè)非0即可規(guī)避該問題。
5、最終Diff再次進(jìn)行差分,-2/+2即為波峰/波谷。
B
參考代碼
1#include 《stdio.h》
2#include 《stdlib.h》
3#define SAMPLE_MAX 20
4#define PV_MAX 10
5
6float Sample[SAMPLE_MAX]={1,2,3,4,4,4,5,2,1,0,0,5,1,0,0,1,2,3,4,0};
7float SampleDiff[SAMPLE_MAX]={0};
8
9typedef struct _tag_FindPV
10{
11 int Pos_Peak[PV_MAX]; //波峰位置存儲(chǔ)
12 int Pos_Valley[PV_MAX]; //波谷位置存儲(chǔ)
13 int Pcnt; //所識(shí)別的波峰計(jì)數(shù)
14 int Vcnt; //所識(shí)別的波谷計(jì)數(shù)
15}SFindPV;
16
17SFindPV stFindPV;
18
19/********************************************
20 * Fuction : initialFindPV
21 * Note : 初始化相關(guān)數(shù)據(jù)
22 *******************************************/
23void initialFindPV(void)
24{
25 int Index = 0;
26
27 for(Index = 0; Index 《 SAMPLE_MAX;Index ++)
28 {
29 SampleDiff[Index] = 0;
30 }
31
32 for(Index = 0; Index 《 PV_MAX;Index ++)
33 {
34 stFindPV.Pos_Peak[Index] = -1;
35 stFindPV.Pos_Valley[Index] = -1;
36 }
37 stFindPV.Pcnt = 0;
38 stFindPV.Vcnt = 0;
39
40}
41
42/********************************************
43 * Fuction : FindPV
44 * Note : 找波峰波谷
45 *******************************************/
46void FindPV(SFindPV *pFindPV,float *Sample)
47{
48 int i = 0;
49
50 //step 1 :首先進(jìn)行前向差分,并歸一化
51 for(i= 0; i 《 SAMPLE_MAX - 1; i++)
52 {
53 if (Sample[i + 1] - Sample[i]》0)
54 SampleDiff[i] = 1;
55 else if (Sample[i + 1] - Sample[i] 《 0)
56 SampleDiff[i] = -1;
57 else
58 SampleDiff[i] = 0;
59 }
60
61 //step 2 :對(duì)相鄰相等的點(diǎn)進(jìn)行領(lǐng)邊坡度處理
62 for(i= 0; i 《 SAMPLE_MAX-1; i++)
63 {
64 if(SampleDiff[i] == 0)
65 {
66 if(i == (SAMPLE_MAX-2))
67 {
68 if (SampleDiff[i - 1] 》= 0)
69 SampleDiff[i] = 1;
70 else
71 SampleDiff[i] = -1;
72 }
73 else
74 {
75 if (SampleDiff[i + 1] 》= 0)
76 SampleDiff[i] = 1;
77 else
78 SampleDiff[i] = -1;
79 }
80
81 }
82 }
83
84 //step 3 :對(duì)相鄰相等的點(diǎn)進(jìn)行領(lǐng)邊坡度處理
85 for(i= 0; i 《 SAMPLE_MAX-1; i++)
86 {
87 if(SampleDiff[i + 1] - SampleDiff[i] == -2) //波峰識(shí)別
88 {
89 pFindPV-》Pos_Peak[pFindPV-》Pcnt] = i + 1;
90 pFindPV-》Pcnt++;
91 }
92 else if(SampleDiff[i + 1] - SampleDiff[i] == 2) //波谷識(shí)別
93 {
94 pFindPV-》Pos_Valley[pFindPV-》Vcnt] = i + 1;
95 pFindPV-》Vcnt++;
96 }
97 }
98}
99
100/********************************************
101 * Fuction : main
102 * Note : 模擬查找波峰波谷
103 *******************************************/
104int main(int argc, char *argv[]) {
105
106 int i = 0;
107
108 initialFindPV();
109
110 FindPV(&stFindPV,Sample);
111
112 printf(“Peak
”);
113 for(i = 0 ;i《 stFindPV.Pcnt;i++)
114 {
115 printf(“-%d”,stFindPV.Pos_Peak[i] + 1); //加1是為了與上圖橫坐標(biāo)一致
116 }
117
118 printf(“
Valley
”);
119 for(i = 0 ;i《 stFindPV.Vcnt;i++)
120 {
121 printf(“-%d”,stFindPV.Pos_Valley[i] + 1);
122 }
123
124 printf(“
”);
125 printf(“歡迎關(guān)注:最后一個(gè)bug
”);
126 return 0;
127}
2、最后
當(dāng)然在實(shí)際的項(xiàng)目中為了更加穩(wěn)定的識(shí)別波峰波谷可能會(huì)對(duì)波峰波谷的出現(xiàn)特點(diǎn)進(jìn)行限制,從而進(jìn)一步減少誤識(shí)別,也有許多人使用數(shù)據(jù)擬合的辦法來識(shí)別波峰波谷,那么識(shí)別的準(zhǔn)確度就與所擬合的函數(shù)有關(guān),通過數(shù)學(xué)方法對(duì)所擬合函數(shù)進(jìn)行波峰波谷的求解,最終得到信號(hào)的波峰波谷,不過這樣的擬合過程對(duì)平臺(tái)的處理能力提出了一定的要求。
編輯:lyn
-
算法
+關(guān)注
關(guān)注
23文章
4619瀏覽量
93041 -
信號(hào)
+關(guān)注
關(guān)注
11文章
2794瀏覽量
76872 -
代碼
+關(guān)注
關(guān)注
30文章
4799瀏覽量
68728
原文標(biāo)題:信號(hào)波峰波谷二階差分識(shí)別算法
文章出處:【微信號(hào):zhuyandz,微信公眾號(hào):FPGA之家】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論