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

目的:人在穿戴手表的时候,通过6轴传感器采集到三个方向的加速度acc和角速度gyro,以此检测人体的运动状态,是处于静止(坐着)、走路或跑步状态。

方法2:传统处理方法
数据集:20-30人
准确度:0.99
具体步骤:
1.使用低通滤波去噪,获得平滑的曲线
2.寻找所有的波峰波谷,修正波峰波谷
3.计算相邻的距离和高度,判断是否走路

备注:目前仅用了a0的信号数据

效果图:

《手表运动状态识别(静止/走路/跑步)_v2(使用传统处理方法)》

静止样例1

《手表运动状态识别(静止/走路/跑步)_v2(使用传统处理方法)》静止样例2

《手表运动状态识别(静止/走路/跑步)_v2(使用传统处理方法)》

运动样例1

《手表运动状态识别(静止/走路/跑步)_v2(使用传统处理方法)》

运动样例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()

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