# 手表运动状态识别（静止/走路/跑步）_v2（使用传统处理方法）

1.使用低通滤波去噪，获得平滑的曲线
2.寻找所有的波峰波谷，修正波峰波谷
3.计算相邻的距离和高度，判断是否走路

## 信号滤波+寻找波峰波谷:

``````import numpy as np
import cv2
import os
import math
from scipy import signal
import matplotlib.pyplot as plt

ax=[]
ay=[]
az=[]
gx=[]
gy=[]
gz=[]
ppg=[]
labels=[]
files=[]

for file in os.listdir(path):
if file.endswith('txt'):
file_name=path+file
else:
continue
f=open(file_name, 'r')

line=line.strip().split(',')

label=line[0]
data=line[1:]

# data=np.array(data)
# data=np.reshape(data,(-1,1))

# 归一化/标准化
# data = preprocessing.scale(data, axis=1, with_std=True)  # 标准化
# data = preprocessing.normalize(data, norm="l1", axis=1)  # 归一化
# data=(data-np.min(data))/(np.max(data)-np.min(data))   # min-max归一化
# data=(data-np.mean(data)) / np.std(data)   # 0均值,1方差 归一化

if 'ax' in file:
ax.append(data[0:20])
if 'ay' in file:
ay.append(data[0:20])
if 'az' in file:
az.append(data[0:20])
if 'gyrox' in file or 'gx' in file:
gx.append(data[0:20])
if 'gyroy' in file or 'gy' in file:
gy.append(data[0:20])
if 'gyroz' in file or 'gz' in file:
gz.append(data[0:20])

ax0=np.reshape(np.array(ax),-1)
ay0=np.reshape(np.array(ay),-1)
az0=np.reshape(np.array(az),-1)
gx0=np.reshape(np.array(gx),-1)
gy0=np.reshape(np.array(gy),-1)
gz0=np.reshape(np.array(gz),-1)
return ax0, ay0, az0, gx0, gy0, gz0

# path="E:/data/手表采集/all/clear-200/0/"
# path="data/jiexi1/all/1/"
path="test/test5/clear-200/0/"
ax0, ay0, az0, gx0, gy0, gz0 = load_data(path)
print("加载数据：", type(ax0), ax0.shape)

acc=[]
for i in range(len(ax0)):
x0=int(ax0[i])
y0=int(ay0[i])
z0=int(az0[i])
sqrt=np.sqrt((pow(x0,2)+pow(y0,2)+pow(z0,2)))
acc.append(sqrt)

base=1
gg=[]
t=20
total=int(len(acc)/t)-int(600/t)
for index in range(total+1):
# for index in range(1):
acc_y=acc[index*t : index*t+600]
# acc_y=np.array(acc[:])
acc_x=np.arange(len(acc_y))

# 滤波
b0, a0 = signal.butter(4, 2*2/100, 'lowpass')  # 1.低通滤波
# b, a = signal.butter(4, [2*1/100, 2*2/100], 'bandpass')  # 2.带通滤波
acc_y2 = signal.filtfilt(b0, a0, acc_y)
# acc_y2 = np.convolve(acc_y, np.ones(25)/25, mode='same')  # 3.平均滤波
# acc_y2 = sgolay(acc_y, 71, 3)  # 4.平滑滤波

# 寻找极值点
maxs_x=signal.argrelextrema(acc_y2,np.greater)[0]
maxs_y=acc_y2[signal.argrelextrema(acc_y2, np.greater)]
mins_x=signal.argrelextrema(acc_y2,np.less)[0]
mins_y=acc_y2[signal.argrelextrema(acc_y2, np.less)]

# 保证极小点作为开头和结尾，删除开头和结尾的极大点
if maxs_x[0]<mins_x[0]:
maxs_x=np.delete(maxs_x,0)
maxs_y=np.delete(maxs_y,0)
if len(maxs_x)==len(mins_x):
maxs_x=np.delete(maxs_x,-1)
maxs_y=np.delete(maxs_y,-1)
# print(len(mins_x), len(mins_y), len(maxs_x), len(maxs_y))

# 计算特征
step=0
for i in range(len(mins_x)-1):
distance1=mins_x[i+1] - mins_x[i]   # 两个极小点的x轴距离
distance2=maxs_y[i] - mins_y[i]   # 波峰-波谷的距离
k=(maxs_y[i]-mins_y[i])/(maxs_x[i]-mins_x[i])   # 斜率：波峰/波谷
# print(i+1, distance1, distance2, k)
if distance1>30 and distance2>400:
step+=1
# print(step)

