From 5832259643549b4f5aea25923ecadc9795a5e936 Mon Sep 17 00:00:00 2001
From: David Rowe <david@ctrlaltstudio.com>
Date: Mon, 11 May 2015 16:41:43 -0700
Subject: [PATCH] Add preferences slider for webcam eyelid closing threshold

---
 interface/src/devices/DdeFaceTracker.cpp | 15 +++--
 interface/src/devices/DdeFaceTracker.h   |  8 ++-
 interface/src/ui/PreferencesDialog.cpp   |  9 +++
 interface/ui/preferencesDialog.ui        | 76 ++++++++++++++++++++++++
 4 files changed, 101 insertions(+), 7 deletions(-)

diff --git a/interface/src/devices/DdeFaceTracker.cpp b/interface/src/devices/DdeFaceTracker.cpp
index 4141f9fb82..31fb523933 100644
--- a/interface/src/devices/DdeFaceTracker.cpp
+++ b/interface/src/devices/DdeFaceTracker.cpp
@@ -137,7 +137,7 @@ struct Packet {
 };
 
 static const float STARTING_DDE_MESSAGE_TIME = 0.033f;
-
+static const float DEFAULT_DDE_EYE_CLOSING_THRESHOLD = 0.8f;
 static const int CALIBRATION_SAMPLES = 150;
 
 #ifdef WIN32
