首页 > 其他分享 >动作识别中的傅里叶变换

动作识别中的傅里叶变换

时间:2023-04-22 22:57:35浏览次数:39  
标签:变换 sum Period np 识别 傅里叶 spec absolute

数据收集与清洗

最近的项目有一个需求是需要根据手机传感器的信息,对用户进行动作识别。

动作识别是通过一系列用户动作的记录和环境状况的数据,判断用户的运动状态(motion activity)。项目的需求仅限于根据数据判断用户的运动状态,如步行,跑步,驾车,骑车等。

采集数据采用的手机中的加速度计(accelerometer),Android的核心代码就是记录加速度计的数据以及当前行为状态的真值。采集的频率为 50Hz,综合考虑了耗电和存储的限制。同时在采集数据时,记录了Samsung motion API和Google Activity Recognition的数据,用来和项目最终的效果做一个对比。

public void onSensorChanged(SensorEvent sensorEvent) {
  if(sensorEvent.sensor.getType()== Sensor.TYPE_ACCELEROMETER){
        float x = sensorEvent.values[0];
        float y = sensorEvent.values[1];
        float z = sensorEvent.values[2];
        mLogger.info("record: " + mStatus + " [" + x + "," + y + "," + z + "]");
  }
}

根据奈奎斯特采样定理,在进行模拟/数字信号的转换过程中,当采样频率fs.max大于信号中最高频率fmax的2倍时(fs.max > fmax * 2),采样之后的数字信号完整地保留了原始信号中的信息,一般实际应用中保证采样频率为信号最高频率的2.56~4倍。虽然我们按照50Hz的标准来采集数据,但是在我们分析数据时,为了保证数据的完整性,应该只取用25Hz。

同时,动作识别需要根据一系列的数据来进行分析,单点的数据不能得到任何信息,因此,需要考虑的就是应该截取多大的时间段来做动作识别的分析。傅里叶变换要求要完整地分析一段离散的数据,那么这段数据中最大的周期应该包含在里面。多种动作中以步行的周期最大,此处暂定2s的时间段来进行分析。如果2s的时间段中覆盖了完整的行为周期,那么绘制出的傅里叶变换图像也应该是对称的。

傅里叶变换,特征抽取

本文的目的并不是要讲述动作识别的实现过程,而是要说明在特征抽取的过程中,最为重要的特征的理论说明和实现。

手机中采集的加速度计的数据是时域的信号,但是当我们需要对信号进行分析时,需要将时域的信号转换到频域中,并从中抽取出特征进行分析。
由于我们所采集的数据是离散的周期性数据,所以就对应离散傅里叶变换。随机抽取两条驾车和两条步行的数据,绘制图像:

import sys
import numpy as np
import matplotlib.pyplot as plt

PERIOD = 2 #s,时间间隔
FREQ = 50 #Hz,样本频率

cs = ['red', 'blue']
lab = ['car', 'walk']
count = 0

plt.figure(figsize = (10,8))
p1 = plt.subplot(211)
p2 = plt.subplot(212)

for line in sys.stdin:
    info = line.strip().split('\t')
    state = info[0]
    x = map(float, info[1].split(','))
    if state == 'bus':
        p1.scatter(np.linspace(0, FREQ, len(x)), np.absolute(np.fft.fft(x)), c= cs[count%2], \
                label = state + str(count%2), s = 30, alpha = (count + 1) * 0.2)
    elif state == 'walk':
        p2.scatter(np.linspace(0, FREQ, len(x)), np.absolute(np.fft.fft(x)), c= cs[count%2], \
                label = state + str(count%2), s = 30, alpha = (count + 1) * 0.2)
    else:
        continue
    count = count + 1

p1.legend()
p1.axis([-10.0,60.0, -10.0,50.0])
p1.set_xlabel('Freq(Hz)')
p1.set_ylabel('fft')

p2.legend()
p2.axis([-10.0,60.0, -10.0,50.0])
p2.set_xlabel('Freq(Hz)')
p2.set_ylabel('fft')

#plt.show()
plt.savefig('./all.png')

得到这四条记录的图像:

步行驾车四条记录

从图像就可以看出,同是步行的数据基本都重叠在一起,同是驾车的数据也基本都重叠在一起,也就是说我们通过分析傅里叶变换之后不同频率的数据的值来作为特征判断用户的动作。

为了直观感受驾车和步行在频域的区别,分别抽取一条步行和一条驾车的数据,绘制图像:

import sys
import numpy as np
import matplotlib.pyplot as plt

PERIOD = 2
FREQ = 50

cs = ['red', 'blue']
lab = ['car', 'walk']
count = 0

plt.figure(figsize = (10,5))

for line in sys.stdin:
    info = line.strip().split('\t')
    state = info[0]
    x = map(float, info[1].split(','))
    plt.scatter(np.linspace(0, FREQ, len(x)), np.absolute(np.fft.fft(x)), c = cs[count], label = state, s = 30, alpha = (count + 1) * 0.3)
    count  = count + 1

