diff options
| -rw-r--r-- | options/tie.cpp | 7 | ||||
| -rw-r--r-- | options/tie.hpp | 2 | ||||
| -rw-r--r-- | tracker-easy/lang/nl_NL.ts | 98 | ||||
| -rw-r--r-- | tracker-easy/lang/ru_RU.ts | 143 | ||||
| -rw-r--r-- | tracker-easy/lang/stub.ts | 98 | ||||
| -rw-r--r-- | tracker-easy/lang/zh_CN.ts | 138 | ||||
| -rw-r--r-- | tracker-easy/module.cpp | 3 | ||||
| -rw-r--r-- | tracker-easy/point-extractor.cpp | 23 | ||||
| -rw-r--r-- | tracker-easy/point-extractor.h | 15 | ||||
| -rw-r--r-- | tracker-easy/preview.cpp | 10 | ||||
| -rw-r--r-- | tracker-easy/preview.h | 2 | ||||
| -rw-r--r-- | tracker-easy/settings.h | 30 | ||||
| -rw-r--r-- | tracker-easy/tracker-easy-dialog.cpp | 164 | ||||
| -rw-r--r-- | tracker-easy/tracker-easy-dialog.h | 9 | ||||
| -rw-r--r-- | tracker-easy/tracker-easy-settings.ui | 1261 | ||||
| -rw-r--r-- | tracker-easy/tracker-easy.cpp | 599 | ||||
| -rw-r--r-- | tracker-easy/tracker-easy.h | 38 | 
17 files changed, 1199 insertions, 1441 deletions
| diff --git a/options/tie.cpp b/options/tie.cpp index 671a72c2..8220854d 100644 --- a/options/tie.cpp +++ b/options/tie.cpp @@ -72,6 +72,13 @@ void tie_setting(value<QVariant>& v, QComboBox* cb)  // XXX TODO need variant with setEnabled based on lambda retval -- sh 20170524 +void tie_setting(value<bool>& v, QRadioButton* cb) +{ +    cb->setChecked(v); +    value_::connect(cb, SIGNAL(toggled(bool)), &v, SLOT(setValue(bool)), v.DIRECT_CONNTYPE); +    value_::connect(&v, SIGNAL(valueChanged(bool)), cb, SLOT(setChecked(bool)), v.SAFE_CONNTYPE); +} +  void tie_setting(value<bool>& v, QCheckBox* cb)  {      cb->setChecked(v); diff --git a/options/tie.hpp b/options/tie.hpp index c2607a6c..2ac27d64 100644 --- a/options/tie.hpp +++ b/options/tie.hpp @@ -20,6 +20,7 @@  #include <QLineEdit>  #include <QLabel>  #include <QTabWidget> +#include <QRadioButton>  #include <cmath> @@ -97,6 +98,7 @@ OTR_OPTIONS_EXPORT void tie_setting(value<int>& v, QComboBox* cb);  OTR_OPTIONS_EXPORT void tie_setting(value<QString>& v, QComboBox* cb);  OTR_OPTIONS_EXPORT void tie_setting(value<QVariant>& v, QComboBox* cb);  OTR_OPTIONS_EXPORT void tie_setting(value<bool>& v, QCheckBox* cb); +OTR_OPTIONS_EXPORT void tie_setting(value<bool>& v, QRadioButton* cb);  OTR_OPTIONS_EXPORT void tie_setting(value<double>& v, QDoubleSpinBox* dsb);  OTR_OPTIONS_EXPORT void tie_setting(value<int>& v, QSpinBox* sb);  OTR_OPTIONS_EXPORT void tie_setting(value<QString>& v, QLineEdit* le); diff --git a/tracker-easy/lang/nl_NL.ts b/tracker-easy/lang/nl_NL.ts index 22a99106..9c4e1843 100644 --- a/tracker-easy/lang/nl_NL.ts +++ b/tracker-easy/lang/nl_NL.ts @@ -2,36 +2,9 @@  <!DOCTYPE TS>  <TS version="2.1" language="nl_NL">  <context> -    <name>EasyTracker::Dialog</name> -    <message> -        <source>%1 yaw samples. Yaw more to %2 samples for stable calibration.</source> -        <translation type="unfinished"></translation> -    </message> -    <message> -        <source>%1 pitch samples. Pitch more to %2 samples for stable calibration.</source> -        <translation type="unfinished"></translation> -    </message> -    <message> -        <source>%1 samples. Over %2, good!</source> -        <translation type="unfinished"></translation> -    </message> -    <message> -        <source>Stop calibration</source> -        <translation type="unfinished"></translation> -    </message> -    <message> -        <source>Start calibration</source> -        <translation type="unfinished"></translation> -    </message> -    <message> -        <source>Tracker offline</source> -        <translation type="unfinished"></translation> -    </message> -</context> -<context>      <name>EasyTracker::Metadata</name>      <message> -        <source>Easy Tracker 0.1</source> +        <source>Easy Tracker 1.0</source>          <translation type="unfinished"></translation>      </message>  </context> @@ -118,140 +91,139 @@          <translation type="unfinished"></translation>      </message>      <message> -        <source>Clip</source> +        <source> mm</source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>Model Dimensions</source> +        <source>About</source>          <translation type="unfinished"></translation>      </message>      <message> -        <source> mm</source> +        <source>Debug (full size preview)</source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>Side</source> +        <source>Deadzone</source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>Front</source> +        <source>Size in pixels of half the edge defining deadzone squares around tracked points</source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>Cap</source> +        <source>Perspective-N-Point solver</source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>Custom</source> +        <source>Make sure you pick a solver supporting the number of marker you are using. For three points detection use either P3P or AP3P.</source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>z:</source> +        <source>P3P</source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>x:</source> +        <source>ITERATIVE</source>          <translation type="unfinished"></translation>      </message>      <message> -        <source><html><head/><body><p>Location of the two remaining model points<br/>with respect to the reference point in default pose</p><p>Use any units you want, not necessarily centimeters.</p></body></html></source> +        <source>EPNP</source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>y:</source> +        <source>DLS</source>          <translation type="unfinished"></translation>      </message>      <message> -        <source><html><head/><body><p><span style=" font-size:16pt;">P</span><span style=" font-size:16pt; vertical-align:sub;">3</span></p></body></html></source> +        <source>UPNP</source>          <translation type="unfinished"></translation>      </message>      <message> -        <source><html><head/><body><p><span style=" font-size:16pt;">P</span><span style=" font-size:16pt; vertical-align:sub;">2</span></p></body></html></source> +        <source>AP3P</source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>Model position</source> +        <source>Tracker</source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>Use only yaw and pitch while calibrating. -Don't roll or change position.</source> +        <source>Settings</source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>Start calibration</source> +        <source>Top Right</source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>About</source> +        <source>Top</source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>Status</source> +        <source>Top Left</source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>Extracted Points:</source> +        <source>Left</source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>Camera Info:</source> +        <source>Vertex count</source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>Debug (full size preview)</source> +        <source>Three vertices</source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>Deadzone</source> +        <source>Four vertices</source>          <translation type="unfinished"></translation>      </message>      <message> -        <source><html><head/><body><p><span style=" font-weight:600;">Easy Tracker<br/>Version 0.1</span></p><p><span style=" font-weight:600;">by Stéphane Lenclud</span></p><p>See  <a href="https://github.com/opentrack/opentrack/wiki/Easy-Tracker"><span style=" font-weight:600; text-decoration: underline; color:#9999AA;">documentation on GitHub</span></a></p></body></html></source> +        <source>Five vertices</source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>Size in pixels of half the edge defining deadzone squares around tracked points</source> +        <source>Center</source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>Perspective-N-Point solver</source> +        <source>Right</source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>Make sure you pick a solver supporting the number of marker you are using. For three points detection use either P3P or AP3P.</source> +        <source><html><head/><body><p><span style=" font-size:12pt;">X</span></p></body></html></source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>P3P</source> +        <source><html><head/><body><p><span style=" font-size:12pt;">Y</span></p></body></html></source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>ITERATIVE</source> +        <source><html><head/><body><p><span style=" font-size:12pt;">Z</span></p></body></html></source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>EPNP</source> +        <source><html><head/><body><p><span style=" font-weight:600;">Easy Tracker<br/>Version 1.0</span></p><p><span style=" font-weight:600;">by Stéphane Lenclud</span></p><p>See <a href="https://github.com/opentrack/opentrack/wiki/Easy-Tracker"><span style=" font-weight:600; text-decoration: underline; color:#9999aa;">documentation on GitHub</span></a></p></body></html></source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>DLS</source> +        <source>Auto center</source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>UPNP</source> +        <source><html><head/><body><p>Use P3P or AP3P for three and four points setup. Use EPNP or ITERATIVE for five points setup. Inconsistent configuration will result in undefined behavior.</p></body></html></source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>AP3P</source> +        <source>Auto center timeout</source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>Tracker</source> +        <source>If no valid pose can be determined after that much time the center pose will be used.</source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>Settings</source> +        <source> ms</source>          <translation type="unfinished"></translation>      </message>  </context> diff --git a/tracker-easy/lang/ru_RU.ts b/tracker-easy/lang/ru_RU.ts index d45c89d1..6499415f 100644 --- a/tracker-easy/lang/ru_RU.ts +++ b/tracker-easy/lang/ru_RU.ts @@ -2,36 +2,9 @@  <!DOCTYPE TS>  <TS version="2.1" language="ru_RU">  <context> -    <name>EasyTracker::Dialog</name> -    <message> -        <source>%1 yaw samples. Yaw more to %2 samples for stable calibration.</source> -        <translation type="unfinished">По оси YAW выполнено: %1 замер(а/ов). Для стабильного результата необходимо не меньше %2</translation> -    </message> -    <message> -        <source>%1 pitch samples. Pitch more to %2 samples for stable calibration.</source> -        <translation type="unfinished">По оси Pitch выполнено: %1 замер(а/ов). Для стабильного результата необходимо не меньше %2</translation> -    </message> -    <message> -        <source>%1 samples. Over %2, good!</source> -        <translation type="unfinished">Получено %1 образца(-ов). Больше %2, отлично!!</translation> -    </message> -    <message> -        <source>Stop calibration</source> -        <translation type="unfinished">Остановить калибровку</translation> -    </message> -    <message> -        <source>Start calibration</source> -        <translation type="unfinished">Начать калибровку</translation> -    </message> -    <message> -        <source>Tracker offline</source> -        <translation type="unfinished">Отслеживание отключено</translation> -    </message> -</context> -<context>      <name>EasyTracker::Metadata</name>      <message> -        <source>Easy Tracker 0.1</source> +        <source>Easy Tracker 1.0</source>          <translation type="unfinished"></translation>      </message>  </context> @@ -118,145 +91,139 @@          <translation>Модель</translation>      </message>      <message> -        <source>Clip</source> -        <translation>Клипса</translation> +        <source> mm</source> +        <translation> мм</translation>      </message>      <message> -        <source>Model Dimensions</source> -        <translation>Размеры модели</translation> +        <source>About</source> +        <translation>О программе</translation>      </message>      <message> -        <source> mm</source> -        <translation> мм</translation> +        <source>Debug (full size preview)</source> +        <translation type="unfinished"></translation>      </message>      <message> -        <source>Side</source> -        <translation>Сбоку</translation> +        <source>Deadzone</source> +        <translation type="unfinished"></translation>      </message>      <message> -        <source>Front</source> -        <translation>Спереди</translation> +        <source>Size in pixels of half the edge defining deadzone squares around tracked points</source> +        <translation type="unfinished"></translation>      </message>      <message> -        <source>Cap</source> -        <translation>Кепка</translation> +        <source>Perspective-N-Point solver</source> +        <translation type="unfinished"></translation>      </message>      <message> -        <source>Custom</source> -        <translation>Свой</translation> +        <source>Make sure you pick a solver supporting the number of marker you are using. For three points detection use either P3P or AP3P.</source> +        <translation type="unfinished"></translation>      </message>      <message> -        <source>z:</source> -        <translation></translation> +        <source>P3P</source> +        <translation type="unfinished"></translation>      </message>      <message> -        <source>x:</source> -        <translation></translation> +        <source>ITERATIVE</source> +        <translation type="unfinished"></translation>      </message>      <message> -        <source><html><head/><body><p>Location of the two remaining model points<br/>with respect to the reference point in default pose</p><p>Use any units you want, not necessarily centimeters.</p></body></html></source> -        <translatorcomment>Расположение двух оставшихся точек модели относительно опорной точки в стандартной позе. Возможно исп-ть любые единицы измерения, не обязательно сантиметры.</translatorcomment> -        <translation><html><head/><body><p> Расположение двух оставшихся точек модели<br/>относительно опорной точки в стандартной позе. </p><p>Возможно использовать любые единицы измерения.</p></body></html</translation> +        <source>EPNP</source> +        <translation type="unfinished"></translation>      </message>      <message> -        <source>y:</source> -        <translation></translation> +        <source>DLS</source> +        <translation type="unfinished"></translation>      </message>      <message> -        <source><html><head/><body><p><span style=" font-size:16pt;">P</span><span style=" font-size:16pt; vertical-align:sub;">3</span></p></body></html></source> -        <translation></translation> +        <source>UPNP</source> +        <translation type="unfinished"></translation>      </message>      <message> -        <source><html><head/><body><p><span style=" font-size:16pt;">P</span><span style=" font-size:16pt; vertical-align:sub;">2</span></p></body></html></source> -        <translation></translation> +        <source>AP3P</source> +        <translation type="unfinished"></translation>      </message>      <message> -        <source>Model position</source> -        <translation>Положение модели</translation> +        <source>Tracker</source> +        <translation type="unfinished"></translation>      </message>      <message> -        <source>Use only yaw and pitch while calibrating. -Don't roll or change position.</source> -        <translation>Во время калибровки -используйте только оси  -YAW и PITCH. -Не используйте оси  -ROLL или X/Y-смещения.</translation> +        <source>Settings</source> +        <translation type="unfinished"></translation>      </message>      <message> -        <source>Start calibration</source> -        <translation>Начать калибровку</translation> +        <source>Top Right</source> +        <translation type="unfinished"></translation>      </message>      <message> -        <source>About</source> -        <translation>О программе</translation> +        <source>Top</source> +        <translation type="unfinished"></translation>      </message>      <message> -        <source>Status</source> -        <translation>Статус</translation> +        <source>Top Left</source> +        <translation type="unfinished"></translation>      </message>      <message> -        <source>Extracted Points:</source> -        <translation>Извлечено точек:</translation> +        <source>Left</source> +        <translation type="unfinished"></translation>      </message>      <message> -        <source>Camera Info:</source> -        <translation>Параметры камеры:</translation> +        <source>Vertex count</source> +        <translation type="unfinished"></translation>      </message>      <message> -        <source>Debug (full size preview)</source> +        <source>Three vertices</source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>Deadzone</source> +        <source>Four vertices</source>          <translation type="unfinished"></translation>      </message>      <message> -        <source><html><head/><body><p><span style=" font-weight:600;">Easy Tracker<br/>Version 0.1</span></p><p><span style=" font-weight:600;">by Stéphane Lenclud</span></p><p>See  <a href="https://github.com/opentrack/opentrack/wiki/Easy-Tracker"><span style=" font-weight:600; text-decoration: underline; color:#9999AA;">documentation on GitHub</span></a></p></body></html></source> +        <source>Five vertices</source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>Size in pixels of half the edge defining deadzone squares around tracked points</source> +        <source>Center</source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>Perspective-N-Point solver</source> +        <source>Right</source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>Make sure you pick a solver supporting the number of marker you are using. For three points detection use either P3P or AP3P.</source> +        <source><html><head/><body><p><span style=" font-size:12pt;">X</span></p></body></html></source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>P3P</source> +        <source><html><head/><body><p><span style=" font-size:12pt;">Y</span></p></body></html></source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>ITERATIVE</source> +        <source><html><head/><body><p><span style=" font-size:12pt;">Z</span></p></body></html></source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>EPNP</source> +        <source><html><head/><body><p><span style=" font-weight:600;">Easy Tracker<br/>Version 1.0</span></p><p><span style=" font-weight:600;">by Stéphane Lenclud</span></p><p>See <a href="https://github.com/opentrack/opentrack/wiki/Easy-Tracker"><span style=" font-weight:600; text-decoration: underline; color:#9999aa;">documentation on GitHub</span></a></p></body></html></source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>DLS</source> +        <source>Auto center</source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>UPNP</source> +        <source><html><head/><body><p>Use P3P or AP3P for three and four points setup. Use EPNP or ITERATIVE for five points setup. Inconsistent configuration will result in undefined behavior.</p></body></html></source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>AP3P</source> +        <source>Auto center timeout</source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>Tracker</source> +        <source>If no valid pose can be determined after that much time the center pose will be used.</source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>Settings</source> +        <source> ms</source>          <translation type="unfinished"></translation>      </message>  </context> diff --git a/tracker-easy/lang/stub.ts b/tracker-easy/lang/stub.ts index 1b58a8f4..7b6facec 100644 --- a/tracker-easy/lang/stub.ts +++ b/tracker-easy/lang/stub.ts @@ -2,36 +2,9 @@  <!DOCTYPE TS>  <TS version="2.1">  <context> -    <name>EasyTracker::Dialog</name> -    <message> -        <source>%1 yaw samples. Yaw more to %2 samples for stable calibration.</source> -        <translation type="unfinished"></translation> -    </message> -    <message> -        <source>%1 pitch samples. Pitch more to %2 samples for stable calibration.</source> -        <translation type="unfinished"></translation> -    </message> -    <message> -        <source>%1 samples. Over %2, good!</source> -        <translation type="unfinished"></translation> -    </message> -    <message> -        <source>Stop calibration</source> -        <translation type="unfinished"></translation> -    </message> -    <message> -        <source>Start calibration</source> -        <translation type="unfinished"></translation> -    </message> -    <message> -        <source>Tracker offline</source> -        <translation type="unfinished"></translation> -    </message> -</context> -<context>      <name>EasyTracker::Metadata</name>      <message> -        <source>Easy Tracker 0.1</source> +        <source>Easy Tracker 1.0</source>          <translation type="unfinished"></translation>      </message>  </context> @@ -118,140 +91,139 @@          <translation type="unfinished"></translation>      </message>      <message> -        <source>Clip</source> +        <source> mm</source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>Model Dimensions</source> +        <source>About</source>          <translation type="unfinished"></translation>      </message>      <message> -        <source> mm</source> +        <source>Debug (full size preview)</source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>Side</source> +        <source>Deadzone</source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>Front</source> +        <source>Size in pixels of half the edge defining deadzone squares around tracked points</source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>Cap</source> +        <source>Perspective-N-Point solver</source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>Custom</source> +        <source>Make sure you pick a solver supporting the number of marker you are using. For three points detection use either P3P or AP3P.</source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>z:</source> +        <source>P3P</source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>x:</source> +        <source>ITERATIVE</source>          <translation type="unfinished"></translation>      </message>      <message> -        <source><html><head/><body><p>Location of the two remaining model points<br/>with respect to the reference point in default pose</p><p>Use any units you want, not necessarily centimeters.</p></body></html></source> +        <source>EPNP</source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>y:</source> +        <source>DLS</source>          <translation type="unfinished"></translation>      </message>      <message> -        <source><html><head/><body><p><span style=" font-size:16pt;">P</span><span style=" font-size:16pt; vertical-align:sub;">3</span></p></body></html></source> +        <source>UPNP</source>          <translation type="unfinished"></translation>      </message>      <message> -        <source><html><head/><body><p><span style=" font-size:16pt;">P</span><span style=" font-size:16pt; vertical-align:sub;">2</span></p></body></html></source> +        <source>AP3P</source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>Model position</source> +        <source>Tracker</source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>Use only yaw and pitch while calibrating. -Don't roll or change position.</source> +        <source>Settings</source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>Start calibration</source> +        <source>Top Right</source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>About</source> +        <source>Top</source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>Status</source> +        <source>Top Left</source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>Extracted Points:</source> +        <source>Left</source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>Camera Info:</source> +        <source>Vertex count</source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>Debug (full size preview)</source> +        <source>Three vertices</source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>Deadzone</source> +        <source>Four vertices</source>          <translation type="unfinished"></translation>      </message>      <message> -        <source><html><head/><body><p><span style=" font-weight:600;">Easy Tracker<br/>Version 0.1</span></p><p><span style=" font-weight:600;">by Stéphane Lenclud</span></p><p>See  <a href="https://github.com/opentrack/opentrack/wiki/Easy-Tracker"><span style=" font-weight:600; text-decoration: underline; color:#9999AA;">documentation on GitHub</span></a></p></body></html></source> +        <source>Five vertices</source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>Size in pixels of half the edge defining deadzone squares around tracked points</source> +        <source>Center</source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>Perspective-N-Point solver</source> +        <source>Right</source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>Make sure you pick a solver supporting the number of marker you are using. For three points detection use either P3P or AP3P.</source> +        <source><html><head/><body><p><span style=" font-size:12pt;">X</span></p></body></html></source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>P3P</source> +        <source><html><head/><body><p><span style=" font-size:12pt;">Y</span></p></body></html></source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>ITERATIVE</source> +        <source><html><head/><body><p><span style=" font-size:12pt;">Z</span></p></body></html></source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>EPNP</source> +        <source><html><head/><body><p><span style=" font-weight:600;">Easy Tracker<br/>Version 1.0</span></p><p><span style=" font-weight:600;">by Stéphane Lenclud</span></p><p>See <a href="https://github.com/opentrack/opentrack/wiki/Easy-Tracker"><span style=" font-weight:600; text-decoration: underline; color:#9999aa;">documentation on GitHub</span></a></p></body></html></source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>DLS</source> +        <source>Auto center</source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>UPNP</source> +        <source><html><head/><body><p>Use P3P or AP3P for three and four points setup. Use EPNP or ITERATIVE for five points setup. Inconsistent configuration will result in undefined behavior.</p></body></html></source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>AP3P</source> +        <source>Auto center timeout</source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>Tracker</source> +        <source>If no valid pose can be determined after that much time the center pose will be used.</source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>Settings</source> +        <source> ms</source>          <translation type="unfinished"></translation>      </message>  </context> diff --git a/tracker-easy/lang/zh_CN.ts b/tracker-easy/lang/zh_CN.ts index d524aaed..bbd8aff1 100644 --- a/tracker-easy/lang/zh_CN.ts +++ b/tracker-easy/lang/zh_CN.ts @@ -2,36 +2,9 @@  <!DOCTYPE TS>  <TS version="2.1" language="zh_CN">  <context> -    <name>EasyTracker::Dialog</name> -    <message> -        <source>%1 yaw samples. Yaw more to %2 samples for stable calibration.</source> -        <translation type="unfinished"></translation> -    </message> -    <message> -        <source>%1 pitch samples. Pitch more to %2 samples for stable calibration.</source> -        <translation type="unfinished"></translation> -    </message> -    <message> -        <source>%1 samples. Over %2, good!</source> -        <translation type="unfinished">%1 样本。%2 正常</translation> -    </message> -    <message> -        <source>Stop calibration</source> -        <translation type="unfinished">停止校准</translation> -    </message> -    <message> -        <source>Start calibration</source> -        <translation type="unfinished">开始校准</translation> -    </message> -    <message> -        <source>Tracker offline</source> -        <translation type="unfinished">跟踪器脱机</translation> -    </message> -</context> -<context>      <name>EasyTracker::Metadata</name>      <message> -        <source>Easy Tracker 0.1</source> +        <source>Easy Tracker 1.0</source>          <translation type="unfinished"></translation>      </message>  </context> @@ -118,140 +91,139 @@          <translation>点模式</translation>      </message>      <message> -        <source>Clip</source> -        <translation>夹子式</translation> +        <source> mm</source> +        <translation> 毫米</translation>      </message>      <message> -        <source>Model Dimensions</source> -        <translation>尺寸</translation> +        <source>About</source> +        <translation>关于</translation>      </message>      <message> -        <source> mm</source> -        <translation> 毫米</translation> +        <source>Debug (full size preview)</source> +        <translation type="unfinished"></translation>      </message>      <message> -        <source>Side</source> -        <translation>侧面</translation> +        <source>Deadzone</source> +        <translation type="unfinished"></translation>      </message>      <message> -        <source>Front</source> -        <translation>正面</translation> +        <source>Size in pixels of half the edge defining deadzone squares around tracked points</source> +        <translation type="unfinished"></translation>      </message>      <message> -        <source>Cap</source> -        <translation>帽子式</translation> +        <source>Perspective-N-Point solver</source> +        <translation type="unfinished"></translation>      </message>      <message> -        <source>Custom</source> -        <translation>自定义模式</translation> +        <source>Make sure you pick a solver supporting the number of marker you are using. For three points detection use either P3P or AP3P.</source> +        <translation type="unfinished"></translation>      </message>      <message> -        <source>z:</source> -        <translation>Z:</translation> +        <source>P3P</source> +        <translation type="unfinished"></translation>      </message>      <message> -        <source>x:</source> -        <translation>X:</translation> +        <source>ITERATIVE</source> +        <translation type="unfinished"></translation>      </message>      <message> -        <source><html><head/><body><p>Location of the two remaining model points<br/>with respect to the reference point in default pose</p><p>Use any units you want, not necessarily centimeters.</p></body></html></source> -        <translation><html><head/><body><p>三点中的两点位置是相对第一个点的</p><p>单位不一定要用厘米</p></body></html></translation> +        <source>EPNP</source> +        <translation type="unfinished"></translation>      </message>      <message> -        <source>y:</source> -        <translation>Y:</translation> +        <source>DLS</source> +        <translation type="unfinished"></translation>      </message>      <message> -        <source><html><head/><body><p><span style=" font-size:16pt;">P</span><span style=" font-size:16pt; vertical-align:sub;">3</span></p></body></html></source> -        <translation><html><head/><body><p><span style=" font-size:16pt;">P</span><span style=" font-size:16pt; vertical-align:sub;">3</span></p></body></html></translation> +        <source>UPNP</source> +        <translation type="unfinished"></translation>      </message>      <message> -        <source><html><head/><body><p><span style=" font-size:16pt;">P</span><span style=" font-size:16pt; vertical-align:sub;">2</span></p></body></html></source> -        <translation><html><head/><body><p><span style=" font-size:16pt;">P</span><span style=" font-size:16pt; vertical-align:sub;">2</span></p></body></html></translation> +        <source>AP3P</source> +        <translation type="unfinished"></translation>      </message>      <message> -        <source>Model position</source> -        <translation>姿态空间位置</translation> +        <source>Tracker</source> +        <translation type="unfinished"></translation>      </message>      <message> -        <source>Start calibration</source> -        <translation>开始校准</translation> +        <source>Settings</source> +        <translation type="unfinished"></translation>      </message>      <message> -        <source>About</source> -        <translation>关于</translation> +        <source>Top Right</source> +        <translation type="unfinished"></translation>      </message>      <message> -        <source>Status</source> -        <translation>状态</translation> +        <source>Top</source> +        <translation type="unfinished"></translation>      </message>      <message> -        <source>Extracted Points:</source> -        <translation>解析出的点:</translation> +        <source>Top Left</source> +        <translation type="unfinished"></translation>      </message>      <message> -        <source>Camera Info:</source> -        <translation>设备信息:</translation> +        <source>Left</source> +        <translation type="unfinished"></translation>      </message>      <message> -        <source>Use only yaw and pitch while calibrating. -Don't roll or change position.</source> -        <translation>用pitch和yaw校准。不要roll或者变换位置</translation> +        <source>Vertex count</source> +        <translation type="unfinished"></translation>      </message>      <message> -        <source>Debug (full size preview)</source> +        <source>Three vertices</source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>Deadzone</source> +        <source>Four vertices</source>          <translation type="unfinished"></translation>      </message>      <message> -        <source><html><head/><body><p><span style=" font-weight:600;">Easy Tracker<br/>Version 0.1</span></p><p><span style=" font-weight:600;">by Stéphane Lenclud</span></p><p>See  <a href="https://github.com/opentrack/opentrack/wiki/Easy-Tracker"><span style=" font-weight:600; text-decoration: underline; color:#9999AA;">documentation on GitHub</span></a></p></body></html></source> +        <source>Five vertices</source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>Size in pixels of half the edge defining deadzone squares around tracked points</source> +        <source>Center</source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>Perspective-N-Point solver</source> +        <source>Right</source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>Make sure you pick a solver supporting the number of marker you are using. For three points detection use either P3P or AP3P.</source> +        <source><html><head/><body><p><span style=" font-size:12pt;">X</span></p></body></html></source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>P3P</source> +        <source><html><head/><body><p><span style=" font-size:12pt;">Y</span></p></body></html></source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>ITERATIVE</source> +        <source><html><head/><body><p><span style=" font-size:12pt;">Z</span></p></body></html></source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>EPNP</source> +        <source><html><head/><body><p><span style=" font-weight:600;">Easy Tracker<br/>Version 1.0</span></p><p><span style=" font-weight:600;">by Stéphane Lenclud</span></p><p>See <a href="https://github.com/opentrack/opentrack/wiki/Easy-Tracker"><span style=" font-weight:600; text-decoration: underline; color:#9999aa;">documentation on GitHub</span></a></p></body></html></source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>DLS</source> +        <source>Auto center</source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>UPNP</source> +        <source><html><head/><body><p>Use P3P or AP3P for three and four points setup. Use EPNP or ITERATIVE for five points setup. Inconsistent configuration will result in undefined behavior.</p></body></html></source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>AP3P</source> +        <source>Auto center timeout</source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>Tracker</source> +        <source>If no valid pose can be determined after that much time the center pose will be used.</source>          <translation type="unfinished"></translation>      </message>      <message> -        <source>Settings</source> +        <source> ms</source>          <translation type="unfinished"></translation>      </message>  </context> diff --git a/tracker-easy/module.cpp b/tracker-easy/module.cpp index 9f5461d5..3a9df22b 100644 --- a/tracker-easy/module.cpp +++ b/tracker-easy/module.cpp @@ -6,8 +6,7 @@  namespace EasyTracker  { - -    QString Metadata::name() { return tr("Easy Tracker 0.1"); } +    QString Metadata::name() { return tr("Easy Tracker 1.0"); }      QIcon Metadata::icon() { return QIcon(":/Resources/easy-tracker-logo.png"); }  } diff --git a/tracker-easy/point-extractor.cpp b/tracker-easy/point-extractor.cpp index f17fcde6..4b54fd25 100644 --- a/tracker-easy/point-extractor.cpp +++ b/tracker-easy/point-extractor.cpp @@ -29,13 +29,20 @@ using namespace numeric_types;  namespace EasyTracker  { -    PointExtractor::PointExtractor() : s(KModuleName) +    PointExtractor::PointExtractor() : iSettings(KModuleName)      { -     +        UpdateSettings();      } +    /// +    void PointExtractor::UpdateSettings() +    { +        iMinPointSize = iSettings.iMinBlobSize; +        iMaxPointSize = iSettings.iMaxBlobSize; +    } -    void PointExtractor::ExtractPoints(const cv::Mat& aFrame, cv::Mat* aPreview, std::vector<cv::Point>& aPoints) +    /// +    void PointExtractor::ExtractPoints(const cv::Mat& aFrame, cv::Mat* aPreview, int aNeededPointCount, std::vector<cv::Point>& aPoints)      {          //TODO: Assert if channel size is neither one nor two          // Make sure our frame channel is 8 bit @@ -108,10 +115,10 @@ namespace EasyTracker              bBox = cv::boundingRect(iContours[i]);              // Make sure bounding box matches our criteria -            if (bBox.width >= s.min_point_size -                && bBox.height >= s.min_point_size -                && bBox.width <= s.max_point_size -                && bBox.height <= s.max_point_size) +            if (bBox.width >= iMinPointSize +                && bBox.height >= iMinPointSize +                && bBox.width <= iMaxPointSize +                && bBox.height <= iMaxPointSize)              {                  // Do a mean shift or cam shift, it's not bringing much though                  //cv::CamShift(iFrameGray, bBox, cv::TermCriteria(cv::TermCriteria::EPS + cv::TermCriteria::MAX_ITER, 10, 1)); @@ -133,7 +140,7 @@ namespace EasyTracker          // Typically noise comming from zippers and metal parts on your clothing.          // With a cap tracker it also successfully discards noise from glasses.          // However it may not work as good with a clip user wearing glasses. -        while (aPoints.size() > KPointCount) // Until we have no more than three points +        while (aPoints.size() > aNeededPointCount) // Until we have no more than three points          {              int maxY = 0;              unsigned index = (unsigned)-1; diff --git a/tracker-easy/point-extractor.h b/tracker-easy/point-extractor.h index 3c65b193..f275769d 100644 --- a/tracker-easy/point-extractor.h +++ b/tracker-easy/point-extractor.h @@ -17,19 +17,18 @@  namespace EasyTracker  { - -    const int KPointCount = 3; -      class PointExtractor       {      public:          PointExtractor();          // extracts points from frame and draws some processing info into frame, if draw_output is set          // dt: time since last call in seconds -        void ExtractPoints(const cv::Mat& aFrame, cv::Mat* aPreview, std::vector<cv::Point>& aPoints); -         +        void ExtractPoints(const cv::Mat& aFrame, cv::Mat* aPreview, int aNeededPointCount, std::vector<cv::Point>& aPoints); + +        void UpdateSettings(); +          // Settings -        Settings s; +        Settings iSettings;          // Our frame with a channel size of 8 bits          cv::Mat iFrameChannelSizeOne;          // Our frame with a single 8 bits channel @@ -37,6 +36,10 @@ namespace EasyTracker          //          std::vector<std::vector<cv::Point> > iContours; +        // Take a copy of settings to avoid dead lock +        int iMinPointSize; +        int iMaxPointSize; +      };  } diff --git a/tracker-easy/preview.cpp b/tracker-easy/preview.cpp index 4d6b7c61..218fca43 100644 --- a/tracker-easy/preview.cpp +++ b/tracker-easy/preview.cpp @@ -105,19 +105,17 @@ namespace EasyTracker          cv::putText(iFrameRgb, aString, cv::Point(4,iFrameRgb.size().height-4), cv::FONT_HERSHEY_PLAIN, 2, cv::Scalar(0, 255, 0),2);      } -    void Preview::DrawCross(cv::Point aPoint) +    void Preview::DrawCross(const cv::Point& aPoint, const cv::Scalar& aColor)      { -        constexpr int len = 9; - -        static const cv::Scalar color(0, 255, 255); +        constexpr int len = 9;                  cv::line(iFrameRgb,              cv::Point(aPoint.x - len, aPoint.y),              cv::Point(aPoint.x + len, aPoint.y), -            color, 2); +            aColor, 2);          cv::line(iFrameRgb,              cv::Point(aPoint.x, aPoint.y - len),              cv::Point(aPoint.x, aPoint.y + len), -            color, 2); +            aColor, 2);      }      void Preview::ensure_size(cv::Mat& frame, int w, int h, int type) diff --git a/tracker-easy/preview.h b/tracker-easy/preview.h index 74ef89aa..d5cc8c30 100644 --- a/tracker-easy/preview.h +++ b/tracker-easy/preview.h @@ -21,7 +21,7 @@ namespace EasyTracker          Preview& operator=(const cv::Mat& frame);          QImage get_bitmap(); -        void DrawCross(cv::Point aPoint); +        void DrawCross(const cv::Point& aPoint, const cv::Scalar& aColor);          void DrawInfo(const std::string& aString);          operator cv::Mat&() { return iFrameResized; } diff --git a/tracker-easy/settings.h b/tracker-easy/settings.h index b4c14967..b0f14417 100644 --- a/tracker-easy/settings.h +++ b/tracker-easy/settings.h @@ -23,30 +23,30 @@ namespace EasyTracker {          value<int> cam_res_x{ b, "camera-res-width", 640 },              cam_res_y{ b, "camera-res-height", 480 },              cam_fps{ b, "camera-fps", 30 }; -        value<double> min_point_size{ b, "min-point-size", 2.5 }, -            max_point_size{ b, "max-point-size", 50 }; +        value<int> iMinBlobSize{ b, "iMinBlobSize", 4 }, iMaxBlobSize{ b, "iMaxBlobSize", 15 };          value<int> DeadzoneRectHalfEdgeSize { b, "deadzone-rect-half-edge-size", 1 }; -        value<int> m01_x{ b, "m_01-x", 0 }, m01_y{ b, "m_01-y", 0 }, m01_z{ b, "m_01-z", 0 }; -        value<int> m02_x{ b, "m_02-x", 0 }, m02_y{ b, "m_02-y", 0 }, m02_z{ b, "m_02-z", 0 }; +        // Type of custom model +        value<bool> iCustomModelThree{ b, "iCustomModelThree", true }; +        value<bool> iCustomModelFour{ b, "iCustomModelFour", false }; +        value<bool> iCustomModelFive{ b, "iCustomModelFive", false }; -        value<int> t_MH_x{ b, "model-centroid-x", 0 }, -            t_MH_y{ b, "model-centroid-y", 0 }, -            t_MH_z{ b, "model-centroid-z", 0 }; +        // Custom model vertices +        value<int> iVertexTopX{ b, "iVertexTopX", 0 }, iVertexTopY{ b, "iVertexTopY", 0 }, iVertexTopZ{ b, "iVertexTopZ", 0 }; +        value<int> iVertexRightX{ b, "iVertexRightX", 0 }, iVertexRightY{ b, "iVertexRightY", 0 }, iVertexRightZ{ b, "iVertexRightZ", 0 }; +        value<int> iVertexLeftX{ b, "iVertexLeftX", 0 }, iVertexLeftY{ b, "iVertexLeftY", 0 }, iVertexLeftZ{ b, "iVertexLeftZ", 0 }; +        value<int> iVertexCenterX{ b, "iVertexCenterX", 0 }, iVertexCenterY{ b, "iVertexCenterY", 0 }, iVertexCenterZ{ b, "iVertexCenterZ", 0 }; +        value<int> iVertexTopRightX{ b, "iVertexTopRightX", 0 }, iVertexTopRightY{ b, "iVertexTopRightY", 0 }, iVertexTopRightZ{ b, "iVertexTopRightZ", 0 }; +        value<int> iVertexTopLeftX{ b, "iVertexTopLeftX", 0 }, iVertexTopLeftY{ b, "iVertexTopLeftY", 0 }, iVertexTopLeftZ{ b, "iVertexTopLeftZ", 0 }; -        value<int> clip_ty{ b, "clip-ty", 40 }, -            clip_tz{ b, "clip-tz", 30 }, -            clip_by{ b, "clip-by", 70 }, -            clip_bz{ b, "clip-bz", 80 }; -        value<int> active_model_panel{ b, "active-model-panel", 0 }, -            cap_x{ b, "cap-x", 35 }, -            cap_y{ b, "cap-y", 55 }, -            cap_z{ b, "cap-z", 100 };          value<int> fov{ b, "camera-fov", 56 };          value<bool> debug{ b, "debug", false }; +        value<bool> iAutoCenter{ b, "iAutoCenter", true }; +        value<int> iAutoCenterTimeout{ b, "iAutoCenterTimeout", 1000 }; +          value<int> PnpSolver{ b, "pnp-solver", cv::SOLVEPNP_P3P }; diff --git a/tracker-easy/tracker-easy-dialog.cpp b/tracker-easy/tracker-easy-dialog.cpp index 411639d5..4a49e194 100644 --- a/tracker-easy/tracker-easy-dialog.cpp +++ b/tracker-easy/tracker-easy-dialog.cpp @@ -26,9 +26,7 @@ namespace EasyTracker      Dialog::Dialog() :          s(KModuleName), -        tracker(nullptr), -        timer(this), -        trans_calib(1, 2) +        tracker(nullptr)      {          init_resources(); @@ -42,39 +40,41 @@ namespace EasyTracker          tie_setting(s.cam_res_y, ui.res_y_spin);          tie_setting(s.cam_fps, ui.fps_spin); -        tie_setting(s.min_point_size, ui.mindiam_spin); -        tie_setting(s.max_point_size, ui.maxdiam_spin); +        tie_setting(s.iMinBlobSize, ui.mindiam_spin); +        tie_setting(s.iMaxBlobSize, ui.maxdiam_spin);          tie_setting(s.DeadzoneRectHalfEdgeSize, ui.spinDeadzone); -        tie_setting(s.clip_by, ui.clip_bheight_spin); -        tie_setting(s.clip_bz, ui.clip_blength_spin); -        tie_setting(s.clip_ty, ui.clip_theight_spin); -        tie_setting(s.clip_tz, ui.clip_tlength_spin); +        tie_setting(s.iVertexTopX, ui.iSpinVertexTopX); +        tie_setting(s.iVertexTopY, ui.iSpinVertexTopY); +        tie_setting(s.iVertexTopZ, ui.iSpinVertexTopZ); -        tie_setting(s.cap_x, ui.cap_width_spin); -        tie_setting(s.cap_y, ui.cap_height_spin); -        tie_setting(s.cap_z, ui.cap_length_spin); +        tie_setting(s.iVertexRightX, ui.iSpinVertexRightX); +        tie_setting(s.iVertexRightY, ui.iSpinVertexRightY); +        tie_setting(s.iVertexRightZ, ui.iSpinVertexRightZ); -        tie_setting(s.m01_x, ui.m1x_spin); -        tie_setting(s.m01_y, ui.m1y_spin); -        tie_setting(s.m01_z, ui.m1z_spin); +        tie_setting(s.iVertexLeftX, ui.iSpinVertexLeftX); +        tie_setting(s.iVertexLeftY, ui.iSpinVertexLeftY); +        tie_setting(s.iVertexLeftZ, ui.iSpinVertexLeftZ); -        tie_setting(s.m02_x, ui.m2x_spin); -        tie_setting(s.m02_y, ui.m2y_spin); -        tie_setting(s.m02_z, ui.m2z_spin); +        tie_setting(s.iVertexCenterX, ui.iSpinVertexCenterX); +        tie_setting(s.iVertexCenterY, ui.iSpinVertexCenterY); +        tie_setting(s.iVertexCenterZ, ui.iSpinVertexCenterZ); -        tie_setting(s.t_MH_x, ui.tx_spin); -        tie_setting(s.t_MH_y, ui.ty_spin); -        tie_setting(s.t_MH_z, ui.tz_spin); +        tie_setting(s.iVertexTopRightX, ui.iSpinVertexTopRightX); +        tie_setting(s.iVertexTopRightY, ui.iSpinVertexTopRightY); +        tie_setting(s.iVertexTopRightZ, ui.iSpinVertexTopRightZ); -        tie_setting(s.fov, ui.fov); +        tie_setting(s.iVertexTopLeftX, ui.iSpinVertexTopLeftX); +        tie_setting(s.iVertexTopLeftY, ui.iSpinVertexTopLeftY); +        tie_setting(s.iVertexTopLeftZ, ui.iSpinVertexTopLeftZ); -        tie_setting(s.active_model_panel, ui.model_tabs); +        tie_setting(s.fov, ui.fov);          tie_setting(s.debug, ui.debug); +        tie_setting(s.iAutoCenter, ui.iCheckBoxAutoCenter); +        tie_setting(s.iAutoCenterTimeout, ui.iSpinBoxAutoCenterTimeout); -        connect(ui.tcalib_button, SIGNAL(toggled(bool)), this, SLOT(startstop_trans_calib(bool)));          connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK()));          connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel())); @@ -83,102 +83,51 @@ namespace EasyTracker          set_camera_settings_available(ui.camdevice_combo->currentText());          connect(ui.camera_settings, &QPushButton::clicked, this, &Dialog::show_camera_settings); -        connect(&timer, &QTimer::timeout, this, &Dialog::poll_tracker_info_impl); -        timer.setInterval(250); - -        connect(&calib_timer, &QTimer::timeout, this, &Dialog::trans_calib_step); -        calib_timer.setInterval(35); +        // Radio Button +        connect(ui.iRadioButtonCustomModelThree, &QRadioButton::clicked, this, &Dialog::UpdateCustomModelControls); +        connect(ui.iRadioButtonCustomModelFour, &QRadioButton::clicked, this, &Dialog::UpdateCustomModelControls); +        connect(ui.iRadioButtonCustomModelFive, &QRadioButton::clicked, this, &Dialog::UpdateCustomModelControls); -        poll_tracker_info_impl(); - -        connect(this, &Dialog::poll_tracker_info, this, &Dialog::poll_tracker_info_impl, Qt::DirectConnection); +        tie_setting(s.iCustomModelThree, ui.iRadioButtonCustomModelThree); +        tie_setting(s.iCustomModelFour, ui.iRadioButtonCustomModelFour); +        tie_setting(s.iCustomModelFive, ui.iRadioButtonCustomModelFive);          for (unsigned k = 0; k < cv::SOLVEPNP_MAX_COUNT; k++) +        {              ui.comboBoxSolvers->setItemData(k, k); +        } +                      tie_setting(s.PnpSolver, ui.comboBoxSolvers); +        UpdateCustomModelControls();      } -     -    void Dialog::startstop_trans_calib(bool start) +    void Dialog::UpdateCustomModelControls()      { -        QMutexLocker l(&calibrator_mutex); - -        if (start) -        { -            qDebug() << "pt: starting translation calibration"; -            calib_timer.start(); -            trans_calib.reset(); -            s.t_MH_x = 0; -            s.t_MH_y = 0; -            s.t_MH_z = 0; - -            ui.sample_count_display->setText(QString()); -        } -        else +        if (ui.iRadioButtonCustomModelThree->isChecked())          { -            calib_timer.stop(); -            qDebug() << "pt: stopping translation calibration"; -            { -                auto[tmp, nsamples] = trans_calib.get_estimate(); -                s.t_MH_x = int(tmp[0]); -                s.t_MH_y = int(tmp[1]); -                s.t_MH_z = int(tmp[2]); - -                constexpr int min_yaw_samples = 15; -                constexpr int min_pitch_samples = 15; -                constexpr int min_samples = min_yaw_samples + min_pitch_samples; - -                // Don't bother counting roll samples. Roll calibration is hard enough -                // that it's a hidden unsupported feature anyway. - -                QString sample_feedback; -                if (nsamples[0] < min_yaw_samples) -                    sample_feedback = tr("%1 yaw samples. Yaw more to %2 samples for stable calibration.").arg(nsamples[0]).arg(min_yaw_samples); -                else if (nsamples[1] < min_pitch_samples) -                    sample_feedback = tr("%1 pitch samples. Pitch more to %2 samples for stable calibration.").arg(nsamples[1]).arg(min_pitch_samples); -                else -                { -                    const int nsamples_total = nsamples[0] + nsamples[1]; -                    sample_feedback = tr("%1 samples. Over %2, good!").arg(nsamples_total).arg(min_samples); -                } - -                ui.sample_count_display->setText(sample_feedback); -            } +            ui.iGroupBoxCenter->hide(); +            ui.iGroupBoxTopRight->hide(); +            ui.iGroupBoxTopLeft->hide();          } -        ui.tx_spin->setEnabled(!start); -        ui.ty_spin->setEnabled(!start); -        ui.tz_spin->setEnabled(!start); - -        if (start) -            ui.tcalib_button->setText(tr("Stop calibration")); -        else -            ui.tcalib_button->setText(tr("Start calibration")); -    } - -    void Dialog::poll_tracker_info_impl() -    { -        //SL: sort this out -        /* -        pt_camera_info info; -        if (tracker && tracker->get_cam_info(info)) +        else if (ui.iRadioButtonCustomModelFour->isChecked())          { -            ui.caminfo_label->setText(tr("%1x%2 @ %3 FPS").arg(info.res_x).arg(info.res_y).arg(iround(info.fps))); - -            // display point info -            const int n_points = tracker->get_n_points(); -            ui.pointinfo_label->setText((n_points == 3 ? tr("%1 OK!") : tr("%1 BAD!")).arg(n_points)); +            ui.iGroupBoxCenter->show(); +            ui.iGroupBoxTopRight->hide(); +            ui.iGroupBoxTopLeft->hide();          } -        else -        */ +        else if (ui.iRadioButtonCustomModelFive->isChecked())          { -            ui.caminfo_label->setText(tr("Tracker offline")); -            ui.pointinfo_label->setText(QString()); +            ui.iGroupBoxCenter->hide(); +            ui.iGroupBoxTopRight->show(); +            ui.iGroupBoxTopLeft->show();          } +      } +      void Dialog::set_camera_settings_available(const QString& /* camera_name */)      {          ui.camera_settings->setEnabled(true); @@ -195,12 +144,7 @@ namespace EasyTracker              (void)video::show_dialog(s.camera_name);      } -    void Dialog::trans_calib_step() -    { -        QMutexLocker l(&calibrator_mutex); -        // TODO: Do we still need that function -    } - +          void Dialog::save()      {          s.b->save(); @@ -220,16 +164,10 @@ namespace EasyTracker      void Dialog::register_tracker(ITracker *t)      {          tracker = static_cast<Tracker*>(t); -        ui.tcalib_button->setEnabled(true); -        poll_tracker_info(); -        timer.start();      }      void Dialog::unregister_tracker()      {          tracker = nullptr; -        ui.tcalib_button->setEnabled(false); -        poll_tracker_info(); -        timer.stop();      }  } diff --git a/tracker-easy/tracker-easy-dialog.h b/tracker-easy/tracker-easy-dialog.h index 768eaa21..7eb1ffb1 100644 --- a/tracker-easy/tracker-easy-dialog.h +++ b/tracker-easy/tracker-easy-dialog.h @@ -26,13 +26,13 @@ namespace EasyTracker          void register_tracker(ITracker *tracker) override;          void unregister_tracker() override;          void save(); +    private: +        void UpdateCustomModelControls(); +      public slots:          void doOK();          void doCancel(); -        void startstop_trans_calib(bool start); -        void trans_calib_step(); -        void poll_tracker_info_impl();          void set_camera_settings_available(const QString& camera_name);          void show_camera_settings();      signals: @@ -41,9 +41,6 @@ namespace EasyTracker          Settings s;          Tracker* tracker; -        QTimer timer, calib_timer; -        TranslationCalibrator trans_calib; -        QMutex calibrator_mutex;          Ui::UICPTClientControls ui;      }; diff --git a/tracker-easy/tracker-easy-settings.ui b/tracker-easy/tracker-easy-settings.ui index 2ec56a04..451b3e54 100644 --- a/tracker-easy/tracker-easy-settings.ui +++ b/tracker-easy/tracker-easy-settings.ui @@ -9,8 +9,8 @@     <rect>      <x>0</x>      <y>0</y> -    <width>418</width> -    <height>724</height> +    <width>465</width> +    <height>764</height>     </rect>    </property>    <property name="sizePolicy"> @@ -36,71 +36,17 @@     <property name="sizeConstraint">      <enum>QLayout::SetFixedSize</enum>     </property> -   <item row="1" column="0" alignment="Qt::AlignVCenter"> -    <widget class="QGroupBox" name="groupBox_5"> +   <item row="7" column="0"> +    <widget class="QDialogButtonBox" name="buttonBox">       <property name="sizePolicy">        <sizepolicy hsizetype="Preferred" vsizetype="Maximum">         <horstretch>0</horstretch>         <verstretch>0</verstretch>        </sizepolicy>       </property> -     <property name="title"> -      <string>Status</string> +     <property name="standardButtons"> +      <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>       </property> -     <layout class="QGridLayout" name="gridLayout_10"> -      <item row="1" column="0"> -       <widget class="QLabel" name="label_3"> -        <property name="sizePolicy"> -         <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> -          <horstretch>0</horstretch> -          <verstretch>0</verstretch> -         </sizepolicy> -        </property> -        <property name="text"> -         <string>Extracted Points:</string> -        </property> -       </widget> -      </item> -      <item row="0" column="0"> -       <widget class="QLabel" name="label_38"> -        <property name="sizePolicy"> -         <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> -          <horstretch>0</horstretch> -          <verstretch>0</verstretch> -         </sizepolicy> -        </property> -        <property name="text"> -         <string>Camera Info:</string> -        </property> -       </widget> -      </item> -      <item row="1" column="1"> -       <widget class="QLabel" name="pointinfo_label"> -        <property name="sizePolicy"> -         <sizepolicy hsizetype="Minimum" vsizetype="Maximum"> -          <horstretch>0</horstretch> -          <verstretch>0</verstretch> -         </sizepolicy> -        </property> -        <property name="text"> -         <string/> -        </property> -       </widget> -      </item> -      <item row="0" column="1"> -       <widget class="QLabel" name="caminfo_label"> -        <property name="sizePolicy"> -         <sizepolicy hsizetype="Minimum" vsizetype="Maximum"> -          <horstretch>0</horstretch> -          <verstretch>0</verstretch> -         </sizepolicy> -        </property> -        <property name="text"> -         <string/> -        </property> -       </widget> -      </item> -     </layout>      </widget>     </item>     <item row="0" column="0"> @@ -343,8 +289,21 @@           <property name="title">            <string>Settings</string>           </property> -         <layout class="QGridLayout" name="gridLayout_7"> -          <item row="2" column="0"> +         <layout class="QGridLayout" name="gridLayout"> +          <item row="1" column="0"> +           <widget class="QLabel" name="label_5"> +            <property name="sizePolicy"> +             <sizepolicy hsizetype="Minimum" vsizetype="Maximum"> +              <horstretch>0</horstretch> +              <verstretch>0</verstretch> +             </sizepolicy> +            </property> +            <property name="text"> +             <string>Debug (full size preview)</string> +            </property> +           </widget> +          </item> +          <item row="5" column="0">             <widget class="QLabel" name="label_7">              <property name="sizePolicy">               <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> @@ -360,24 +319,24 @@              </property>             </widget>            </item> -          <item row="5" column="0"> -           <widget class="QLabel" name="labelDeadzone"> +          <item row="5" column="2"> +           <widget class="QSpinBox" name="mindiam_spin">              <property name="sizePolicy">               <sizepolicy hsizetype="Preferred" vsizetype="Maximum">                <horstretch>0</horstretch>                <verstretch>0</verstretch>               </sizepolicy>              </property> -            <property name="text"> -             <string>Deadzone</string> +            <property name="toolTip"> +             <string>Minimum point diameter</string>              </property> -            <property name="buddy"> -             <cstring>maxdiam_spin</cstring> +            <property name="suffix"> +             <string> px</string>              </property>             </widget>            </item> -          <item row="3" column="0"> -           <widget class="QLabel" name="label_8"> +          <item row="2" column="2"> +           <widget class="QCheckBox" name="iCheckBoxAutoCenter">              <property name="sizePolicy">               <sizepolicy hsizetype="Preferred" vsizetype="Maximum">                <horstretch>0</horstretch> @@ -385,15 +344,25 @@               </sizepolicy>              </property>              <property name="text"> -             <string>Max size</string> +             <string/>              </property> -            <property name="buddy"> -             <cstring>maxdiam_spin</cstring> +           </widget> +          </item> +          <item row="1" column="2"> +           <widget class="QCheckBox" name="debug"> +            <property name="sizePolicy"> +             <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> +              <horstretch>0</horstretch> +              <verstretch>0</verstretch> +             </sizepolicy> +            </property> +            <property name="text"> +             <string/>              </property>             </widget>            </item> -          <item row="0" column="0"> -           <widget class="QLabel" name="label_5"> +          <item row="2" column="0"> +           <widget class="QLabel" name="label_13">              <property name="sizePolicy">               <sizepolicy hsizetype="Minimum" vsizetype="Maximum">                <horstretch>0</horstretch> @@ -401,12 +370,12 @@               </sizepolicy>              </property>              <property name="text"> -             <string>Debug (full size preview)</string> +             <string>Auto center</string>              </property>             </widget>            </item> -          <item row="0" column="1"> -           <widget class="QCheckBox" name="debug"> +          <item row="6" column="0"> +           <widget class="QLabel" name="label_8">              <property name="sizePolicy">               <sizepolicy hsizetype="Preferred" vsizetype="Maximum">                <horstretch>0</horstretch> @@ -414,11 +383,27 @@               </sizepolicy>              </property>              <property name="text"> -             <string/> +             <string>Max size</string>              </property>             </widget>            </item> -          <item row="1" column="0"> +          <item row="7" column="2"> +           <widget class="QSpinBox" name="spinDeadzone"> +            <property name="sizePolicy"> +             <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> +              <horstretch>0</horstretch> +              <verstretch>0</verstretch> +             </sizepolicy> +            </property> +            <property name="toolTip"> +             <string>Size in pixels of half the edge defining deadzone squares around tracked points</string> +            </property> +            <property name="suffix"> +             <string> px</string> +            </property> +           </widget> +          </item> +          <item row="4" column="0">             <widget class="QLabel" name="label_12">              <property name="sizePolicy">               <sizepolicy hsizetype="Minimum" vsizetype="Maximum"> @@ -426,12 +411,15 @@                <verstretch>0</verstretch>               </sizepolicy>              </property> +            <property name="toolTip"> +             <string><html><head/><body><p>Use P3P or AP3P for three and four points setup. Use EPNP or ITERATIVE for five points setup. Inconsistent configuration will result in undefined behavior.</p></body></html></string> +            </property>              <property name="text">               <string>Perspective-N-Point solver</string>              </property>             </widget>            </item> -          <item row="1" column="1"> +          <item row="4" column="2">             <widget class="QComboBox" name="comboBoxSolvers">              <property name="sizePolicy">               <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> @@ -477,30 +465,24 @@              </item>             </widget>            </item> -          <item row="2" column="1"> -           <widget class="QDoubleSpinBox" name="mindiam_spin"> +          <item row="7" column="0"> +           <widget class="QLabel" name="labelDeadzone">              <property name="sizePolicy">               <sizepolicy hsizetype="Preferred" vsizetype="Maximum">                <horstretch>0</horstretch>                <verstretch>0</verstretch>               </sizepolicy>              </property> -            <property name="toolTip"> -             <string>Minimum point diameter</string> -            </property> -            <property name="suffix"> -             <string> px</string> -            </property> -            <property name="decimals"> -             <number>1</number> +            <property name="text"> +             <string>Deadzone</string>              </property> -            <property name="singleStep"> -             <double>0.100000000000000</double> +            <property name="buddy"> +             <cstring>maxdiam_spin</cstring>              </property>             </widget>            </item> -          <item row="3" column="1"> -           <widget class="QDoubleSpinBox" name="maxdiam_spin"> +          <item row="6" column="2"> +           <widget class="QSpinBox" name="maxdiam_spin">              <property name="sizePolicy">               <sizepolicy hsizetype="Preferred" vsizetype="Maximum">                <horstretch>0</horstretch> @@ -513,16 +495,26 @@              <property name="suffix">               <string> px</string>              </property> -            <property name="decimals"> -             <number>1</number> +           </widget> +          </item> +          <item row="3" column="0"> +           <widget class="QLabel" name="label_14"> +            <property name="sizePolicy"> +             <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> +              <horstretch>0</horstretch> +              <verstretch>0</verstretch> +             </sizepolicy>              </property> -            <property name="singleStep"> -             <double>0.100000000000000</double> +            <property name="text"> +             <string>Auto center timeout</string> +            </property> +            <property name="buddy"> +             <cstring>mindiam_spin</cstring>              </property>             </widget>            </item> -          <item row="5" column="1"> -           <widget class="QSpinBox" name="spinDeadzone"> +          <item row="3" column="2"> +           <widget class="QSpinBox" name="iSpinBoxAutoCenterTimeout">              <property name="sizePolicy">               <sizepolicy hsizetype="Preferred" vsizetype="Maximum">                <horstretch>0</horstretch> @@ -530,10 +522,16 @@               </sizepolicy>              </property>              <property name="toolTip"> -             <string>Size in pixels of half the edge defining deadzone squares around tracked points</string> +             <string>If no valid pose can be determined after that much time the center pose will be used.</string>              </property>              <property name="suffix"> -             <string> px</string> +             <string> ms</string> +            </property> +            <property name="maximum"> +             <number>3600000</number> +            </property> +            <property name="singleStep"> +             <number>500</number>              </property>             </widget>            </item> @@ -546,705 +544,359 @@        <attribute name="title">         <string>Model</string>        </attribute> -      <layout class="QGridLayout" name="gridLayout_3"> -       <item row="0" column="0"> -        <widget class="QTabWidget" name="model_tabs"> -         <property name="enabled"> -          <bool>true</bool> +      <layout class="QVBoxLayout" name="verticalLayout_2"> +       <item> +        <widget class="QGroupBox" name="groupBoxCustomModelType"> +         <property name="title"> +          <string>Vertex count</string>           </property> -         <property name="sizePolicy"> -          <sizepolicy hsizetype="Preferred" vsizetype="Minimum"> -           <horstretch>0</horstretch> -           <verstretch>0</verstretch> -          </sizepolicy> +         <layout class="QHBoxLayout" name="horizontalLayout"> +          <item> +           <widget class="QRadioButton" name="iRadioButtonCustomModelThree"> +            <property name="text"> +             <string>Three vertices</string> +            </property> +            <property name="checked"> +             <bool>true</bool> +            </property> +           </widget> +          </item> +          <item> +           <widget class="QRadioButton" name="iRadioButtonCustomModelFour"> +            <property name="text"> +             <string>Four vertices</string> +            </property> +           </widget> +          </item> +          <item> +           <widget class="QRadioButton" name="iRadioButtonCustomModelFive"> +            <property name="text"> +             <string>Five vertices</string> +            </property> +           </widget> +          </item> +         </layout> +        </widget> +       </item> +       <item> +        <widget class="QGroupBox" name="groupBox"> +         <property name="title"> +          <string/>           </property> -         <property name="tabShape"> -          <enum>QTabWidget::Rounded</enum> +         <property name="flat"> +          <bool>false</bool>           </property> -         <property name="currentIndex"> -          <number>2</number> +         <layout class="QHBoxLayout" name="horizontalLayout_8"> +          <item> +           <widget class="QLabel" name="label"> +            <property name="text"> +             <string><html><head/><body><p><span style=" font-size:12pt;">X</span></p></body></html></string> +            </property> +           </widget> +          </item> +          <item> +           <widget class="QLabel" name="label_6"> +            <property name="text"> +             <string><html><head/><body><p><span style=" font-size:12pt;">Y</span></p></body></html></string> +            </property> +           </widget> +          </item> +          <item> +           <widget class="QLabel" name="label_11"> +            <property name="text"> +             <string><html><head/><body><p><span style=" font-size:12pt;">Z</span></p></body></html></string> +            </property> +           </widget> +          </item> +         </layout> +        </widget> +       </item> +       <item> +        <widget class="QGroupBox" name="iGroupBoxTop"> +         <property name="title"> +          <string>Top</string>           </property> -         <property name="usesScrollButtons"> -          <bool>false</bool> +         <layout class="QHBoxLayout" name="horizontalLayout_2"> +          <property name="topMargin"> +           <number>9</number> +          </property> +          <item> +           <widget class="QSpinBox" name="iSpinVertexTopX"> +            <property name="suffix"> +             <string> mm</string> +            </property> +            <property name="minimum"> +             <number>-65535</number> +            </property> +            <property name="maximum"> +             <number>65535</number> +            </property> +           </widget> +          </item> +          <item> +           <widget class="QSpinBox" name="iSpinVertexTopY"> +            <property name="suffix"> +             <string> mm</string> +            </property> +            <property name="minimum"> +             <number>-65535</number> +            </property> +            <property name="maximum"> +             <number>65535</number> +            </property> +           </widget> +          </item> +          <item> +           <widget class="QSpinBox" name="iSpinVertexTopZ"> +            <property name="suffix"> +             <string> mm</string> +            </property> +            <property name="minimum"> +             <number>-65535</number> +            </property> +            <property name="maximum"> +             <number>65535</number> +            </property> +           </widget> +          </item> +         </layout> +        </widget> +       </item> +       <item> +        <widget class="QGroupBox" name="iGroupBoxRight"> +         <property name="title"> +          <string>Right</string>           </property> -         <property name="documentMode"> -          <bool>false</bool> +         <layout class="QHBoxLayout" name="horizontalLayout_3"> +          <item> +           <widget class="QSpinBox" name="iSpinVertexRightX"> +            <property name="suffix"> +             <string> mm</string> +            </property> +            <property name="minimum"> +             <number>-65535</number> +            </property> +            <property name="maximum"> +             <number>65535</number> +            </property> +           </widget> +          </item> +          <item> +           <widget class="QSpinBox" name="iSpinVertexRightY"> +            <property name="suffix"> +             <string> mm</string> +            </property> +            <property name="minimum"> +             <number>-65535</number> +            </property> +            <property name="maximum"> +             <number>65535</number> +            </property> +           </widget> +          </item> +          <item> +           <widget class="QSpinBox" name="iSpinVertexRightZ"> +            <property name="suffix"> +             <string> mm</string> +            </property> +            <property name="minimum"> +             <number>-65535</number> +            </property> +            <property name="maximum"> +             <number>65535</number> +            </property> +           </widget> +          </item> +         </layout> +        </widget> +       </item> +       <item> +        <widget class="QGroupBox" name="iGroupBoxLeft"> +         <property name="title"> +          <string>Left</string>           </property> -         <property name="tabsClosable"> -          <bool>false</bool> +         <layout class="QHBoxLayout" name="horizontalLayout_4"> +          <item> +           <widget class="QSpinBox" name="iSpinVertexLeftX"> +            <property name="suffix"> +             <string> mm</string> +            </property> +            <property name="minimum"> +             <number>-65535</number> +            </property> +            <property name="maximum"> +             <number>65535</number> +            </property> +           </widget> +          </item> +          <item> +           <widget class="QSpinBox" name="iSpinVertexLeftY"> +            <property name="suffix"> +             <string> mm</string> +            </property> +            <property name="minimum"> +             <number>-65535</number> +            </property> +            <property name="maximum"> +             <number>65535</number> +            </property> +           </widget> +          </item> +          <item> +           <widget class="QSpinBox" name="iSpinVertexLeftZ"> +            <property name="suffix"> +             <string> mm</string> +            </property> +            <property name="minimum"> +             <number>-65535</number> +            </property> +            <property name="maximum"> +             <number>65535</number> +            </property> +           </widget> +          </item> +         </layout> +        </widget> +       </item> +       <item> +        <widget class="QGroupBox" name="iGroupBoxCenter"> +         <property name="title"> +          <string>Center</string>           </property> -         <widget class="QWidget" name="tabClip"> -          <property name="enabled"> -           <bool>false</bool> -          </property> -          <attribute name="title"> -           <string>Clip</string> -          </attribute> -          <layout class="QGridLayout" name="gridLayout_6"> -           <item row="0" column="0"> -            <widget class="QGroupBox" name="groupBox_8"> -             <property name="sizePolicy"> -              <sizepolicy hsizetype="Preferred" vsizetype="Minimum"> -               <horstretch>0</horstretch> -               <verstretch>0</verstretch> -              </sizepolicy> -             </property> -             <property name="minimumSize"> -              <size> -               <width>331</width> -               <height>208</height> -              </size> -             </property> -             <property name="title"> -              <string>Model Dimensions</string> -             </property> -             <widget class="QSpinBox" name="clip_tlength_spin"> -              <property name="geometry"> -               <rect> -                <x>70</x> -                <y>35</y> -                <width>100</width> -                <height>22</height> -               </rect> -              </property> -              <property name="suffix"> -               <string> mm</string> -              </property> -              <property name="minimum"> -               <number>-65535</number> -              </property> -              <property name="maximum"> -               <number>65535</number> -              </property> -             </widget> -             <widget class="QSpinBox" name="clip_bheight_spin"> -              <property name="geometry"> -               <rect> -                <x>150</x> -                <y>130</y> -                <width>100</width> -                <height>22</height> -               </rect> -              </property> -              <property name="suffix"> -               <string> mm</string> -              </property> -              <property name="minimum"> -               <number>-65535</number> -              </property> -              <property name="maximum"> -               <number>65535</number> -              </property> -             </widget> -             <widget class="QLabel" name="label_44"> -              <property name="geometry"> -               <rect> -                <x>65</x> -                <y>55</y> -                <width>71</width> -                <height>111</height> -               </rect> -              </property> -              <property name="text"> -               <string/> -              </property> -              <property name="pixmap"> -               <pixmap resource="tracker_easy.qrc">:/Resources/clip_side.png</pixmap> -              </property> -             </widget> -             <widget class="QLabel" name="label_50"> -              <property name="geometry"> -               <rect> -                <x>20</x> -                <y>40</y> -                <width>46</width> -                <height>13</height> -               </rect> -              </property> -              <property name="text"> -               <string>Side</string> -              </property> -             </widget> -             <widget class="QSpinBox" name="clip_blength_spin"> -              <property name="geometry"> -               <rect> -                <x>50</x> -                <y>160</y> -                <width>100</width> -                <height>22</height> -               </rect> -              </property> -              <property name="suffix"> -               <string> mm</string> -              </property> -              <property name="minimum"> -               <number>-65535</number> -              </property> -              <property name="maximum"> -               <number>65535</number> -              </property> -             </widget> -             <widget class="QSpinBox" name="clip_theight_spin"> -              <property name="geometry"> -               <rect> -                <x>150</x> -                <y>70</y> -                <width>100</width> -                <height>22</height> -               </rect> -              </property> -              <property name="suffix"> -               <string> mm</string> -              </property> -              <property name="minimum"> -               <number>-65535</number> -              </property> -              <property name="maximum"> -               <number>65535</number> -              </property> -             </widget> -             <widget class="QLabel" name="label_51"> -              <property name="geometry"> -               <rect> -                <x>290</x> -                <y>40</y> -                <width>46</width> -                <height>13</height> -               </rect> -              </property> -              <property name="text"> -               <string>Front</string> -              </property> -             </widget> -             <widget class="QLabel" name="label_45"> -              <property name="geometry"> -               <rect> -                <x>300</x> -                <y>70</y> -                <width>21</width> -                <height>111</height> -               </rect> -              </property> -              <property name="text"> -               <string/> -              </property> -              <property name="pixmap"> -               <pixmap resource="tracker_easy.qrc">:/Resources/clip_front.png</pixmap> -              </property> -             </widget> -            </widget> -           </item> -          </layout> -         </widget> -         <widget class="QWidget" name="tabCap"> -          <attribute name="title"> -           <string>Cap</string> -          </attribute> -          <layout class="QVBoxLayout" name="verticalLayout_14"> -           <item> -            <widget class="QGroupBox" name="groupBox_9"> -             <property name="minimumSize"> -              <size> -               <width>331</width> -               <height>208</height> -              </size> -             </property> -             <property name="title"> -              <string>Model Dimensions</string> -             </property> -             <widget class="QLabel" name="label_46"> -              <property name="geometry"> -               <rect> -                <x>100</x> -                <y>60</y> -                <width>111</width> -                <height>81</height> -               </rect> -              </property> -              <property name="text"> -               <string/> -              </property> -              <property name="pixmap"> -               <pixmap resource="tracker_easy.qrc">:/Resources/cap_side.png</pixmap> -              </property> -             </widget> -             <widget class="QLabel" name="label_48"> -              <property name="geometry"> -               <rect> -                <x>20</x> -                <y>40</y> -                <width>46</width> -                <height>13</height> -               </rect> -              </property> -              <property name="text"> -               <string>Side</string> -              </property> -             </widget> -             <widget class="QSpinBox" name="cap_length_spin"> -              <property name="geometry"> -               <rect> -                <x>90</x> -                <y>40</y> -                <width>101</width> -                <height>22</height> -               </rect> -              </property> -              <property name="suffix"> -               <string> mm</string> -              </property> -              <property name="minimum"> -               <number>-65535</number> -              </property> -              <property name="maximum"> -               <number>65535</number> -              </property> -             </widget> -             <widget class="QLabel" name="label_47"> -              <property name="geometry"> -               <rect> -                <x>220</x> -                <y>100</y> -                <width>81</width> -                <height>81</height> -               </rect> -              </property> -              <property name="text"> -               <string/> -              </property> -              <property name="pixmap"> -               <pixmap resource="tracker_easy.qrc">:/Resources/cap_front.png</pixmap> -              </property> -             </widget> -             <widget class="QSpinBox" name="cap_width_spin"> -              <property name="geometry"> -               <rect> -                <x>240</x> -                <y>70</y> -                <width>81</width> -                <height>22</height> -               </rect> -              </property> -              <property name="suffix"> -               <string> mm</string> -              </property> -              <property name="minimum"> -               <number>-65535</number> -              </property> -              <property name="maximum"> -               <number>65535</number> -              </property> -             </widget> -             <widget class="QLabel" name="label_49"> -              <property name="geometry"> -               <rect> -                <x>240</x> -                <y>40</y> -                <width>46</width> -                <height>13</height> -               </rect> -              </property> -              <property name="text"> -               <string>Front</string> -              </property> -             </widget> -             <widget class="QSpinBox" name="cap_height_spin"> -              <property name="geometry"> -               <rect> -                <x>20</x> -                <y>90</y> -                <width>81</width> -                <height>22</height> -               </rect> -              </property> -              <property name="suffix"> -               <string> mm</string> -              </property> -              <property name="minimum"> -               <number>-65535</number> -              </property> -              <property name="maximum"> -               <number>65535</number> -              </property> -             </widget> -            </widget> -           </item> -          </layout> -         </widget> -         <widget class="QWidget" name="tabCustom"> -          <property name="enabled"> -           <bool>false</bool> -          </property> -          <attribute name="title"> -           <string>Custom</string> -          </attribute> -          <layout class="QGridLayout" name="gridLayout"> -           <item row="0" column="0"> -            <widget class="QGroupBox" name="groupBox_7"> -             <property name="title"> -              <string>Model Dimensions</string> -             </property> -             <layout class="QGridLayout" name="gridLayout_5"> -              <item row="3" column="1"> -               <widget class="QLabel" name="label_57"> -                <property name="sizePolicy"> -                 <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> -                  <horstretch>0</horstretch> -                  <verstretch>0</verstretch> -                 </sizepolicy> -                </property> -                <property name="text"> -                 <string>z:</string> -                </property> -               </widget> -              </item> -              <item row="2" column="5"> -               <widget class="QSpinBox" name="m2y_spin"> -                <property name="suffix"> -                 <string> mm</string> -                </property> -                <property name="minimum"> -                 <number>-65535</number> -                </property> -                <property name="maximum"> -                 <number>65535</number> -                </property> -               </widget> -              </item> -              <item row="1" column="1"> -               <widget class="QLabel" name="label_63"> -                <property name="sizePolicy"> -                 <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> -                  <horstretch>0</horstretch> -                  <verstretch>0</verstretch> -                 </sizepolicy> -                </property> -                <property name="text"> -                 <string>x:</string> -                </property> -               </widget> -              </item> -              <item row="1" column="2"> -               <widget class="QSpinBox" name="m1x_spin"> -                <property name="suffix"> -                 <string> mm</string> -                </property> -                <property name="minimum"> -                 <number>-65535</number> -                </property> -                <property name="maximum"> -                 <number>65535</number> -                </property> -               </widget> -              </item> -              <item row="2" column="2"> -               <widget class="QSpinBox" name="m1y_spin"> -                <property name="suffix"> -                 <string> mm</string> -                </property> -                <property name="minimum"> -                 <number>-65535</number> -                </property> -                <property name="maximum"> -                 <number>65535</number> -                </property> -               </widget> -              </item> -              <item row="3" column="5"> -               <widget class="QSpinBox" name="m2z_spin"> -                <property name="suffix"> -                 <string> mm</string> -                </property> -                <property name="minimum"> -                 <number>-65535</number> -                </property> -                <property name="maximum"> -                 <number>65535</number> -                </property> -               </widget> -              </item> -              <item row="1" column="5"> -               <widget class="QSpinBox" name="m2x_spin"> -                <property name="suffix"> -                 <string> mm</string> -                </property> -                <property name="minimum"> -                 <number>-65535</number> -                </property> -                <property name="maximum"> -                 <number>65535</number> -                </property> -               </widget> -              </item> -              <item row="0" column="0" colspan="6"> -               <widget class="QLabel" name="label_56"> -                <property name="sizePolicy"> -                 <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> -                  <horstretch>0</horstretch> -                  <verstretch>0</verstretch> -                 </sizepolicy> -                </property> -                <property name="text"> -                 <string><html><head/><body><p>Location of the two remaining model points<br/>with respect to the reference point in default pose</p><p>Use any units you want, not necessarily centimeters.</p></body></html></string> -                </property> -               </widget> -              </item> -              <item row="3" column="2"> -               <widget class="QSpinBox" name="m1z_spin"> -                <property name="suffix"> -                 <string> mm</string> -                </property> -                <property name="minimum"> -                 <number>-65535</number> -                </property> -                <property name="maximum"> -                 <number>65535</number> -                </property> -               </widget> -              </item> -              <item row="2" column="4"> -               <widget class="QLabel" name="label_70"> -                <property name="sizePolicy"> -                 <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> -                  <horstretch>0</horstretch> -                  <verstretch>0</verstretch> -                 </sizepolicy> -                </property> -                <property name="text"> -                 <string>y:</string> -                </property> -               </widget> -              </item> -              <item row="1" column="4"> -               <widget class="QLabel" name="label_67"> -                <property name="sizePolicy"> -                 <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> -                  <horstretch>0</horstretch> -                  <verstretch>0</verstretch> -                 </sizepolicy> -                </property> -                <property name="text"> -                 <string>x:</string> -                </property> -               </widget> -              </item> -              <item row="1" column="3"> -               <widget class="QLabel" name="label_64"> -                <property name="sizePolicy"> -                 <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> -                  <horstretch>0</horstretch> -                  <verstretch>0</verstretch> -                 </sizepolicy> -                </property> -                <property name="text"> -                 <string><html><head/><body><p><span style=" font-size:16pt;">P</span><span style=" font-size:16pt; vertical-align:sub;">3</span></p></body></html></string> -                </property> -               </widget> -              </item> -              <item row="1" column="0"> -               <widget class="QLabel" name="label_60"> -                <property name="sizePolicy"> -                 <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> -                  <horstretch>0</horstretch> -                  <verstretch>0</verstretch> -                 </sizepolicy> -                </property> -                <property name="text"> -                 <string><html><head/><body><p><span style=" font-size:16pt;">P</span><span style=" font-size:16pt; vertical-align:sub;">2</span></p></body></html></string> -                </property> -               </widget> -              </item> -              <item row="3" column="4"> -               <widget class="QLabel" name="label_69"> -                <property name="sizePolicy"> -                 <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> -                  <horstretch>0</horstretch> -                  <verstretch>0</verstretch> -                 </sizepolicy> -                </property> -                <property name="text"> -                 <string>z:</string> -                </property> -               </widget> -              </item> -              <item row="2" column="1"> -               <widget class="QLabel" name="label_58"> -                <property name="sizePolicy"> -                 <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> -                  <horstretch>0</horstretch> -                  <verstretch>0</verstretch> -                 </sizepolicy> -                </property> -                <property name="text"> -                 <string>y:</string> -                </property> -               </widget> -              </item> -             </layout> -            </widget> -           </item> -          </layout> -         </widget> +         <layout class="QHBoxLayout" name="horizontalLayout_5"> +          <item> +           <widget class="QSpinBox" name="iSpinVertexCenterX"> +            <property name="suffix"> +             <string> mm</string> +            </property> +            <property name="minimum"> +             <number>-65535</number> +            </property> +            <property name="maximum"> +             <number>65535</number> +            </property> +           </widget> +          </item> +          <item> +           <widget class="QSpinBox" name="iSpinVertexCenterY"> +            <property name="suffix"> +             <string> mm</string> +            </property> +            <property name="minimum"> +             <number>-65535</number> +            </property> +            <property name="maximum"> +             <number>65535</number> +            </property> +           </widget> +          </item> +          <item> +           <widget class="QSpinBox" name="iSpinVertexCenterZ"> +            <property name="suffix"> +             <string> mm</string> +            </property> +            <property name="minimum"> +             <number>-65535</number> +            </property> +            <property name="maximum"> +             <number>65535</number> +            </property> +           </widget> +          </item> +         </layout>          </widget>         </item> -       <item row="1" column="0"> -        <widget class="QGroupBox" name="groupBox_10"> -         <property name="sizePolicy"> -          <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> -           <horstretch>0</horstretch> -           <verstretch>0</verstretch> -          </sizepolicy> +       <item> +        <widget class="QGroupBox" name="iGroupBoxTopRight"> +         <property name="title"> +          <string>Top Right</string>           </property> +         <layout class="QHBoxLayout" name="horizontalLayout_6"> +          <item> +           <widget class="QSpinBox" name="iSpinVertexTopRightX"> +            <property name="suffix"> +             <string> mm</string> +            </property> +            <property name="minimum"> +             <number>-65535</number> +            </property> +            <property name="maximum"> +             <number>65535</number> +            </property> +           </widget> +          </item> +          <item> +           <widget class="QSpinBox" name="iSpinVertexTopRightY"> +            <property name="suffix"> +             <string> mm</string> +            </property> +            <property name="minimum"> +             <number>-65535</number> +            </property> +            <property name="maximum"> +             <number>65535</number> +            </property> +           </widget> +          </item> +          <item> +           <widget class="QSpinBox" name="iSpinVertexTopRightZ"> +            <property name="suffix"> +             <string> mm</string> +            </property> +            <property name="minimum"> +             <number>-65535</number> +            </property> +            <property name="maximum"> +             <number>65535</number> +            </property> +           </widget> +          </item> +         </layout> +        </widget> +       </item> +       <item> +        <widget class="QGroupBox" name="iGroupBoxTopLeft">           <property name="title"> -          <string>Model position</string> +          <string>Top Left</string>           </property> -         <layout class="QGridLayout" name="gridLayout_4"> -          <item row="0" column="0"> -           <widget class="QFrame" name="frame_2"> -            <property name="frameShape"> -             <enum>QFrame::NoFrame</enum> -            </property> -            <property name="frameShadow"> -             <enum>QFrame::Raised</enum> -            </property> -            <layout class="QGridLayout" name="gridLayout_11"> -             <item row="1" column="1"> -              <widget class="QSpinBox" name="ty_spin"> -               <property name="suffix"> -                <string> mm</string> -               </property> -               <property name="minimum"> -                <number>-65535</number> -               </property> -               <property name="maximum"> -                <number>65536</number> -               </property> -              </widget> -             </item> -             <item row="2" column="0"> -              <widget class="QLabel" name="label_66"> -               <property name="sizePolicy"> -                <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> -                 <horstretch>0</horstretch> -                 <verstretch>0</verstretch> -                </sizepolicy> -               </property> -               <property name="text"> -                <string>z:</string> -               </property> -              </widget> -             </item> -             <item row="2" column="1"> -              <widget class="QSpinBox" name="tz_spin"> -               <property name="suffix"> -                <string> mm</string> -               </property> -               <property name="minimum"> -                <number>-65535</number> -               </property> -               <property name="maximum"> -                <number>65536</number> -               </property> -              </widget> -             </item> -             <item row="0" column="0"> -              <widget class="QLabel" name="label_61"> -               <property name="sizePolicy"> -                <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> -                 <horstretch>0</horstretch> -                 <verstretch>0</verstretch> -                </sizepolicy> -               </property> -               <property name="text"> -                <string>x:</string> -               </property> -              </widget> -             </item> -             <item row="0" column="1"> -              <widget class="QSpinBox" name="tx_spin"> -               <property name="suffix"> -                <string> mm</string> -               </property> -               <property name="minimum"> -                <number>-65535</number> -               </property> -               <property name="maximum"> -                <number>65536</number> -               </property> -              </widget> -             </item> -             <item row="1" column="0"> -              <widget class="QLabel" name="label_62"> -               <property name="sizePolicy"> -                <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> -                 <horstretch>0</horstretch> -                 <verstretch>0</verstretch> -                </sizepolicy> -               </property> -               <property name="text"> -                <string>y:</string> -               </property> -              </widget> -             </item> -            </layout> +         <layout class="QHBoxLayout" name="horizontalLayout_7"> +          <item> +           <widget class="QSpinBox" name="iSpinVertexTopLeftX"> +            <property name="suffix"> +             <string> mm</string> +            </property> +            <property name="minimum"> +             <number>-65535</number> +            </property> +            <property name="maximum"> +             <number>65535</number> +            </property>             </widget>            </item> -          <item row="0" column="1"> -           <widget class="QFrame" name="frame"> -            <property name="frameShape"> -             <enum>QFrame::NoFrame</enum> -            </property> -            <property name="frameShadow"> -             <enum>QFrame::Raised</enum> -            </property> -            <layout class="QVBoxLayout" name="verticalLayout_2"> -             <item> -              <widget class="QLabel" name="label_59"> -               <property name="text"> -                <string>Use only yaw and pitch while calibrating. -Don't roll or change position.</string> -               </property> -               <property name="alignment"> -                <set>Qt::AlignCenter</set> -               </property> -               <property name="wordWrap"> -                <bool>true</bool> -               </property> -               <property name="openExternalLinks"> -                <bool>false</bool> -               </property> -              </widget> -             </item> -             <item> -              <widget class="QLabel" name="sample_count_display"> -               <property name="sizePolicy"> -                <sizepolicy hsizetype="Minimum" vsizetype="Maximum"> -                 <horstretch>0</horstretch> -                 <verstretch>0</verstretch> -                </sizepolicy> -               </property> -               <property name="text"> -                <string/> -               </property> -               <property name="wordWrap"> -                <bool>true</bool> -               </property> -              </widget> -             </item> -             <item> -              <widget class="QPushButton" name="tcalib_button"> -               <property name="enabled"> -                <bool>false</bool> -               </property> -               <property name="text"> -                <string>Start calibration</string> -               </property> -               <property name="checkable"> -                <bool>true</bool> -               </property> -              </widget> -             </item> -            </layout> +          <item> +           <widget class="QSpinBox" name="iSpinVertexTopLeftY"> +            <property name="suffix"> +             <string> mm</string> +            </property> +            <property name="minimum"> +             <number>-65535</number> +            </property> +            <property name="maximum"> +             <number>65535</number> +            </property> +           </widget> +          </item> +          <item> +           <widget class="QSpinBox" name="iSpinVertexTopLeftZ"> +            <property name="suffix"> +             <string> mm</string> +            </property> +            <property name="minimum"> +             <number>-65535</number> +            </property> +            <property name="maximum"> +             <number>65535</number> +            </property>             </widget>            </item>           </layout> @@ -1260,7 +912,7 @@ Don't roll or change position.</string>         <item row="0" column="0">          <widget class="QLabel" name="label_10">           <property name="text"> -          <string><html><head/><body><p><span style=" font-weight:600;">Easy Tracker<br/>Version 0.1</span></p><p><span style=" font-weight:600;">by Stéphane Lenclud</span></p><p>See  <a href="https://github.com/opentrack/opentrack/wiki/Easy-Tracker"><span style=" font-weight:600; text-decoration: underline; color:#9999AA;">documentation on GitHub</span></a></p></body></html></string> +          <string><html><head/><body><p><span style=" font-weight:600;">Easy Tracker<br/>Version 1.0</span></p><p><span style=" font-weight:600;">by Stéphane Lenclud</span></p><p>See <a href="https://github.com/opentrack/opentrack/wiki/Easy-Tracker"><span style=" font-weight:600; text-decoration: underline; color:#9999aa;">documentation on GitHub</span></a></p></body></html></string>           </property>           <property name="alignment">            <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> @@ -1287,19 +939,6 @@ Don't roll or change position.</string>       </widget>      </widget>     </item> -   <item row="2" column="0"> -    <widget class="QDialogButtonBox" name="buttonBox"> -     <property name="sizePolicy"> -      <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> -       <horstretch>0</horstretch> -       <verstretch>0</verstretch> -      </sizepolicy> -     </property> -     <property name="standardButtons"> -      <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> -     </property> -    </widget> -   </item>    </layout>   </widget>   <tabstops> @@ -1310,24 +949,6 @@ Don't roll or change position.</string>    <tabstop>fps_spin</tabstop>    <tabstop>fov</tabstop>    <tabstop>camera_settings</tabstop> -  <tabstop>model_tabs</tabstop> -  <tabstop>clip_tlength_spin</tabstop> -  <tabstop>clip_theight_spin</tabstop> -  <tabstop>clip_bheight_spin</tabstop> -  <tabstop>clip_blength_spin</tabstop> -  <tabstop>cap_length_spin</tabstop> -  <tabstop>cap_height_spin</tabstop> -  <tabstop>cap_width_spin</tabstop> -  <tabstop>m1x_spin</tabstop> -  <tabstop>m1y_spin</tabstop> -  <tabstop>m1z_spin</tabstop> -  <tabstop>m2x_spin</tabstop> -  <tabstop>m2y_spin</tabstop> -  <tabstop>m2z_spin</tabstop> -  <tabstop>tx_spin</tabstop> -  <tabstop>ty_spin</tabstop> -  <tabstop>tz_spin</tabstop> -  <tabstop>tcalib_button</tabstop>   </tabstops>   <resources>    <include location="tracker_easy.qrc"/> diff --git a/tracker-easy/tracker-easy.cpp b/tracker-easy/tracker-easy.cpp index ebc6e128..e13bdf37 100644 --- a/tracker-easy/tracker-easy.cpp +++ b/tracker-easy/tracker-easy.cpp @@ -24,11 +24,14 @@  using namespace options;  // Disable debug -#define dbgout if (true) {} else std::cout +#define dbgout if (true) {} else std::cout << "\n" <<std::chrono::system_clock::now().time_since_epoch().count() << ": "  //#define infout if (true) {} else std::cout  // Enable debug  //#define dbgout if (false) {} else std::cout -#define infout if (false) {} else std::cout +#define infout if (false) {} else std::cout << "\n" << std::chrono::system_clock::now().time_since_epoch().count() << ": " + +// We need at least 3 vertices to be able to do anything +const int KMinVertexCount = 3;  namespace EasyTracker  { @@ -49,14 +52,35 @@ namespace EasyTracker          //connect(&iSettings.cam_fps, value_::value_changed<int>(), this, &Tracker::SetFps, Qt::DirectConnection);          // Make sure deadzones are updated whenever the settings are changed -        connect(&iSettings.DeadzoneRectHalfEdgeSize, value_::value_changed<int>(), this, &Tracker::UpdateDeadzones, Qt::DirectConnection); -        UpdateDeadzones(iSettings.DeadzoneRectHalfEdgeSize); +        connect(&iSettings.DeadzoneRectHalfEdgeSize, value_::value_changed<int>(), this, &Tracker::UpdateSettings, Qt::DirectConnection); + +        // Update point extractor whenever some of the settings it needs are changed +        connect(&iSettings.iMinBlobSize, value_::value_changed<int>(), this, &Tracker::UpdateSettings, Qt::DirectConnection); +        connect(&iSettings.iMaxBlobSize, value_::value_changed<int>(), this, &Tracker::UpdateSettings, Qt::DirectConnection);          // Make sure solver is updated whenever the settings are changed -        connect(&iSettings.PnpSolver, value_::value_changed<int>(), this, &Tracker::UpdateSolver, Qt::DirectConnection); -        UpdateSolver(iSettings.PnpSolver); +        connect(&iSettings.PnpSolver, value_::value_changed<int>(), this, &Tracker::UpdateSettings, Qt::DirectConnection); + +        // Debug +        connect(&iSettings.debug, value_::value_changed<bool>(), this, &Tracker::UpdateSettings, Qt::DirectConnection); + +        // Make sure model is updated whenever it is changed +        connect(&iSettings.iCustomModelThree, value_::value_changed<bool>(), this, &Tracker::UpdateModel, Qt::DirectConnection); +        connect(&iSettings.iCustomModelFour, value_::value_changed<bool>(), this, &Tracker::UpdateModel, Qt::DirectConnection); +        connect(&iSettings.iCustomModelFive, value_::value_changed<bool>(), this, &Tracker::UpdateModel, Qt::DirectConnection); + +        // Update model logic +        #define UM(v) connect(&iSettings.v, value_::value_changed<int>(), this, &Tracker::UpdateModel, Qt::DirectConnection) +        UM(iVertexTopX); UM(iVertexTopY); UM(iVertexTopZ); +        UM(iVertexTopRightX); UM(iVertexTopRightY); UM(iVertexTopRightZ); +        UM(iVertexTopLeftX); UM(iVertexTopLeftY); UM(iVertexTopLeftZ); +        UM(iVertexRightX); UM(iVertexRightY); UM(iVertexRightZ); +        UM(iVertexLeftX); UM(iVertexLeftY); UM(iVertexLeftZ); +        UM(iVertexCenterX); UM(iVertexCenterY); UM(iVertexCenterZ); + +        UpdateModel(); -        CreateModelFromSettings();         +        UpdateSettings();      }      Tracker::~Tracker() @@ -77,7 +101,6 @@ namespace EasyTracker      // Compute Euler angles from rotation matrix      void getEulerAngles(cv::Mat &rotCamerMatrix, cv::Vec3d &eulerAngles)      { -          cv::Mat cameraMatrix, rotMatrix, transVect, rotMatrixX, rotMatrixY, rotMatrixZ;          double* _r = rotCamerMatrix.ptr<double>();          double projMatrix[12] = { _r[0],_r[1],_r[2],0, @@ -95,19 +118,6 @@ namespace EasyTracker      }      /// -    void Tracker::CreateModelFromSettings() -    { -        // Construct the points defining the object we want to detect based on settings. -        // We are converting them from millimeters to centimeters. -        // TODO: Need to support clip too. That's cap only for now. -        // s.active_model_panel != PointModel::Clip -        iModel.clear(); -        iModel.push_back(cv::Point3f(iSettings.cap_x / 10.0, iSettings.cap_z / 10.0, -iSettings.cap_y / 10.0)); // Right -        iModel.push_back(cv::Point3f(-iSettings.cap_x / 10.0, iSettings.cap_z / 10.0, -iSettings.cap_y / 10.0)); // Left -        iModel.push_back(cv::Point3f(0, 0, 0)); // Top -    } - -    ///      void Tracker::CreateCameraIntrinsicsMatrices()      {          // Create our camera matrix                 @@ -132,11 +142,194 @@ namespace EasyTracker          iDistCoeffsMatrix.at<double>(7, 0) = iCameraInfo.radialDistortionSixthOrder; // Radial sixth order      } + +    void Tracker::MatchVertices(int& aTopIndex, int& aRightIndex, int& aLeftIndex, int& aCenterIndex, int& aTopRight, int& aTopLeft) +    { +        if (iModel.size() == 5) +        { +            MatchFiveVertices(aTopIndex, aRightIndex, aLeftIndex, aTopRight, aTopLeft); +        } +        else +        { +            MatchThreeOrFourVertices(aTopIndex, aRightIndex, aLeftIndex, aCenterIndex); +        } +    } + + +    void Tracker::MatchFiveVertices(int& aTopIndex, int& aRightIndex, int& aLeftIndex, int& aTopRight, int& aTopLeft) +    { +        //Bitmap origin is top left +        iTrackedPoints.clear(); + +        int vertexIndices[] = { -1,-1,-1,-1,-1 }; +        std::vector<int> indices = { 0,1,2,3,4 }; + +        // Tracked points must match the order of the object model points. +        // Find top most point, that's the one with min Y as we assume our guy's head is not up side down +        int minY = std::numeric_limits<int>::max(); +        for (int i = 0; i < iPoints.size(); i++) +        { +            if (iPoints[i].y < minY) +            { +                minY = iPoints[i].y; +                vertexIndices[VertexPosition::Top] = i;                 +            } +        } +        indices.erase(std::find(indices.begin(), indices.end(), vertexIndices[VertexPosition::Top])); + +        // Find right most point  +        int maxX = 0; +        for (int i = 0; i < iPoints.size(); i++) +        { +            // Excluding top most point +            if (i != vertexIndices[VertexPosition::Top] && iPoints[i].x > maxX) +            { +                maxX = iPoints[i].x; +                vertexIndices[VertexPosition::Right] = i; +            } +        } +        indices.erase(std::find(indices.begin(), indices.end(), vertexIndices[VertexPosition::Right])); + +        // Find left most point +        int minX = std::numeric_limits<int>::max(); +        for (int i = 0; i < iPoints.size(); i++) +        { +            // Excluding top most point and right most point +            if (i != vertexIndices[VertexPosition::Top] && i != vertexIndices[VertexPosition::Right] && iPoints[i].x < minX) +            { +                minX = iPoints[i].x; +                vertexIndices[VertexPosition::Left] = i; +            } +        } +        indices.erase(std::find(indices.begin(), indices.end(), vertexIndices[VertexPosition::Left])); + +        // Check which of our two remaining points is on the left +        int leftIndex = -1; +        int rightIndex = -1; +        if (iPoints[indices[0]].x > iPoints[indices[1]].x) +        { +            leftIndex = indices[1]; +            rightIndex = indices[0]; +        } +        else +        { +            leftIndex = indices[0]; +            rightIndex = indices[1]; +        } + +        // Check which of the left points is at the top +        if (iPoints[vertexIndices[VertexPosition::Left]].y < iPoints[leftIndex].y) +        { +            vertexIndices[VertexPosition::TopLeft] = vertexIndices[VertexPosition::Left]; +            vertexIndices[VertexPosition::Left] = leftIndex; +        } +        else +        { +            vertexIndices[VertexPosition::TopLeft] = leftIndex; +        } + +        // Check which of the right points is at the top +        if (iPoints[vertexIndices[VertexPosition::Right]].y < iPoints[rightIndex].y) +        { +            vertexIndices[VertexPosition::TopRight] = vertexIndices[VertexPosition::Right]; +            vertexIndices[VertexPosition::Right] = rightIndex; +        } +        else +        { +            vertexIndices[VertexPosition::TopRight] = rightIndex; +        } + + +        // Order matters, see UpdateModel function  +        iTrackedPoints.push_back(iPoints[vertexIndices[VertexPosition::Top]]); +        iTrackedPoints.push_back(iPoints[vertexIndices[VertexPosition::Right]]); +        iTrackedPoints.push_back(iPoints[vertexIndices[VertexPosition::Left]]); +        iTrackedPoints.push_back(iPoints[vertexIndices[VertexPosition::TopRight]]); +        iTrackedPoints.push_back(iPoints[vertexIndices[VertexPosition::TopLeft]]); + +        // +        aTopIndex = vertexIndices[VertexPosition::Top]; +        aRightIndex = vertexIndices[VertexPosition::Right]; +        aLeftIndex = vertexIndices[VertexPosition::Left]; +        aTopRight = vertexIndices[VertexPosition::TopRight]; +        aTopLeft = vertexIndices[VertexPosition::TopLeft]; + + +    } + + +    void Tracker::MatchThreeOrFourVertices(int& aTopIndex, int& aRightIndex, int& aLeftIndex, int& aCenterIndex) +    { +        //Bitmap origin is top left +        iTrackedPoints.clear(); +        // Tracked points must match the order of the object model points. +        // Find top most point, that's the one with min Y as we assume our guy's head is not up side down +        int minY = std::numeric_limits<int>::max(); +        for (int i = 0; i < iPoints.size(); i++) +        { +            if (iPoints[i].y < minY) +            { +                minY = iPoints[i].y; +                aTopIndex = i; +            } +        } + + +        int maxX = 0; + +        // Find right most point  +        for (int i = 0; i < iPoints.size(); i++) +        { +            // Excluding top most point +            if (i != aTopIndex && iPoints[i].x > maxX) +            { +                maxX = iPoints[i].x; +                aRightIndex = i; +            } +        } + +        // Find left most point +        int minX = std::numeric_limits<int>::max(); +        for (int i = 0; i < iPoints.size(); i++) +        { +            // Excluding top most point and right most point +            if (i != aTopIndex && i != aRightIndex && iPoints[i].x < minX) +            { +                aLeftIndex = i; +                minX = iPoints[i].x; +            } +        } + +        // Find center point, the last one +        for (int i = 0; i < iPoints.size(); i++) +        { +            // Excluding the three points we already have +            if (i != aTopIndex && i != aRightIndex && i != aLeftIndex) +            { +                aCenterIndex = i; +            } +        } + +        // Order matters +        iTrackedPoints.push_back(iPoints[aTopIndex]); +        iTrackedPoints.push_back(iPoints[aRightIndex]); +        iTrackedPoints.push_back(iPoints[aLeftIndex]); +        if (iModel.size() > iTrackedPoints.size()) +        { +            // We are tracking more than 3 points +            iTrackedPoints.push_back(iPoints[aCenterIndex]); +        } +    } + +     +      ///      ///      ///      void Tracker::ProcessFrame()      { +        QMutexLocker l(&iProcessLock); +          // Create OpenCV matrix from our frame          // TODO: Assert channel size is one or two          iMatFrame = cv::Mat(iFrame.height, iFrame.width, CV_MAKETYPE((iFrame.channelSize == 2 ? CV_16U : CV_8U), iFrame.channels), iFrame.data, iFrame.stride); @@ -149,170 +342,208 @@ namespace EasyTracker          }          iPoints.clear(); -        iPointExtractor.ExtractPoints(iMatFrame, (doPreview ? &iPreview.iFrameRgb : nullptr), iPoints); +        iPointExtractor.ExtractPoints(iMatFrame, (doPreview ? &iPreview.iFrameRgb : nullptr), iModel.size(), iPoints); -        const bool success = iPoints.size() >= KPointCount; +        const bool success = iPoints.size() >= iModel.size() && iModel.size() >= KMinVertexCount;          int topPointIndex = -1; +        int rightPointIndex = -1; +        int leftPointIndex = -1; +        int centerPointIndex = -1; +        int topRightPointIndex = -1; +        int topLeftPointIndex = -1; +        if (success)          { -            QMutexLocker l(¢er_lock); - -            if (success) +            // Lets match our 3D vertices with our image 2D points +            MatchVertices(topPointIndex, rightPointIndex, leftPointIndex, centerPointIndex, topRightPointIndex, topLeftPointIndex); + +            bool movedEnough = true; +            // Check if we moved enough since last time we were here +            // This is our deadzone management +            if (iDeadzoneHalfEdge != 0 // Check if deazones are enabled +                && iTrackedRects.size() == iTrackedPoints.size())              { -                ever_success.store(true, std::memory_order_relaxed); - -                //Bitmap origin is top left -                iTrackedPoints.clear(); -                // Tracked points must match the order of the object model points. -                // Find top most point, that's the one with min Y as we assume our guy's head is not up side down -                int minY = std::numeric_limits<int>::max(); -                for (int i = 0; i < 3; i++) +                movedEnough = false; +                for (size_t i = 0; i < iTrackedPoints.size(); i++)                  { -                    if (iPoints[i].y < minY) +                    if (!iTrackedRects[i].contains(iTrackedPoints[i]))                      { -                        minY = iPoints[i].y; -                        topPointIndex = i; +                        movedEnough = true; +                        break;                      }                  } +            } -                int rightPointIndex = -1; -                int maxX = 0; - -                // Find right most point  -                for (int i = 0; i < 3; i++) +            if (!movedEnough) +            { +                // We are in a dead zone +                // However we still have tracking so make sure we don't auto center +                QMutexLocker lock(&iDataLock); +                iBestTime.start(); +            } +            else +            { +                // Build deadzone rectangles if needed +                iTrackedRects.clear(); +                if (iDeadzoneHalfEdge != 0) // Check if deazones are enabled                  { -                    // Excluding top most point -                    if (i != topPointIndex && iPoints[i].x > maxX) +                    for (const cv::Point& pt : iTrackedPoints)                      { -                        maxX = iPoints[i].x; -                        rightPointIndex = i; +                        cv::Rect rect(pt - cv::Point(iDeadzoneHalfEdge, iDeadzoneHalfEdge), cv::Size(iDeadzoneEdge, iDeadzoneEdge)); +                        iTrackedRects.push_back(rect);                      }                  } -                // Find left most point -                int leftPointIndex = -1; -                for (int i = 0; i < 3; i++) +                dbgout << "Object: " << iModel << "\n"; +                dbgout << "Points: " << iTrackedPoints << "\n"; + +                iAngles.clear(); +                iBestSolutionIndex = -1; +                // Solve P3P problem with OpenCV +                int solutionCount = 0; +                if (iModel.size() == 3)                  { -                    // Excluding top most point -                    if (i != topPointIndex && i != rightPointIndex) +                    solutionCount = cv::solveP3P(iModel, iTrackedPoints, iCameraMatrix, iDistCoeffsMatrix, iRotations, iTranslations, iSolver); +                } +                else +                { +                    //Guess extrinsic boolean is only for ITERATIVE method, it will be set to false for all other method +                    cv::Mat rotation, translation; +                    // Init only needed for iterative, it's also useless as it is +                    rotation = cv::Mat::zeros(3, 1, CV_64FC1); +                    translation = cv::Mat::zeros(3, 1, CV_64FC1); +                    rotation.setTo(cv::Scalar(0)); +                    translation.setTo(cv::Scalar(0)); +                    ///// +                    iRotations.clear(); +                    iTranslations.clear(); +                    bool solved = cv::solvePnP(iModel, iTrackedPoints, iCameraMatrix, iDistCoeffsMatrix, rotation, translation, true, iSolver ); +                    if (solved)                      { -                        leftPointIndex = i; -                        break; +                        solutionCount = 1; +                        iRotations.push_back(rotation); +                        iTranslations.push_back(translation);                      }                  } -                // -                iTrackedPoints.push_back(iPoints[rightPointIndex]); -                iTrackedPoints.push_back(iPoints[leftPointIndex]); -                iTrackedPoints.push_back(iPoints[topPointIndex]); +                // Reset best solution index +                iBestSolutionIndex = -1; -                bool movedEnough = true; -                // Check if we moved enough since last time we were here -                // This is our deadzone management -                if (iSettings.DeadzoneRectHalfEdgeSize != 0 // Check if deazones are enabled -                    && iTrackedRects.size() == iTrackedPoints.size()) +                if (solutionCount > 0)                  { -                    movedEnough = false; -                    for (size_t i = 0; i < iTrackedPoints.size(); i++) +                    dbgout << "Solution count: " << solutionCount << "\n"; +                    int minPitch = std::numeric_limits<int>::max(); +                    // Find the solution we want amongst all possible ones +                    for (int i = 0; i < solutionCount; i++)                      { -                        if (!iTrackedRects[i].contains(iTrackedPoints[i])) +                        dbgout << "Translation:\n"; +                        dbgout << iTranslations.at(i); +                        dbgout << "\n"; +                        dbgout << "Rotation:\n"; +                        //dbgout << rvecs.at(i); +                        cv::Mat rotationCameraMatrix; +                        cv::Rodrigues(iRotations[i], rotationCameraMatrix); +                        cv::Vec3d angles; +                        getEulerAngles(rotationCameraMatrix, angles); +                        iAngles.push_back(angles); + +                        // Check if pitch is closest to zero +                        int absolutePitch = std::abs(angles[0]); +                        if (minPitch > absolutePitch)                          { -                            movedEnough = true; -                            break; +                            // The solution with pitch closest to zero is the one we want +                            minPitch = absolutePitch; +                            iBestSolutionIndex = i;                          } + +                        dbgout << angles; +                        dbgout << "\n";                      } + +                    dbgout << "\n";                  } -                if (movedEnough) +                if (iBestSolutionIndex != -1)                  { -                    // Build deadzone rectangles if needed -                    iTrackedRects.clear(); -                    if (iSettings.DeadzoneRectHalfEdgeSize != 0) // Check if deazones are enabled -                    { -                        for (const cv::Point& pt : iTrackedPoints) -                        { -                            cv::Rect rect(pt - cv::Point(iDeadzoneHalfEdge, iDeadzoneHalfEdge), cv::Size(iDeadzoneEdge, iDeadzoneEdge)); -                            iTrackedRects.push_back(rect); -                        } -                    } +                    // Best translation +                    cv::Vec3d translation = iTranslations[iBestSolutionIndex]; +                    // Best angles +                    cv::Vec3d angles = iAngles[iBestSolutionIndex]; -                    dbgout << "Object: " << iModel << "\n"; -                    dbgout << "Points: " << iTrackedPoints << "\n"; +                    // Pass solution through our kalman filter +                    iKf.Update(translation[0], translation[1], translation[2], angles[2], angles[0], angles[1]); -                    iAngles.clear(); -                    iBestSolutionIndex = -1; -                    // Solve P3P problem with OpenCV -                    int solutionCount = cv::solveP3P(iModel, iTrackedPoints, iCameraMatrix, iDistCoeffsMatrix, iRotations, iTranslations, iSolver); - -                    if (solutionCount > 0) +                    // Check if our solution makes sense +                    // For now, just discard solutions with extrem pitch  +                    if (std::abs(angles[0]) > 50) //TODO: Put that in settings                      { -                        dbgout << "Solution count: " << solutionCount << "\n"; -                        int minPitch = std::numeric_limits<int>::max(); -                        // Find the solution we want amongst all possible ones -                        for (int i = 0; i < solutionCount; i++) -                        { -                            dbgout << "Translation:\n"; -                            dbgout << iTranslations.at(i); -                            dbgout << "\n"; -                            dbgout << "Rotation:\n"; -                            //dbgout << rvecs.at(i); -                            cv::Mat rotationCameraMatrix; -                            cv::Rodrigues(iRotations[i], rotationCameraMatrix); -                            cv::Vec3d angles; -                            getEulerAngles(rotationCameraMatrix, angles); -                            iAngles.push_back(angles); - -                            // Check if pitch is closest to zero -                            int absolutePitch = std::abs(angles[0]); -                            if (minPitch > absolutePitch) -                            { -                                // The solution with pitch closest to zero is the one we want -                                minPitch = absolutePitch; -                                iBestSolutionIndex = i; -                            } - -                            dbgout << angles; -                            dbgout << "\n"; -                        } - -                        dbgout << "\n"; +                        infout << "WARNING: discarding solution!"; +                        iBadSolutionCount++; +                    } +                    else +                    { +                        iGoodSolutionCount++; +                        // We succeded in finding a solution to our PNP problem +                        ever_success.store(true, std::memory_order_relaxed); + +                        // Send solution data back to main thread +                        QMutexLocker l2(&iDataLock); +                        iBestAngles = angles; +                        iBestTranslation = translation; +                        iBestTime.start();                      } -                } -            } -                         -            if (iBestSolutionIndex != -1) -            { -                // Best translation -                cv::Vec3d translation = iTranslations[iBestSolutionIndex]; -                // Best angles -                cv::Vec3d angles = iAngles[iBestSolutionIndex]; - -                // Pass solution through our kalman filter -                iKf.Update(translation[0], translation[1], translation[2], angles[2], angles[0], angles[1]); - -                // Send solution data back to main thread -                QMutexLocker l2(&data_lock); -                iBestAngles = angles; -                iBestTranslation = translation; +                }              } -          }          if (doPreview)          { +            double qualityIndex = 1 - (iGoodSolutionCount!=0?(double)iBadSolutionCount / (double)iGoodSolutionCount:0);              std::ostringstream ss; -            ss << "FPS: " << iFps << "/" << iSkippedFps; +            ss << "FPS: " << iFps << "/" << iSkippedFps << "   QI: " << qualityIndex;              iPreview.DrawInfo(ss.str()); -            // +            //Color is BGR              if (topPointIndex != -1)              {                  // Render a cross to indicate which point is the head -                iPreview.DrawCross(iPoints[topPointIndex]); +                static const cv::Scalar color(0, 255, 255); // Yellow +                iPreview.DrawCross(iPoints[topPointIndex],color);              } +            if (rightPointIndex != -1) +            { +                static const cv::Scalar color(255, 0, 255); // Pink +                iPreview.DrawCross(iPoints[rightPointIndex], color); +            } + +            if (leftPointIndex != -1) +            { +                static const cv::Scalar color(255, 0, 0); // Blue                 +                iPreview.DrawCross(iPoints[leftPointIndex], color); +            } + +            if (centerPointIndex != -1) +            { +                static const cv::Scalar color(0, 255, 0); // Green +                iPreview.DrawCross(iPoints[centerPointIndex], color); +            } + +            if (topRightPointIndex != -1) +            { +                static const cv::Scalar color(0, 0, 255); // Red +                iPreview.DrawCross(iPoints[topRightPointIndex], color); +            } + +            if (topLeftPointIndex != -1) +            { +                static const cv::Scalar color(255, 255, 0); // Cyan +                iPreview.DrawCross(iPoints[topLeftPointIndex], color); +            } + +              // Render our deadzone rects              for (const cv::Rect& rect : iTrackedRects)              { @@ -320,7 +551,7 @@ namespace EasyTracker              }              // Show full size preview pop-up -            if (iSettings.debug) +            if (iDebug)              {                  cv::imshow("Preview", iPreview.iFrameRgb);                  cv::waitKey(1); @@ -340,7 +571,7 @@ namespace EasyTracker          else          {              // No preview, destroy preview pop-up -            if (iSettings.debug) +            if (iDebug)              {                  cv::destroyWindow("Preview");              } @@ -442,27 +673,54 @@ namespace EasyTracker          iKf.Init(18, 6, 0, dt);      } -    void Tracker::UpdateDeadzones(int aHalfEdgeSize) + +    /// +    /// Create our model from settings specifications +    /// +    void Tracker::UpdateModel()      { -        QMutexLocker l(¢er_lock); -        iDeadzoneHalfEdge = aHalfEdgeSize; -        iDeadzoneEdge = iDeadzoneHalfEdge * 2; -        iTrackedRects.clear(); -    } +        infout << "Update model"; +        QMutexLocker lock(&iProcessLock); +        // Construct the points defining the object we want to detect based on settings. +        // We are converting them from millimeters to centimeters. +        // TODO: Need to support clip too. That's cap only for now. +        iModel.clear(); +        iModel.push_back(cv::Point3f(iSettings.iVertexTopX / 10.0, iSettings.iVertexTopY / 10.0, iSettings.iVertexTopZ / 10.0)); // Top +        iModel.push_back(cv::Point3f(iSettings.iVertexRightX / 10.0, iSettings.iVertexRightY / 10.0, iSettings.iVertexRightZ / 10.0)); // Right +        iModel.push_back(cv::Point3f(iSettings.iVertexLeftX / 10.0, iSettings.iVertexLeftY / 10.0, iSettings.iVertexLeftZ / 10.0)); // Left -    void Tracker::UpdateSolver(int aSolver) -    { -        QMutexLocker l(¢er_lock); -        iSolver = aSolver; +        if (iSettings.iCustomModelFour) +        { +            iModel.push_back(cv::Point3f(iSettings.iVertexCenterX / 10.0, iSettings.iVertexCenterY / 10.0, iSettings.iVertexCenterZ / 10.0)); // Center +        } +        else if (iSettings.iCustomModelFive) +        { +            iModel.push_back(cv::Point3f(iSettings.iVertexTopRightX / 10.0, iSettings.iVertexTopRightY / 10.0, iSettings.iVertexTopRightZ / 10.0)); // Top Right +            iModel.push_back(cv::Point3f(iSettings.iVertexTopLeftX / 10.0, iSettings.iVertexTopLeftY / 10.0, iSettings.iVertexTopLeftZ / 10.0)); // Top Left +        }      } +    /// +    /// Take a copy of the settings needed by our thread to avoid deadlocks +    /// +    void Tracker::UpdateSettings() +    { +        infout << "Update Setting"; +        QMutexLocker l(&iProcessLock); +        iPointExtractor.UpdateSettings(); +        iSolver = iSettings.PnpSolver; +        iDeadzoneHalfEdge = iSettings.DeadzoneRectHalfEdgeSize; +        iDeadzoneEdge = iDeadzoneHalfEdge * 2; +        iTrackedRects.clear(); +        iDebug = iSettings.debug; +    } - +    ///      module_status Tracker::start_tracker(QFrame* video_frame)      {          // Check that we support that solver -        if (iSolver!=cv::SOLVEPNP_P3P && iSolver != cv::SOLVEPNP_AP3P) +        if (iSolver!=cv::SOLVEPNP_P3P && iSolver != cv::SOLVEPNP_AP3P && iModel.size()==3)          {              return module_status("Error: Solver not supported use either P3P or AP3P.");          } @@ -495,28 +753,47 @@ namespace EasyTracker      }      // +    void FeedData(double* aData, const cv::Vec3d& aAngles, const cv::Vec3d& aTranslation) +    { +        aData[Yaw] = aAngles[1]; +        aData[Pitch] = aAngles[0]; +        aData[Roll] = aAngles[2]; +        aData[TX] = aTranslation[0]; +        aData[TY] = aTranslation[1]; +        aData[TZ] = aTranslation[2]; +    } + +    //      // That's called around 250 times per second.      // Therefore we better not do anything here other than provide current data.      // -    void Tracker::data(double *data) +    void Tracker::data(double* aData)      {          if (ever_success.load(std::memory_order_relaxed))          {              // Get data back from tracker thread -            QMutexLocker l(&data_lock); -            data[Yaw] = iBestAngles[1]; -            data[Pitch] = iBestAngles[0]; -            data[Roll] = iBestAngles[2]; -            data[TX] = iBestTranslation[0]; -            data[TY] = iBestTranslation[1]; -            data[TZ] = iBestTranslation[2]; +            QMutexLocker l(&iDataLock); +            // If there was no new data recently then we provide center data. +            // Basically, if our user remove her hat, we will go back to center position until she puts it back on. +            if (iSettings.iAutoCenter && iBestTime.elapsed_ms() > iSettings.iAutoCenterTimeout) +            { +                // Reset to center until we get new data +                FeedData(aData, iCenterAngles, iCenterTranslation); +            } +            else +            { +                // We got valid data, provide it +                FeedData(aData, iBestAngles, iBestTranslation); +            }          }      }      bool Tracker::center()      { -        QMutexLocker l(¢er_lock); -        //TODO: Do we need to do anything there? +        QMutexLocker l(&iDataLock); +        iCenterTranslation = iBestTranslation; +        iCenterAngles = iBestAngles; +        // Returning false tells the pipeline we want to use the default center behaviour          return false;      } diff --git a/tracker-easy/tracker-easy.h b/tracker-easy/tracker-easy.h index 41226d23..952f05a4 100644 --- a/tracker-easy/tracker-easy.h +++ b/tracker-easy/tracker-easy.h @@ -33,6 +33,19 @@  namespace EasyTracker  { +    namespace VertexPosition +    { +        enum Type +        { +            Top = 0, +            Right, +            Left, +            TopRight, +            TopLeft, +            Center +        }; +    } +      static const QString KModuleName = "tracker-easy";      class Dialog; @@ -58,9 +71,13 @@ namespace EasyTracker      private: -        void CreateModelFromSettings(); +        void UpdateModel();          void CreateCameraIntrinsicsMatrices(); -        void ProcessFrame(); +        void ProcessFrame();         +        void MatchVertices(int& aTopIndex, int& aRightIndex, int& aLeftIndex, int& aCenterIndex, int& aTopRight, int& aTopLeft); +        void MatchThreeOrFourVertices(int& aTopIndex, int& aRightIndex, int& aLeftIndex, int& aCenterIndex); +        void MatchFiveVertices(int& aTopIndex, int& aRightIndex, int& aLeftIndex, int& aTopRight, int& aTopLeft); +                  // @@ -68,8 +85,7 @@ namespace EasyTracker          void set_fov(int value);          void SetFps(int aFps);          void DoSetFps(int aFps); -        void UpdateDeadzones(int aHalfEdgeSize); -        void UpdateSolver(int aSolver); +        void UpdateSettings();          QMutex camera_mtx;          QThread iThread; @@ -93,14 +109,16 @@ namespace EasyTracker          Preview iPreview;          std::atomic<bool> ever_success = false; -        mutable QMutex center_lock, data_lock; +        mutable QMutex iProcessLock, iDataLock; +        //// Copy the settings need by our thread to avoid dead locks          // Deadzone          int iDeadzoneEdge=0;          int iDeadzoneHalfEdge=0; -          // Solver          int iSolver = cv::SOLVEPNP_P3P; +        bool iDebug = false; +        ////          // Statistics          Timer iTimer; @@ -109,6 +127,8 @@ namespace EasyTracker          int iSkippedFrameCount = 0;          int iFps = 0;          int iSkippedFps = 0; +        uint iBadSolutionCount = 0; +        uint iGoodSolutionCount = 0;          //          KalmanFilterPose iKf; @@ -136,6 +156,12 @@ namespace EasyTracker          cv::Vec3d iBestTranslation;          // Best angles          cv::Vec3d iBestAngles; +        // Time at which we found our last best solution +        Timer iBestTime; +        // Center translation +        cv::Vec3d iCenterTranslation = {0,0,0}; +        // Center angles +        cv::Vec3d iCenterAngles = { 0,0,0 };      };  } | 