@@ -182,6 +182,7 @@ DdeFaceTracker::DdeFaceTracker(const QHostAddress& host, quint16 serverPort, qui
     _lastEyeBlinks(),
     _filteredEyeBlinks(),
     _lastEyeCoefficients(),
+    _eyeClosingThreshold("ddeEyeClosingThreshold", DEFAULT_DDE_EYE_CLOSING_THRESHOLD),
     _isCalibrating(false),
     _calibrationValues(),
     _calibrationCount(0),
@@ -464,12 +465,12 @@ void DdeFaceTracker::decodePacket(const QByteArray& buffer) {
 
                 // Change to closing or opening states
                 const float EYE_CONTROL_HYSTERISIS = 0.25f;
-                const float EYE_CLOSING_THRESHOLD = 0.8f;
-                const float EYE_OPENING_THRESHOLD = EYE_CONTROL_THRESHOLD - EYE_CONTROL_HYSTERISIS;
-                if ((_eyeStates[i] == EYE_OPEN || _eyeStates[i] == EYE_OPENING) && eyeCoefficients[i] > EYE_CLOSING_THRESHOLD) {
+                float eyeClosingThreshold = getEyeClosingThreshold();
+                float eyeOpeningThreshold = eyeClosingThreshold - EYE_CONTROL_HYSTERISIS;
+                if ((_eyeStates[i] == EYE_OPEN || _eyeStates[i] == EYE_OPENING) && eyeCoefficients[i] > eyeClosingThreshold) {
                     _eyeStates[i] = EYE_CLOSING;
                 } else if ((_eyeStates[i] == EYE_CLOSED || _eyeStates[i] == EYE_CLOSING)
-                    && eyeCoefficients[i] < EYE_OPENING_THRESHOLD) {
+                    && eyeCoefficients[i] < eyeOpeningThreshold) {
                     _eyeStates[i] = EYE_OPENING;
                 }
 
@@ -559,6 +560,10 @@ void DdeFaceTracker::decodePacket(const QByteArray& buffer) {
     }
 }
 
+void DdeFaceTracker::setEyeClosingThreshold(float eyeClosingThreshold) {
+    _eyeClosingThreshold.set(eyeClosingThreshold);
+}
+
 static const int CALIBRATION_BILLBOARD_WIDTH = 240;
 static const int CALIBRATION_BILLBOARD_HEIGHT = 180;
 static const int CALIBRATION_BILLBOARD_TOP_MARGIN = 60;
diff --git a/interface/src/devices/DdeFaceTracker.h b/interface/src/devices/DdeFaceTracker.h
index f627464c6f..8c30c5a4c3 100644
--- a/interface/src/devices/DdeFaceTracker.h
+++ b/interface/src/devices/DdeFaceTracker.h
@@ -50,6 +50,9 @@ public:
     float getMouthSmileLeft() const { return getBlendshapeCoefficient(_mouthSmileLeftIndex); }
     float getMouthSmileRight() const { return getBlendshapeCoefficient(_mouthSmileRightIndex); }
 
+    float getEyeClosingThreshold() { return _eyeClosingThreshold.get(); }
+    void setEyeClosingThreshold(float eyeClosingThreshold);
+
 public slots:
     void setEnabled(bool enabled);
     void calibrate();
@@ -89,8 +92,7 @@ private:
     int _rightBlinkIndex;
     int _leftEyeOpenIndex;
     int _rightEyeOpenIndex;
-    
-    // Brows
+
     int _browDownLeftIndex;
     int _browDownRightIndex;
     int _browUpCenterIndex;
@@ -124,6 +126,8 @@ private:
     float _lastEyeBlinks[2];
     float _filteredEyeBlinks[2];
     float _lastEyeCoefficients[2];
+    Setting::Handle<float> _eyeClosingThreshold;
+
     QVector<float> _coefficientAverages;
 
     bool _isCalibrating;
diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp
index 4622ffd7ed..febd6f90bf 100644
--- a/interface/src/ui/PreferencesDialog.cpp
+++ b/interface/src/ui/PreferencesDialog.cpp
@@ -14,6 +14,7 @@
 
 #include <AudioClient.h>
 #include <avatar/AvatarManager.h>
+#include <devices/DdeFaceTracker.h>
 #include <devices/Faceshift.h>
 #include <devices/SixenseManager.h>
 #include <NetworkingConstants.h>
@@ -135,6 +136,10 @@ void PreferencesDialog::loadPreferences() {
     ui.pupilDilationSlider->setValue(myAvatar->getHead()->getPupilDilation() *
                                      ui.pupilDilationSlider->maximum());
     
+    auto dde = DependencyManager::get<DdeFaceTracker>();
+    ui.ddeEyeClosingThresholdSlider->setValue(dde->getEyeClosingThreshold() * 
+                                              ui.ddeEyeClosingThresholdSlider->maximum());
+
     auto faceshift = DependencyManager::get<Faceshift>();
     ui.faceshiftEyeDeflectionSider->setValue(faceshift->getEyeDeflection() *
                                              ui.faceshiftEyeDeflectionSider->maximum());
@@ -222,6 +227,10 @@ void PreferencesDialog::savePreferences() {
     
     qApp->setFieldOfView(ui.fieldOfViewSpin->value());
     
+    auto dde = DependencyManager::get<DdeFaceTracker>();
+    dde->setEyeClosingThreshold(ui.ddeEyeClosingThresholdSlider->value() / 
+                                (float)ui.ddeEyeClosingThresholdSlider->maximum());
+
     auto faceshift = DependencyManager::get<Faceshift>();
     faceshift->setEyeDeflection(ui.faceshiftEyeDeflectionSider->value() /
                                 (float)ui.faceshiftEyeDeflectionSider->maximum());
diff --git a/interface/ui/preferencesDialog.ui b/interface/ui/preferencesDialog.ui
index d26bdaee8a..a949b42684 100644
--- a/interface/ui/preferencesDialog.ui
+++ b/interface/ui/preferencesDialog.ui
@@ -1310,6 +1310,82 @@
          </item>
         </layout>
        </item>
+       <item>
+        <layout class="QHBoxLayout" name="horizontalLayout_28">
+         <property name="spacing">
+          <number>0</number>
+         </property>
+         <property name="topMargin">
+          <number>7</number>
+         </property>
+         <property name="rightMargin">
+          <number>0</number>
+         </property>
+         <property name="bottomMargin">
+          <number>7</number>
+         </property>
+         <item alignment="Qt::AlignLeft">
+          <widget class="QLabel" name="label_7">
+           <property name="font">
+            <font>
+             <family>Arial</family>
+            </font>
+           </property>
+           <property name="text">
+            <string>Camera eye closing threshold</string>
+           </property>
+           <property name="indent">
+            <number>0</number>
+           </property>
+           <property name="buddy">
+            <cstring>ddeEyeClosingThresholdSlider</cstring>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <spacer name="horizontalSpacer_8">
+           <property name="font">
+            <font>
+             <family>Arial</family>
+            </font>
+           </property>
+           <property name="orientation">
+            <enum>Qt::Horizontal</enum>
+           </property>
+           <property name="sizeHint" stdset="0">
+            <size>
+             <width>40</width>
+             <height>20</height>
+            </size>
+           </property>
+          </spacer>
+         </item>
+         <item>
+          <widget class="QSlider" name="ddeEyeClosingThresholdSlider">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="minimumSize">
+            <size>
+             <width>130</width>
+             <height>0</height>
+            </size>
+           </property>
+           <property name="font">
+            <font>
+             <family>Arial</family>
+            </font>
+           </property>
+           <property name="orientation">
+            <enum>Qt::Horizontal</enum>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </item>
        <item>
         <layout class="QHBoxLayout" name="horizontalLayout_6">
          <property name="spacing">