# 步数大于5则证明这段时间在走路
if step>=5:
label=1
else:
label=0
if label==base:
gg.append(1)
else:
gg.append(0)
print("acc：", np.mean(gg))

plt.plot(acc_x, acc_y, 'r',label='polyfit values')
plt.plot(acc_x, acc_y2, 'g',label='polyfit values')
plt.plot(maxs_x,maxs_y, 'o', color='blue', markersize=5) #极大值点
plt.plot(mins_x, mins_y,'o', color='green', markersize=5) #极小值点
plt.show()

# if label!=base:
#     plt.title([index, step],fontsize=16)
#     plt.text(-3, 20, "function: y = x * x", size = 15)

#     plt.plot(acc_x, acc_y, 'r',label='polyfit values')
#     plt.plot(acc_x, acc_y2, 'g',label='polyfit values')

#     plt.plot(maxs_x,maxs_y, 'o', color='blue', markersize=5) #极大值点
#     plt.plot(mins_x, mins_y,'o', color='green', markersize=5) #极小值点
#     # plt.show()
#     plt.pause(0.3)
#     plt.close()``````

## 模拟现网数据：（二分类）

``````import numpy as np
import cv2
import os
import math
from scipy import signal
import matplotlib.pyplot as plt

ax=[]
ay=[]
az=[]
gx=[]
gy=[]
gz=[]
ppg=[]
labels=[]
files=[]

for file in os.listdir(path):
if file.endswith('txt'):
file_name=path+file
else:
continue
f=open(file_name, 'r')

line=line.strip().split(',')

label=line[0]
data=line[1:]

# data=np.array(data)
# data=np.reshape(data,(-1,1))

# 归一化/标准化
# data = preprocessing.scale(data, axis=1, with_std=True)  # 标准化
# data = preprocessing.normalize(data, norm="l1", axis=1)  # 归一化
# data=(data-np.min(data))/(np.max(data)-np.min(data))   # min-max归一化
# data=(data-np.mean(data)) / np.std(data)   # 0均值,1方差 归一化

if '-ax' in file:
ax.append(data[0:20])
if '-ay' in file:
ay.append(data[0:20])
if '-az' in file:
az.append(data[0:20])
if 'gyrox' in file or '-gx' in file:
gx.append(data[0:20])
if 'gyroy' in file or '-gy' in file:
gy.append(data[0:20])
if 'gyroz' in file or '-gz' in file:
gz.append(data[0:20])

ax0=np.reshape(np.array(ax),-1)
ay0=np.reshape(np.array(ay),-1)
az0=np.reshape(np.array(az),-1)
gx0=np.reshape(np.array(gx),-1)
gy0=np.reshape(np.array(gy),-1)
gz0=np.reshape(np.array(gz),-1)
return ax0, ay0, az0, gx0, gy0, gz0
# return gx0, gy0, gz0, gx0, gy0, gz0

def lvbo(acc_y):
# 滤波
b0, a0 = signal.butter(4, 2*2/100, 'lowpass')  # 1.低通滤波
acc_y2 = signal.filtfilt(b0, a0, acc_y)

# 寻找极值点
# acc_point=new_acc
acc_point=acc_y2
maxs_x=signal.argrelextrema(acc_point, np.greater)[0]
maxs_y=acc_point[signal.argrelextrema(acc_point, np.greater)]
mins_x=signal.argrelextrema(acc_point,np.less)[0]
mins_y=acc_point[signal.argrelextrema(acc_point, np.less)]

return acc_y2,maxs_x,maxs_y,mins_x,mins_y

def append_data(arr, data):
if len(arr)<3:
arr.append(data)
else:
arr=arr[1:]
arr.append(data)
return arr

def data_change(arr):
new_arr=[]
for datas in arr:
for data in datas:
new_arr.append(data)
return new_arr

def data_change2(arr):
new_arr=[]
for i in range(len(arr)):
datas=arr[i]
for data in datas:
data=data+200*i
new_arr.append(data)
return new_arr

# path='E:/data/watch_data/all/clear-200/0/'
# path="data/jiexi0/all/1/"
path="test/test5/clear-200/0/"
# ax0, ay0, az0, gx0, gy0, gz0 = load_data(path)
ax0, ay0, az0, gx0, gy0, gz0 = load_data(path)
print("加载数据：", type(ax0), ax0.shape)

acc=[]
for i in range(len(ax0)):
x0=int(ax0[i])
y0=int(ay0[i])
z0=int(az0[i])
sqrt=np.sqrt((pow(x0,2)+pow(y0,2)+pow(z0,2)))
acc.append(sqrt)

