主要内容

使用惯性测量单元的手势识别

这个例子展示了如何基于手持惯性测量单元(IMU)识别手势。手势识别是一般人类活动识别(HAR)领域的一个子领域。在本例中,使用四元数动态时间扭曲和聚类构建模板匹配算法,对五种手势进行分类。

动态时间翘曲是一种用来度量两个时间序列数据之间相似性的算法。动态时间扭曲比较两个序列,方法是将第一个序列中的数据点与第二个序列中的数据点对齐,忽略时间同步动态时间翘曲还提供了两个未对齐序列之间的距离度量。

与动态时间翘曲类似,四元数动态时间翘曲在四元数空间或旋转空间中比较两个序列[1]

四元数动态时间扭曲还返回两个方向轨迹之间的标量距离。这个距离度量允许你聚类数据,并为每个手势找到一个模板轨迹。您可以使用一组模板轨迹来识别和分类新的轨迹。

这种使用四元数动态时间翘曲和聚类生成模板轨迹的方法是中描述的两级分类系统的第二级[2]

手势和数据收集

在本例中,您将构建一个识别并分类以下五种手势的算法。每个动作都从同一位置开始,右前臂水平,与地面平行。

  • 向上-举起手臂,然后回到水平。

up.png

  • 向下- L放下手臂,然后回到水平。

down.png

  • -向左滑动手臂,然后返回中心。练习期间前臂与地面平行。

left.png

  • 正确的-向右滑动手臂,然后回到中心。练习期间前臂与地面平行。

right.png

  • —手顺时针旋转90度,回到原来的方向。练习期间前臂与地面平行。

twist.png

方法捕获这五种手势的数据Arduino 金宝appMATLAB支持包。四个不同的人表演这五个手势,每个手势重复九到十次。记录的数据,保存为表格,包含加速度计和陀螺仪读数、采样率、正在执行的手势,以及执行手势的人的名字。

传感器融合预处理

第一步是融合所有加速度计和陀螺仪读数,以产生一组方向时间序列,或轨迹。您将使用imufilter系统对象用于融合加速度计和陀螺仪读数。的imufilter“系统”对象可在“导航工具箱”和“传感器融合与跟踪工具箱”中使用。你可以使用parfor循环来加速计算。如果你有并行计算工具箱parfor循环将并行运行,否则为常规运行循环将按顺序运行。

Ld =负载(“imuGestureDataset.mat”);dataset = ld.imuGestureDataset;数据集=数据集(randperm(size(数据集,1)),:);% Shuffle数据集Ntrials = size(数据集,1);Orientation = cell(Ntrials,1);parforii=1:Ntrials h = imufilter(“SampleRate”数据集(二世:).SampleRate);方向{ii} = h(数据集。dataset.Gyroscope加速度计{2},{2});结束
使用'Processes'配置文件启动并行池(parpool)…连接到并行池(工人数量:4)。
dataset = addvars(dataset, Orientation, NewVariableNames=“定位”);手势=字符串(唯一的(dataset.Gesture));所有手势类型的数组people =字符串(唯一的(dataset.Who));Ngestures =数字(手势);Npeople =数字(人);

四元数动态时间扭曲背景

四元数动态时间翘曲[1]比较了四元数空间中的两个方向时间序列,提出了一个由四元数距离、导数和曲率三部分组成的距离度量。在本例中,您将只比较基于四元数距离的信号。

四元数动态时间翘曲使用时间翘曲来计算两个序列之间的最佳对齐。

下面使用四元数动态时间翘曲来比较两个方向序列(四元数)。

创建两个随机方向:

rng (20);Q = randrot(2,1);

创建两个不同的轨道连接两个方向:

H1 = 0:0.01:1;H2 = [0 (1,10) (h1).^2];Traj1 = slerp(q(1),q(2),h1).';Traj2 = slerp(q(1),q(2),h2).';

请注意traj1而且traj2在相同的方向开始和结束,它们有不同的长度,它们沿着这些方向以不同的速度转换。

接下来比较并找到这两个轨迹之间的最佳对齐使用四元数动态时间翘曲。

[qdist, idx1, idx2] = helperQDTW(traj1, traj2);

它们之间的距离度量是一个标量

qdist
Qdist = 1.1474

控件绘制最佳对齐idx1而且idx2变量