plt.legend()
plt.xlim(-10, 60)
plt.ylim(-10, 50)
plt.xlabel('Freq(Hz)')
plt.ylabel('fft')
#plt.show()
plt.savefig('./car_walk.png')

得到两条记录的图像:

步行驾车两条记录

从步行和驾车的图像对比来看,在低频阶段我们可以看到步行的值比驾车要高,但是在高频阶段,驾车的值要比步行的值要高,所以在采取特征进行训练时,我们考虑以下特征:

x_spec = np.fft.fft(xlist)
y_spec = np.fft.fft(ylist)
z_spec = np.fft.fft(zlist)
m_spec = np.fft.fft(magni)

x_f1 = np.sum(np.absolute(x_spec[:Period]))
y_f1 = np.sum(np.absolute(y_spec[:Period]))
z_f1 = np.sum(np.absolute(z_spec[:Period]))
m_f1 = np.sum(np.absolute(m_spec[:Period]))

x_f2_3 = np.sum(np.absolute(x_spec[2*Period:3*Period]))
y_f2_3 = np.sum(np.absolute(y_spec[2*Period:3*Period]))
z_f2_3 = np.sum(np.absolute(z_spec[2*Period:3*Period]))
m_f2_3 = np.sum(np.absolute(m_spec[2*Period:3*Period]))

x_f1_3 = np.sum(np.absolute(x_spec[1*Period:3*Period]))
y_f1_3 = np.sum(np.absolute(y_spec[1*Period:3*Period]))
z_f1_3 = np.sum(np.absolute(z_spec[1*Period:3*Period]))
m_f1_3 = np.sum(np.absolute(m_spec[1*Period:3*Period]))

x_f4_5 = np.sum(np.absolute(x_spec[4*Period:5*Period]))
y_f4_5 = np.sum(np.absolute(y_spec[4*Period:5*Period]))
z_f4_5 = np.sum(np.absolute(z_spec[4*Period:5*Period]))
m_f4_5 = np.sum(np.absolute(m_spec[4*Period:5*Period]))

x_f6_16 = np.sum(np.absolute(x_spec[6*Period:16*Period]))
y_f6_16 = np.sum(np.absolute(y_spec[6*Period:16*Period]))
z_f6_16 = np.sum(np.absolute(z_spec[6*Period:16*Period]))
m_f6_16 = np.sum(np.absolute(m_spec[6*Period:16*Period]))

x_f4_16 = np.sum(np.absolute(x_spec[4*Period:16*Period]))
y_f4_16 = np.sum(np.absolute(y_spec[4*Period:16*Period]))
z_f4_16 = np.sum(np.absolute(z_spec[4*Period:16*Period]))
m_f4_16 = np.sum(np.absolute(z_spec[4*Period:16*Period]))

傅里叶分析

之前没有学习过傅里叶分析,因为这次项目需要,所以就或多或少地了解了一些用来应对项目。

你眼中看似落叶纷飞变化无常的世界,实际只是躺在上帝怀中一份早已谱好的乐章。 看上去这么诗意的一句话其实是教材上对傅里叶分析的介绍。
傅里叶分析分为傅里叶级数(Fourier Serie)和傅里叶变换(Fourier Transformation)。法国数学家傅里叶发现,任何周期函数都可以用正弦函数和余弦函数构成的无穷级数来表示(选择正弦函数和余弦函数作为基函数是因为他们是正交的),暂时不考虑证明!

傅里叶级数

time_area

上图是sin(x) + sin(3x) + sin(5x) + sin(7*x)的图像以及它们分开的各自的图像。当这几个函数分开时,我们还是可以进行分辨的,但是一旦将它们组合在一起,我们无法分辨这个函数,也使得我们无法对其进行处理和提取信息。

freq_area

对应上一幅图中在时域的图像,这幅图显示了之前的函数在频域的图像,我们可以看出之前复杂的函数被分拆成多个函数的组合,以上是傅里叶级数的应用,实际可以用来进行信号的过滤,声音的提取等。

傅里叶分析究竟是干什么用的?这段相对比较枯燥,已经知道了的同学可以直接跳到下一个分割线。

先说一个最直接的用途。无论听广播还是看电视,我们一定对一个词不陌生——频道。频道频道,就是频率的通道,不同的频道就是将不同的频率作为一个通道来进行信息传输。下面大家尝试一件事:
先在纸上画一个sin(x),不一定标准,意思差不多就行。不是很难吧。

好,接下去画一个sin(3x)+sin(5x)的图形。别说标准不标准了,曲线什么时候上升什么时候下降你都不一定画的对吧?

好,画不出来不要紧,我把sin(3x)+sin(5x)的曲线给你,但是前提是你不知道这个曲线的方程式,现在需要你把sin(5x)给我从图里拿出去,看看剩下的是什么。这基本是不可能做到的。
但是在频域呢?则简单的很,无非就是几条竖线而已。

所以很多在时域看似不可能做到的数学操作,在频域相反很容易。这就是需要傅里叶变换的地方。尤其是从某条曲线中去除一些特定的频率成分,这在工程上称为滤波,是信号处理最重要的概念之一,只有在频域才能轻松的做到。