maxs_xx2=[]
maxs_yy2=[]
mins_xx2=[]
mins_yy2=[]
y2_list=[]

y_list=[]
gg=[]
base=1
t=200
total=int(len(acc)/t)
for index in range(total):
data=acc[index*t : (index+1)*t]

# 整体：600点滤波
# 1.数据进栈
y_list=append_data(y_list, data)
# 2.数据转换-变成一维数组
acc_y=data_change(y_list)
# 3.滤波+极值点
acc_y2,maxs_x,maxs_y,mins_x,mins_y=lvbo(acc_y)
# 4.删除开头和结尾的极大点
if maxs_x[0]<mins_x[0]:
maxs_x=np.delete(maxs_x,0)
maxs_y=np.delete(maxs_y,0)
if len(maxs_x)==len(mins_x):
maxs_x=np.delete(maxs_x,-1)
maxs_y=np.delete(maxs_y,-1)
# print(maxs_x,mins_x)

# 现网模拟-200点滤波
# 1.滤波+极值点
y2,maxs_x2,maxs_y2,mins_x2,mins_y2=lvbo(data)
# print(maxs_x2,)

# 纠正波峰波谷
if index>=1:
if len(mins_x2)>0 and len(maxs_x2)>0:
if maxs_x2[0]<mins_x2[0] and new_maxs_x[-1]>new_mins_x[-1]:
maxs_x2=np.delete(maxs_x2,0)
maxs_y2=np.delete(maxs_y2,0)
if len(mins_x2)>0 and len(maxs_x2)>0:
if maxs_x2[0]>mins_x2[0] and new_maxs_x[-1]<new_mins_x[-1]:
mins_x2=np.delete(mins_x2,0)
mins_y2=np.delete(mins_y2,0)

# 2.数据进栈
y2_list=append_data(y2_list,y2)
maxs_xx2=append_data(maxs_xx2,maxs_x2)
maxs_yy2=append_data(maxs_yy2,maxs_y2)
mins_xx2=append_data(mins_xx2,mins_x2)
mins_yy2=append_data(mins_yy2,mins_y2)

# 3.数据转换
new_acc=data_change(y2_list)
new_maxs_x=data_change2(maxs_xx2)
new_maxs_y=data_change(maxs_yy2)
new_mins_x=data_change2(mins_xx2)
new_mins_y=data_change(mins_yy2)
# print(index,len(new_acc), len(new_maxs_x), len(new_maxs_y))

# 4.删除开头和结尾的极大点
a=len(maxs_xx2)-1
if new_maxs_x[0]<new_mins_x[0]:
maxs_xx2[0]=np.delete(maxs_xx2[0],0)
maxs_yy2[0]=np.delete(maxs_yy2[0],0)
new_maxs_x=np.delete(new_maxs_x,0)
new_maxs_y=np.delete(new_maxs_y,0)
if new_maxs_x[-1]>new_mins_x[-1]:
maxs_xx2[a]=np.delete(maxs_xx2[a],-1)
maxs_yy2[a]=np.delete(maxs_yy2[a],0)
new_maxs_x=np.delete(new_maxs_x,-1)
new_maxs_y=np.delete(new_maxs_y,-1)
# print(len(new_mins_x), len(new_mins_y))

# 计算特征
step=0
for i in range(len(new_mins_x)-1):
distance1=new_mins_x[i+1] - new_mins_x[i]   # 两个极小点的x轴距离
distance2=new_maxs_y[i] - new_mins_y[i]   # 波峰-波谷的距离
k=(new_maxs_y[i]-new_mins_y[i])/(new_maxs_x[i]-new_mins_x[i])   # 斜率：波峰/波谷
# print(i+1, distance1, distance2, k)
if distance1>30 and distance2>400:
step+=1
# print(step)

if index>=2:
# 步数大于5则证明这段时间在走路
if step>=4:
label=1
else:
label=0
if label==base:
gg.append(1)
else:
gg.append(0)
# print("acc：", np.mean(gg), path, index)

acc_x=np.arange(len(acc_y))
x2=np.arange(len(new_acc))
plt.figure(figsize=(15,7))
plt.plot(acc_x, acc_y, 'b',label='acc_y')
plt.plot(acc_x, acc_y2, 'g',label='acc_y2')
plt.plot(x2, new_acc, 'r',label='new_acc')
plt.legend(loc='upper right')

plt.plot(new_maxs_x,new_maxs_y, 'o', color='blue', markersize=5) #极大值点
plt.plot(new_mins_x, new_mins_y,'o', color='green', markersize=5) #极小值点
plt.show()
#     # plt.pause(0.3)
#     # plt.close()``````

