目的:人在穿戴手表的时候,通过6轴传感器采集到三个方向的加速度acc和角速度gyro,以此检测人体的运动状态,是处于静止(坐着)、走路或跑步状态。
方法2:传统处理方法
数据集:20-30人
准确度:0.99
具体步骤:
1.使用低通滤波去噪,获得平滑的曲线
2.寻找所有的波峰波谷,修正波峰波谷
3.计算相邻的距离和高度,判断是否走路
备注:目前仅用了a0的信号数据
效果图:
静止样例1
静止样例2
运动样例1
运动样例2
信号滤波+寻找波峰波谷:
import numpy as np
import cv2
import os
import math
from scipy import signal
import matplotlib.pyplot as plt
def load_data(path):
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')
for line in f.readlines():
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()
模拟现网数据:(二分类)
现网每次进来200个点,滑窗间隔20个点,每600点(3s)作为一条数据。
import numpy as np
import cv2
import os
import math
from scipy import signal
import matplotlib.pyplot as plt
def load_data(path):
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')
for line in f.readlines():
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()
模拟现网数据:(三分类)
现网每次进来200个点,滑窗间隔20个点,每600点(3s)作为一条数据。
import numpy as np
import cv2
import os
import math
from scipy import signal
import matplotlib.pyplot as plt
def load_data(path):
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')
for line in f.readlines():
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()