E1 = eulerd(traj1,“ZYX股票”“帧”);E2 = eulerd(traj2,“ZYX股票”“帧”);图;次要情节(1,1);情节(e1,“-”);传奇(“偏航(Z)”“球场(Y)”“滚(X)”);ylabel (“traj1”)次要情节(3、1、2);集(gca),“ColorOrderIndex”4);持有;情节(e2、“-”);传奇(“偏航(Z)”“球场(Y)”“滚(X)”);ylabel (“traj2”)举行;次要情节(3,1,3);阴谋(1:元素个数(idx1) e1 (idx1,:)“-”...1:元素个数(idx2) e2 (idx2:)“o”);标题(“对齐信号”);次要情节(1,1);标题(" traj1和traj2的欧拉角"

图中包含3个轴对象。axis对象1,标题为traj1和traj2的Euler Angles,包含3个类型为line的对象。这些对象表示偏航(Z),俯仰(Y),横滚(X)。坐标轴对象2包含3个类型为line的对象。这些对象表示偏航(Z),俯仰(Y),横滚(X)。轴对象3的标题为Aligned信号包含6个类型为line的对象。

snapnow;

训练和测试数据划分

数据集包含四个测试对象的轨迹。您将使用来自三个主题的数据训练您的算法,并在第四个主题上测试算法。这个过程重复四次,每次交替使用谁进行测试,谁进行培训。您将为每一轮测试生成一个混淆矩阵,以查看分类精度。

精度=零(1,n人);pp=1:Npeople testPerson = people(pp);Trainset = dataset(数据集。谁~= testPerson,:);Testset = dataset(数据集。Who == testPerson,:);

有了收集到的手势数据,您可以使用四元数动态时间扭曲函数来计算特定手势的所有记录之间的相互距离。

预分配一个距离结构并计算距离gg=1:Ngestures (gg);Subdata = trainset(列车集)手势== gest,:);Nsubdata = size(subdata,1);D = 0 (Nsubdata);traj = subdata.Orientation;parfor2 = 1: Nsubdatajj = 1: Nsubdata如果Jj > ii只计算三角矩阵D(ii,jj) = helperQDTW(traj{ii}, traj{jj});结束结束结束Allgestures .(gest) = traj;dist.(gest) = D + D.';渲染对称矩阵得到所有相互距离结束

集群和模板

下一步是为每个手势生成模板轨迹。结构经销包含给定手势的所有记录对之间的相互距离。在本节中,您将基于相互距离对给定手势的所有轨迹进行聚类。这个函数helperClusterWithSplitting使用中描述的集群分裂方法[2]所有的轨迹最初都放在一个集群中。如果聚类的半径(聚类中任意两个轨迹之间的最大距离)大于radiusLimit。

对于每个集群,拆分过程继续递归地进行。一旦为每个聚类找到一个中值,与该聚类相关的轨迹就会保存为该特定手势的模板。如果集群中的轨迹数与给定手势的轨迹总数之比小于clusterMinPct,该集群被丢弃。这可以防止异常值轨迹对分类过程产生负面影响。取决于选择radiusLimit而且clusterMinPct一个手势可能有一个或几个集群,因此可能有一个或几个模板。

radiusLimit = 60;clusterMinPct = 0.2;parforgg=1:Ngestures (gg);Dg = dist.(gest);% #好< * PFBNS >[gclusters, gtemplates] = helperClusterWithSplitting(Dg, radiusLimit);clusterSizes = cellfun(@ nummel, gclusters,“UniformOutput”,真正的);totalSize = sum(clusterSizes);clusterPct = clusterSizes./totalSize;validClusters = clusterPct >tidx = gtemplates(validClusters);TMPLT = allgestures.(gest)(tidx);templateTraj{gg} = tmplt;标签{gg} = repmat(gest, numel(tmplt),1);结束templates = table(vertcat(templateTraj{:}), vertcat(labels{:}));templates.Properties.VariableNames = [“定位”“姿态”];

模板变量存储为表格.中存储的模板轨迹取向变量和存储在手势变量。控件中的新手势将使用这组模板来识别testset。

分类系统

使用四元数动态时间翘曲,比较来自测试集的新手势数据,可以将每个手势模板进行比较。系统将新的未知手势归类为与未知手势具有最小四元数动态时间扭曲距离的模板类。如果到每个模板的距离超出radiusLimit,测试手势被标记为未被认可的

Ntest = size(测试集,1);Ntemplates = size(templates,1);testTraj = testset.Orientation;expected = testset.手势;实际=字符串(大小(预期));parforii=1:Ntest testdist = 0 (1,Ntemplates);tt=1:Ntemplates testdist(tt) = helperQDTW(testTraj{ii}, templates.Orientation{tt});结束[mind, mindidx] = min(testdist);如果mind > radiusLimit实际(ii) =“识别”其他的actual(ii) = templates.Gesture{mindidx};结束结束结果。(testPerson)。实际=实际的;结果。(testPerson)。预期的;结束

计算系统在测试集中识别手势的准确性,并生成混淆矩阵

页= 1:Npeople图;行为=结果(人(pp)).实际的;Exp =结果(人(pp)).预期;numCorrect = sum(act == exp);Ntest =数字(行为);精度= 100 * numCorrect./Ntest;confusionchart([经验;“识别”]、[行为;错过]);标题("测试对象= "+人(pp) +换行+"精确度= "+精度+“%”);结束snapnow;

MATLAB图

MATLAB图

MATLAB图

MATLAB图

四种测试对象配置的平均准确度均在90%以上。

AverageAccuracy =平均值(准确度)
平均准确率= 94

结论

通过融合IMU数据和imufilter对象,并使用四元数动态时间扭曲将手势轨迹与一组模板轨迹进行比较,您可以高精度地识别手势。您可以使用传感器融合以及四元数动态时间扭曲和聚类来构建有效的手势识别系统。

参考文献

[1] B. Jablonski,“四元数动态时间扭曲”,《IEEE信号处理汇刊》,第60卷,no. 1。2012年3月。

R. Srivastava和P. Sinha,“使用四元数动态时间翘曲技术的手部运动和手势表征”,在IEEE传感器杂志,第16卷,第1期。2016年3月1日。