## 模拟现网数据：（三分类）

``````import numpy as np
import cv2
import os
import math
from scipy import signal
import matplotlib.pyplot as plt

ax=[]
ay=[]
az=[]
gx=[]
gy=[]
gz=[]
ppg=[]
labels=[]
files=[]

for file in os.listdir(path):
if file.endswith('txt'):
file_name=path+file
else:
continue
f=open(file_name, 'r')

line=line.strip().split(',')

label=line[0]
data=line[1:]

# data=np.array(data)
# data=np.reshape(data,(-1,1))

# 归一化/标准化
# data = preprocessing.scale(data, axis=1, with_std=True)  # 标准化
# data = preprocessing.normalize(data, norm="l1", axis=1)  # 归一化
# data=(data-np.min(data))/(np.max(data)-np.min(data))   # min-max归一化
# data=(data-np.mean(data)) / np.std(data)   # 0均值,1方差 归一化

if '-ax' in file:
ax.append(data[0:20])
if '-ay' in file:
ay.append(data[0:20])
if '-az' in file:
az.append(data[0:20])
if 'gyrox' in file or '-gx' in file:
gx.append(data[0:20])
if 'gyroy' in file or '-gy' in file:
gy.append(data[0:20])
if 'gyroz' in file or '-gz' in file:
gz.append(data[0:20])

ax0=np.reshape(np.array(ax),-1)
ay0=np.reshape(np.array(ay),-1)
az0=np.reshape(np.array(az),-1)
gx0=np.reshape(np.array(gx),-1)
gy0=np.reshape(np.array(gy),-1)
gz0=np.reshape(np.array(gz),-1)
return ax0, ay0, az0, gx0, gy0, gz0
# return gx0, gy0, gz0, gx0, gy0, gz0

def find_peak(arr):
peak1=[]
peak1_index=[]
for i in range(1,len(arr)-1):
if arr[i]>arr[i-1] and arr[i] > arr[i + 1] and len(peak1)<33:
peak1.append(arr[i])
peak1_index.append(i)

peak2=[]
peak2_index=[]
for i in range(1,len(arr)-1):
if arr[i]<arr[i-1] and arr[i] < arr[i + 1] and len(peak2)<33:
peak2.append(arr[i])
peak2_index.append(i)

return peak1_index,peak1,peak2_index,peak2

def lvbo(acc_y):
# 滤波
b0, a0 = signal.butter(2, 4*2/100, 'lowpass')  # 1.低通滤波
acc_y2 = signal.filtfilt(b0, a0, acc_y)

# 寻找极值点
acc_point=acc_y2
# maxs_x=signal.argrelextrema(acc_point, np.greater)[0]
# maxs_y=acc_point[signal.argrelextrema(acc_point, np.greater)]
# mins_x=signal.argrelextrema(acc_point,np.less)[0]
# mins_y=acc_point[signal.argrelextrema(acc_point, np.less)]

maxs_x,maxs_y,mins_x,mins_y=find_peak(acc_point)
return acc_y2,maxs_x,maxs_y,mins_x,mins_y

def append_data(arr, data):
if len(arr)<3:
arr.append(data)
else:
arr=arr[1:]
arr.append(data)
return arr

def data_change(arr):
new_arr=[]
for datas in arr:
for data in datas:
new_arr.append(data)
return new_arr

def data_change2(arr):
new_arr=[]
for i in range(len(arr)):
datas=arr[i]
for data in datas:
data=data+200*i
new_arr.append(data)
return new_arr

path = "test/test5/clear-200/0/"
ax0, ay0, az0, gx0, gy0, gz0 = load_data(path)
print("加载数据：", type(ax0), ax0.shape)

acc=[]
for i in range(len(ax0)):
x0=int(ax0[i])
y0=int(ay0[i])
z0=int(az0[i])
sqrt=np.sqrt((pow(x0,2)+pow(y0,2)+pow(z0,2)))
acc.append(sqrt)

maxs_xx2=[]
maxs_yy2=[]
mins_xx2=[]
mins_yy2=[]
y2_list=[]

y_list=[]
gg=[]
base=0
t=200
total=int(len(acc)/t)
for index in range(total):
data=acc[index*t : (index+1)*t]

