1 /*
2 * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "gesture_predictor.hpp"
18
19 #include "constants.hpp"
20
21 namespace {
22 /* State for the averaging algorithm we're using. */
23 float prediction_history[kGestureCount][kPredictionHistoryLength] = {};
24 int prediction_history_index = 0;
25 int prediction_suppression_count = 0;
26 } /* namespace */
27
28 /* Return the result of the last prediction
29 * 0: wing("W"), 1: ring("O"), 2: slope("angle"), 3: unknown
30 */
PredictGesture(float * output)31 int PredictGesture(float *output)
32 {
33 /* Record the latest predictions in our rolling history buffer. */
34 for (int i = 0; i < kGestureCount; ++i) {
35 prediction_history[i][prediction_history_index] = output[i];
36 }
37 /* Figure out which slot to put the next predictions into. */
38 ++prediction_history_index;
39 if (prediction_history_index >= kPredictionHistoryLength) {
40 prediction_history_index = 0;
41 }
42
43 /* Average the last n predictions for each gesture, and find which has the
44 * highest score.
45 */
46 int max_predict_index = -1;
47 float max_predict_score = 0.0f;
48 for (int i = 0; i < kGestureCount; i++) {
49 float prediction_sum = 0.0f;
50 for (int j = 0; j < kPredictionHistoryLength; ++j) {
51 prediction_sum += prediction_history[i][j];
52 }
53 const float prediction_average = prediction_sum / kPredictionHistoryLength;
54 if ((max_predict_index == -1) || (prediction_average > max_predict_score)) {
55 max_predict_index = i;
56 max_predict_score = prediction_average;
57 }
58 }
59
60 /* If there's been a recent prediction, don't trigger a new one too soon. */
61 if (prediction_suppression_count > 0) {
62 --prediction_suppression_count;
63 }
64 /* If we're predicting no gesture, or the average score is too low, or there's
65 * been a gesture recognised too recently, return no gesture.
66 */
67 if ((max_predict_index == kNoGesture) ||
68 (max_predict_score < kDetectionThreshold) ||
69 (prediction_suppression_count > 0)) {
70 return kNoGesture;
71 } else {
72 /* Reset the suppression counter so we don't come up with another prediction
73 * too soon.
74 */
75 prediction_suppression_count = kPredictionSuppressionDuration;
76 return max_predict_index;
77 }
78 }
79