再说一个更重要,但是稍微复杂一点的用途——求解微分方程。(这段有点难度,看不懂的可以直接跳过这段)微分方程的重要性不用我过多介绍了。各行各业都用的到。但是求解微分方程却是一件相当麻烦的事情。因为除了要计算加减乘除,还要计算微分积分。而傅里叶变换则可以让微分和积分在频域中变为乘法和除法,大学数学瞬间变小学算术有没有。

傅里叶变换

傅里叶级数的本质是将一个周期的信号分解成无限多分开的(离散的)正弦波。
但是,我们在实际的应用中,遇到更多的是非周期的数据,而且我们也意识到无法将连续的非周期信号变换为周期的离散信号。
在傅里叶变换中,如果在时域的信号是周期离散的数据,那么对应在频域的信号就是非周期的离散的数据。
如果在时域的信号是周期连续的数据,那么对应在频域的信号就是非周期的连续的数据,对于单一的正余弦函数,是一条单一的直线。

参考资料:

  1. 傅里叶分析教程

标签:变换,sum,Period,np,识别,傅里叶,spec,absolute
From: https://www.cnblogs.com/xyhalcyon/p/17344353.html

相关文章

  • Dlib 结合 Opencv 识别技术代码资料
    结合Dlibshap64面部识别#include<dlib/opencv.h>#include<opencv2/opencv.hpp>#include<dlib/image_processing/frontal_face_detector.h>#include<dlib/image_processing/render_face_detections.h>#include<dlib/image_processing.h>......
  • 人脸识别 进度9
    张旭彤:写了:修复了新增学生后签到总表显示错误的问题问题:没有进行较为完善的整体测试准备:进行较为完善的整体测试冀朝赛:美化了一些页面的按钮,对新的学生注册并录入照片功能页面进行了美化。 团队照片: ......
  • OpenCV实现文档扫描识别
    目录1.处理读入图像(1)读入模板图像(2)预处理(3)轮廓检测(4)透视变换2.调用pytesseract工具实现图片内容的提取本文实现了对读入图片进行变换,最后调用pytesseract工具实现图片内容的提取。包含高斯滤波操作去除噪音点、边缘检测、轮廓检测、透视变换、pytesseract文本识别。步......
  • 人工智能:语音识别技术介绍
    今天给大家介绍一下关于语音识别相关的知识,希望对大家有所帮助!1、什么是语音语音指的是人类通过发声器官发出来具有一定意义、用来沟通交流的声音。计算机中语音存储:以波形文件的方式存储,通过波形反映语音的变化,从而可以获取音强、音长等参数信息。音域参数:傅利叶谱、梅尔频率到谱......
  • 记录问题:goland无法识别sdk的问题
    goland版本:2020go版本:1.20.3最新版在goland中配置GOROOT时找不到sdk解决版本:>cd/usr/local/go#我本地go的安装目录>cd/src/runtime/internal/sys>vizversion.gopackagesysconstTheVersion=`go1.20.3`//添加这一段代码,使用反引号重启goland打开,回到配置sd......
  • unity实现简单AR识别
    首先前往unity官网:https://unity.cn/releases,下拉找到下载UnityHub绿色按钮下载完安装进入UnityHub中,在侧边栏找到Installs,点击打开下载如图所示的unity版本(注:unity同ue,只能高版本向低版本兼容)下载过程中记得取消勾选Documentation,选择简体中文(注:很多内容需要访问外网......
  • YouTube怎么判断影片内含侵权内容? 解析Content ID内容识别系统的原理及功能
    你有没有发现YouTube上有许多没有声音,或是画面翻转的影片?这些主要都是为了逃避YouTube全自动的内容识别系统(ContentID)监测。YouTube为了保护版权影片,发展出这一套强大的武器:ContentID。到底ContentID是什么样的功能?有什么强大的能力呢? YouTubeContentID功能包含了影......
  • WebStorm 2023.1 vue文件标签中变量无法识别 Unresolved variable or type
    从老版本WebStorm升级到 WebStorm2023.1之后,打开项目莫名爆红 可能是查询的不对,很多博客指明是依赖的问题,实际修改无效问题出在文件类型指向不对修改为: 问题解决 ......
  • OpenCV实现银行卡数字识别
    目录1.预处理模板图像(1)读入模板图像(2)化为灰度图(3)化为二值图(4)画出0-9这10个数字的外轮廓(5)计算外接矩形并且resize成合适大小2.预处理银行卡图像(1)读入需识别的银行卡并化为灰度图(2)礼帽操作(3)梯度运算(Sobel算子)(4)闭操作(5)阈值分割(6)再进行闭操作(7)计算外轮廓(8)计......
  • GPT-NER:通过大型语言模型的命名实体识别
    讲在前面,chatgpt出来的时候就想过将其利用在信息抽取方面,后续也发现了不少基于这种大语言模型的信息抽取的论文,比如之前收集过的:https://github.com/cocacola-lab/GPT4IEhttps://github.com/RidongHan/Evaluation-of-ChatGPT-on-Information-Extractionhttps://github.com/cocac......