# 整体：600点滤波
# 1.数据进栈
y_list=append_data(y_list, data)
# 2.数据转换-变成一维数组
acc_y=data_change(y_list)
# 3.滤波+极值点
acc_y2,maxs_x,maxs_y,mins_x,mins_y=lvbo(acc_y)
# 4.删除开头和结尾的极大点
if maxs_x[0]<mins_x[0]:
maxs_x=np.delete(maxs_x,0)
maxs_y=np.delete(maxs_y,0)
if len(maxs_x)==len(mins_x):
maxs_x=np.delete(maxs_x,-1)
maxs_y=np.delete(maxs_y,-1)
# print(maxs_x,mins_x)

# 现网模拟-200点滤波
# 1.滤波+极值点
y2,maxs_x2,maxs_y2,mins_x2,mins_y2=lvbo(data)
# print(maxs_x2,)

# 纠正波峰波谷
if index>=1:
if len(mins_x2)>0 and len(maxs_x2)>0:
if maxs_x2[0]<mins_x2[0] and new_maxs_x[-1]>new_mins_x[-1]:
maxs_x2=np.delete(maxs_x2,0)
maxs_y2=np.delete(maxs_y2,0)
if len(mins_x2)>0 and len(maxs_x2)>0:
if maxs_x2[0]>mins_x2[0] and new_maxs_x[-1]<new_mins_x[-1]:
mins_x2=np.delete(mins_x2,0)
mins_y2=np.delete(mins_y2,0)

# 2.数据进栈
y2_list=append_data(y2_list,y2)
maxs_xx2=append_data(maxs_xx2,maxs_x2)
maxs_yy2=append_data(maxs_yy2,maxs_y2)
mins_xx2=append_data(mins_xx2,mins_x2)
mins_yy2=append_data(mins_yy2,mins_y2)

# 3.数据转换
new_acc=data_change(y2_list)
new_maxs_x=data_change2(maxs_xx2)
new_maxs_y=data_change(maxs_yy2)
new_mins_x=data_change2(mins_xx2)
new_mins_y=data_change(mins_yy2)
# print(index,len(new_acc), len(new_maxs_x), len(new_maxs_y))

# 4.删除开头和结尾的极大点
a=len(maxs_xx2)-1
if new_maxs_x[0]<new_mins_x[0]:
maxs_xx2[0]=np.delete(maxs_xx2[0],0)
maxs_yy2[0]=np.delete(maxs_yy2[0],0)
new_maxs_x=np.delete(new_maxs_x,0)
new_maxs_y=np.delete(new_maxs_y,0)
if new_maxs_x[-1]>new_mins_x[-1]:
maxs_xx2[a]=np.delete(maxs_xx2[a],-1)
maxs_yy2[a]=np.delete(maxs_yy2[a],0)
new_maxs_x=np.delete(new_maxs_x,-1)
new_maxs_y=np.delete(new_maxs_y,-1)
# print(len(new_mins_x), len(new_mins_y))

# 计算特征
step1 = 0
step2 = 0
for i in range(len(new_mins_x)-1):
distance1=new_mins_x[i+1] - new_mins_x[i]   # 两个极小点的x轴距离
distance2=new_maxs_y[i] - new_mins_y[i]   # 波峰-波谷的距离
# k=(new_maxs_y[i]-new_mins_y[i])/(new_maxs_x[i]-new_mins_x[i])   # 斜率：波峰/波谷
# print(i+1, distance1, distance2, k)
if distance1 > 30:
if distance2 > 400 and distance2 < 3000:
step1 += 1
if distance2 > 3000:
step2 += 1

# print(step)

if index>=2:
# 步数大于5则证明这段时间在走路
if step2 >= 5:
label = 2
elif step1 >= 5:
label = 1
else:
label = 0
if label == base:
gg.append(1)
else:
gg.append(0)

# print("0-acc：", np.mean(gg), path, index)

acc_x=np.arange(len(acc_y))
x2=np.arange(len(new_acc))
plt.figure(figsize=(15,7))
plt.plot(acc_x, acc_y, 'b',label='acc_y')
plt.plot(acc_x, acc_y2, 'g',label='acc_y2')
plt.plot(x2, new_acc, 'r',label='new_acc')
plt.legend(loc='upper right')

plt.plot(new_maxs_x,new_maxs_y, 'o', color='blue', markersize=5) #极大值点
plt.plot(new_mins_x, new_mins_y,'o', color='green', markersize=5) #极小值点
plt.show()
#     # plt.pause(0.3)
#     # plt.close()``````

原文作者：尼古拉斯·two_dog
原文地址: https://blog.csdn.net/gm_Ergou/article/details/118388814
本文转自网络文章，转载此文章仅为分享知识，如有侵权，请联系博主进行删除。