如果给出一个触摸点列表,如何检测摇动手势?

时间:2017-05-10 06:44:46

标签: c++ algorithm c++11

从一组点中检测一个摇动手势,基本上是在寻找方向上的三个变化:

示例:(我们只需要查看x坐标,因为我们只查看水平抖动,而不是垂直抖动)

  

1,2,3,4,5,6,7,8,[9],8,7,[6],[7]

在上面的x-coords序列中,我用[]标记了方向的变化。

问题是,在上述情况下,我们甚至会发现微小的无意震动 - 例如,如果你要求一个人将手指从屏幕底部拖到顶部直线,他的手可能会移动一点点左右无意间,我们认为这是一个“摇晃”

示例:

  

1,2,[3],[2],[3] ....(无意的摇晃)

为了避免这种情况,我们需要某种阈值,只有在此之上,我们才将运动看作是一种震动。例如,方向变化之间的差距应至少为3分,值的差异应为至少4分。

所以我们应该有类似的东西:

  <1,2> 1,2,5,5,7,8,[9],8,7,6,[5],6,7,8,[9] .....检测到摇动< / p>      <1,2> 1,2,5,5,7,8,[9],8,7,6,6,7,8,9 .....忽略了摇动

     <1,2> 1,2,3,1 ....忽略了摇......

实施起来似乎很棘手,因为可能需要跟踪三个指数。而不是自己实现这个,我想知道这是一个已知的算法,我可以查找一个解决方案吗?

1 个答案:

答案 0 :(得分:3)

根据导数描述函数运动变化的事实,您可以使用导数来轻松解决问题。

enter image description here

我们来看第一个例子:

1, 2, 3, 4, 5, 6, 7, 8, [9], 8, 7, [6], [7] 

通过找到该序列的衍生物:

1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, 1
+  +  +  +  +  +  +  +   -   -   -  +

现在,很容易知道震动发生在哪里。

另一个例子:

 1, 12, 15, 8, 3, 1, 0, 5, 17, 30

一阶导数:

11, 3, -7, -5, -2, -1, 5, 12, 13
 +  +   -   -   -   -  +   +  +

简单实施(未经测试,未经优化):

template <typename valueType> // http://stackoverflow.com/a/67020/4523099
bool same_sign(typename valueType x, typename valueType y){
     return (x >= 0) ^ (y < 0);
}

template <typename T>
std::vector<T> get_derivative(std::vector<T> vec_x){
    for(size_t i=0;i<vec_x.size()-1;++i){
         vec_x[i]= vec_x[i+1]-vec_x[i];
    }
    vec_x.pop_back();
    return vec_x;
}

int main(){
    std::vector<int> x{1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 7, 6, 7 };
    auto first_derivative=get_derivative(x);
    std::vector<size_t> indices_of_shakes;
    for(size_t i=0;i<first_derivative.size()-1;++i){
        if(!same_sign(first_derivative[i],first_derivative[i+1])){
            indices_of_shakes.emplace_back(i);
        }

    } 
}