summaryrefslogtreecommitdiffhomepage
path: root/ftnoir_tracker_ht
diff options
context:
space:
mode:
Diffstat (limited to 'ftnoir_tracker_ht')
-rw-r--r--ftnoir_tracker_ht/ftnoir_tracker_ht.cpp106
-rw-r--r--ftnoir_tracker_ht/ftnoir_tracker_ht.h6
-rw-r--r--ftnoir_tracker_ht/ftnoir_tracker_ht_dll.h4
-rw-r--r--ftnoir_tracker_ht/ht-api.h56
-rw-r--r--ftnoir_tracker_ht/images/ht.icobin0 -> 15086 bytes
-rw-r--r--ftnoir_tracker_ht/trackercontrols.ui301
-rw-r--r--ftnoir_tracker_ht/video_widget.cpp69
-rw-r--r--ftnoir_tracker_ht/video_widget.h42
8 files changed, 512 insertions, 72 deletions
diff --git a/ftnoir_tracker_ht/ftnoir_tracker_ht.cpp b/ftnoir_tracker_ht/ftnoir_tracker_ht.cpp
index 336ede2d..5785b21a 100644
--- a/ftnoir_tracker_ht/ftnoir_tracker_ht.cpp
+++ b/ftnoir_tracker_ht/ftnoir_tracker_ht.cpp
@@ -1,13 +1,11 @@
#include "stdafx.h"
-#include "../ftnoir_tracker_base/ftnoir_tracker_base.h"
+#include "ftnoir_tracker_base/ftnoir_tracker_base.h"
#include "headtracker-ftnoir.h"
#include "ftnoir_tracker_ht.h"
#include "ftnoir_tracker_ht_dll.h"
#include "ui_trackercontrols.h"
-#include "../facetracknoir/global-settings.h"
-
-#define WIDGET_WIDTH 250
-#define WIDGET_HEIGHT 188
+#include "facetracknoir/global-settings.h"
+#include <cmath>
#if defined(_WIN32) || defined(__WIN32)
#include <dshow.h>
@@ -98,31 +96,48 @@ static void load_settings(ht_config_t* config, Tracker* tracker)
QSettings iniFile( currentFile, QSettings::IniFormat );
iniFile.beginGroup( "HT-Tracker" );
- config->classification_delay = 4000;
- config->field_of_view = iniFile.value("fov", 69).toFloat();
+ config->classification_delay = 500;
+ config->field_of_view = iniFile.value("fov", 52).toFloat();
config->pyrlk_pyramids = 3;
- config->pyrlk_win_size_w = config->pyrlk_win_size_h = 21;
- config->max_keypoints = 250;
- config->keypoint_quality = 12;
- config->keypoint_distance = 2.3f;
- config->keypoint_3distance = 6;
- //config->force_width = 640;
- //config->force_height = 480;
- config->force_fps = iniFile.value("fps", 0).toInt();
- config->camera_index = iniFile.value("camera-index", -1).toInt();
- config->ransac_num_iters = 100;
- config->ransac_max_reprojection_error = 6.5f;
- config->ransac_max_inlier_error = 6.5f;
- config->ransac_max_mean_error = 4.0f;
- config->ransac_abs_max_mean_error = 7.0f;
- config->debug = 0;
- config->ransac_min_features = 0.75f;
+ config->pyrlk_win_size_w = config->pyrlk_win_size_h = 21;
+ config->max_keypoints = 300;
+ config->keypoint_quality = 2;
+ config->keypoint_distance = 2.5;
+ config->keypoint_3distance = 6;
+ //config->force_width = 640;
+ //config->force_height = 480;
+ config->force_fps = iniFile.value("fps", 0).toInt();
+ config->camera_index = iniFile.value("camera-index", -1).toInt();
+ config->ransac_num_iters = 100;
+ config->ransac_max_reprojection_error = 3.63637;
+ config->ransac_max_inlier_error = 3;
+ config->ransac_max_mean_error = 3.5;
+ config->ransac_abs_max_mean_error = 7;
+ config->debug = 1;
+ config->ransac_min_features = 0.80;
int res = iniFile.value("resolution", 0).toInt();
if (res < 0 || res >= (int)(sizeof(*resolution_choices) / sizeof(resolution_tuple)))
res = 0;
resolution_tuple r = resolution_choices[res];
config->force_width = r.width;
- config->force_height = r.height;
+ config->force_height = r.height;
+ config->user_landmarks = iniFile.value("use-bashed-coords").toBool();
+ if (config->user_landmarks)
+ {
+ config->user_landmark_locations[0][0] = iniFile.value("b1").toDouble();
+ config->user_landmark_locations[1][0] = iniFile.value("b2").toDouble();
+ config->user_landmark_locations[2][0] = iniFile.value("b3").toDouble();
+ config->user_landmark_locations[0][1] = iniFile.value("b4").toDouble();
+ config->user_landmark_locations[1][1] = iniFile.value("b5").toDouble();
+ config->user_landmark_locations[2][1] = iniFile.value("b6").toDouble();
+ config->user_landmark_locations[0][2] = iniFile.value("b7").toDouble();
+ config->user_landmark_locations[1][2] = iniFile.value("b8").toDouble();
+ config->user_landmark_locations[2][2] = iniFile.value("b9").toDouble();
+ config->user_landmark_locations[0][3] = iniFile.value("b10").toDouble();
+ config->user_landmark_locations[1][3] = iniFile.value("b11").toDouble();
+ config->user_landmark_locations[2][3] = iniFile.value("b12").toDouble();
+ }
+ qDebug() << "width" << r.width << "height" << r.height;
if (tracker)
{
tracker->enableRX = iniFile.value("enable-rx", true).toBool();
@@ -159,7 +174,6 @@ Tracker::~Tracker()
void Tracker::StartTracker(QFrame* videoframe)
{
- videoframe->setAttribute(Qt::WA_NativeWindow);
videoframe->show();
videoWidget = new VideoWidget(videoframe);
QHBoxLayout* layout = new QHBoxLayout();
@@ -168,7 +182,6 @@ void Tracker::StartTracker(QFrame* videoframe)
if (videoframe->layout())
delete videoframe->layout();
videoframe->setLayout(layout);
- videoWidget->resize(WIDGET_WIDTH, WIDGET_HEIGHT);
videoWidget->show();
this->layout = layout;
load_settings(&shm->config, this);
@@ -181,8 +194,8 @@ void Tracker::StartTracker(QFrame* videoframe)
#else
subprocess.start(QCoreApplication::applicationDirPath() + "/tracker-ht/headtracker-ftnoir");
#endif
- connect(&timer, SIGNAL(timeout()), this, SLOT(paint_widget()));
- timer.start(15);
+ connect(&timer, SIGNAL(timeout()), this, SLOT(paint_widget()), Qt::QueuedConnection);
+ timer.start(40);
}
void Tracker::paint_widget() {
@@ -209,8 +222,12 @@ bool Tracker::GiveHeadPoseData(THeadPoseData* data)
data->yaw = shm->result.rotx;
if (enableRY)
data->pitch = shm->result.roty;
- if (enableRZ)
+ if (enableRZ) {
data->roll = shm->result.rotz;
+ double sign = data->roll >= 0 ? 1 : -1;
+ if (fabs(fabs(data->roll) - 180) < fabs(data->roll))
+ data->roll = fabs(fabs(data->roll) - 180) * sign;
+ }
if (enableTX)
data->x = shm->result.tx;
if (enableTY)
@@ -227,7 +244,7 @@ bool Tracker::GiveHeadPoseData(THeadPoseData* data)
//-----------------------------------------------------------------------------
void TrackerDll::getFullName(QString *strToBeFilled)
{
- *strToBeFilled = "HT 0.7";
+ *strToBeFilled = "HT 0.8";
}
void TrackerDll::getShortName(QString *strToBeFilled)
@@ -278,7 +295,6 @@ extern "C" FTNOIR_TRACKER_BASE_EXPORT void* CALLING_CONVENTION GetDialog( )
TrackerControls::TrackerControls()
{
ui.setupUi(this);
- loadSettings();
connect(ui.cameraName, SIGNAL(currentIndexChanged(int)), this, SLOT(settingChanged(int)));
connect(ui.cameraFPS, SIGNAL(currentIndexChanged(int)), this, SLOT(settingChanged(int)));
connect(ui.cameraFOV, SIGNAL(valueChanged(double)), this, SLOT(settingChanged(double)));
@@ -290,6 +306,7 @@ TrackerControls::TrackerControls()
connect(ui.tz, SIGNAL(stateChanged(int)), this, SLOT(settingChanged(int)));
connect(ui.buttonCancel, SIGNAL(clicked()), this, SLOT(doCancel()));
connect(ui.buttonOK, SIGNAL(clicked()), this, SLOT(doOK()));
+ loadSettings();
settingsDirty = false;
}
@@ -303,6 +320,7 @@ void TrackerControls::showEvent(QShowEvent *event)
void TrackerControls::Initialize(QWidget* parent)
{
+ loadSettings();
show();
}
@@ -343,6 +361,19 @@ void TrackerControls::loadSettings()
ui.ty->setCheckState(iniFile.value("enable-ty", true).toBool() ? Qt::Checked : Qt::Unchecked);
ui.tz->setCheckState(iniFile.value("enable-tz", true).toBool() ? Qt::Checked : Qt::Unchecked);
ui.resolution->setCurrentIndex(iniFile.value("resolution", 0).toInt());
+ ui.groupBox_2->setChecked(iniFile.value("use-bashed-coords").toBool());
+ ui.doubleSpinBox_1->setValue(iniFile.value("b1", 0).toDouble());
+ ui.doubleSpinBox_2->setValue(iniFile.value("b2", 0).toDouble());
+ ui.doubleSpinBox_3->setValue(iniFile.value("b3", 0).toDouble());
+ ui.doubleSpinBox_4->setValue(iniFile.value("b4", 0).toDouble());
+ ui.doubleSpinBox_5->setValue(iniFile.value("b5", 0).toDouble());
+ ui.doubleSpinBox_6->setValue(iniFile.value("b6", 0).toDouble());
+ ui.doubleSpinBox_7->setValue(iniFile.value("b7", 0).toDouble());
+ ui.doubleSpinBox_8->setValue(iniFile.value("b8", 0).toDouble());
+ ui.doubleSpinBox_9->setValue(iniFile.value("b9", 0).toDouble());
+ ui.doubleSpinBox_10->setValue(iniFile.value("b10", 0).toDouble());
+ ui.doubleSpinBox_11->setValue(iniFile.value("b11", 0).toDouble());
+ ui.doubleSpinBox_12->setValue(iniFile.value("b12", 0).toDouble());
iniFile.endGroup();
settingsDirty = false;
}
@@ -381,6 +412,19 @@ void TrackerControls::save()
iniFile.setValue("enable-ty", ui.ty->checkState() != Qt::Unchecked ? true : false);
iniFile.setValue("enable-tz", ui.tz->checkState() != Qt::Unchecked ? true : false);
iniFile.setValue("resolution", ui.resolution->currentIndex());
+ iniFile.setValue("b1", ui.doubleSpinBox_1->value());
+ iniFile.setValue("b2", ui.doubleSpinBox_2->value());
+ iniFile.setValue("b3", ui.doubleSpinBox_3->value());
+ iniFile.setValue("b4", ui.doubleSpinBox_4->value());
+ iniFile.setValue("b5", ui.doubleSpinBox_5->value());
+ iniFile.setValue("b6", ui.doubleSpinBox_6->value());
+ iniFile.setValue("b7", ui.doubleSpinBox_7->value());
+ iniFile.setValue("b8", ui.doubleSpinBox_8->value());
+ iniFile.setValue("b9", ui.doubleSpinBox_9->value());
+ iniFile.setValue("b10", ui.doubleSpinBox_10->value());
+ iniFile.setValue("b11", ui.doubleSpinBox_11->value());
+ iniFile.setValue("b12", ui.doubleSpinBox_12->value());
+ iniFile.setValue("use-bashed-coords", ui.groupBox_2->isChecked());
iniFile.endGroup();
settingsDirty = false;
}
diff --git a/ftnoir_tracker_ht/ftnoir_tracker_ht.h b/ftnoir_tracker_ht/ftnoir_tracker_ht.h
index 1a449dca..f5d0c271 100644
--- a/ftnoir_tracker_ht/ftnoir_tracker_ht.h
+++ b/ftnoir_tracker_ht/ftnoir_tracker_ht.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013 Stanislaw Halik <sthalik@misaki.pl>
+/* Copyright (c) 2013 Stanisław Halik <sthalik@misaki.pl>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -9,11 +9,11 @@
#define FTNOIR_TRACKER_HT_H
#include "stdafx.h"
-#include "../ftnoir_tracker_base/ftnoir_tracker_base.h"
+#include "ftnoir_tracker_base/ftnoir_tracker_base.h"
#include "headtracker-ftnoir.h"
#include "ui_trackercontrols.h"
#include "video_widget.h"
-#include "../compat/compat.h"
+#include "compat/compat.h"
#include <QObject>
#include <QTimer>
diff --git a/ftnoir_tracker_ht/ftnoir_tracker_ht_dll.h b/ftnoir_tracker_ht/ftnoir_tracker_ht_dll.h
index f3bfd381..1e53f802 100644
--- a/ftnoir_tracker_ht/ftnoir_tracker_ht_dll.h
+++ b/ftnoir_tracker_ht/ftnoir_tracker_ht_dll.h
@@ -5,8 +5,8 @@
* copyright notice and this permission notice appear in all copies.
*/
-#include "../ftnoir_tracker_base/ftnoir_tracker_base.h"
-#include "../facetracknoir/global-settings.h"
+#include "ftnoir_tracker_base/ftnoir_tracker_base.h"
+#include "facetracknoir/global-settings.h"
//-----------------------------------------------------------------------------
class TrackerDll : public Metadata
diff --git a/ftnoir_tracker_ht/ht-api.h b/ftnoir_tracker_ht/ht-api.h
index ac8d45cf..81caf16f 100644
--- a/ftnoir_tracker_ht/ht-api.h
+++ b/ftnoir_tracker_ht/ht-api.h
@@ -1,9 +1,9 @@
#pragma once
#ifndef HT_API
#ifndef __cplusplus
-# define HT_EXTERN
+# define HT_EXTERN
#else
-# define HT_EXTERN extern "C"
+# define HT_EXTERN extern "C"
#endif
# if defined(_WIN32) && !defined(MINGW)
# define HT_API(t) HT_EXTERN __declspec(dllexport) t __stdcall
@@ -19,56 +19,58 @@ struct ht_context;
typedef struct ht_context headtracker_t;
typedef struct ht_config {
- float field_of_view;
- float classification_delay;
- int pyrlk_pyramids;
- int pyrlk_win_size_w;
- int pyrlk_win_size_h;
+ float field_of_view;
+ float classification_delay;
+ int pyrlk_pyramids;
+ int pyrlk_win_size_w;
+ int pyrlk_win_size_h;
float ransac_max_inlier_error;
float ransac_max_reprojection_error;
- int max_keypoints;
+ int max_keypoints;
int keypoint_quality;
- float keypoint_distance;
+ float keypoint_distance;
float keypoint_3distance;
int force_width;
- int force_height;
- int force_fps;
- int camera_index;
- bool debug;
+ int force_height;
+ int force_fps;
+ int camera_index;
+ bool debug;
int ransac_num_iters;
float ransac_min_features;
float ransac_max_mean_error;
float ransac_abs_max_mean_error;
+ bool user_landmarks;
+ float user_landmark_locations[3][4];
} ht_config_t;
typedef struct {
double rotx, roty, rotz;
double tx, ty, tz;
- bool filled;
+ bool filled;
} ht_result_t;
typedef enum {
- cfg_type_float = 0,
- cfg_type_int = 1,
- cfg_type_bool = 2,
+ cfg_type_float = 0,
+ cfg_type_int = 1,
+ cfg_type_bool = 2,
cfg_type_double = 3
} ht_cfg_type_t;
typedef union
{
- double d;
- float f;
- int i;
+ double d;
+ float f;
+ int i;
} ht_cfg_value_t;
typedef struct {
- const char* name;
- int offset;
- ht_cfg_type_t type;
- ht_cfg_value_t default_value;
- ht_cfg_value_t min;
- ht_cfg_value_t max;
- const char* docstring;
+ const char* name;
+ int offset;
+ ht_cfg_type_t type;
+ ht_cfg_value_t default_value;
+ ht_cfg_value_t min;
+ ht_cfg_value_t max;
+ const char* docstring;
} ht_reflection_t;
typedef struct {
diff --git a/ftnoir_tracker_ht/images/ht.ico b/ftnoir_tracker_ht/images/ht.ico
new file mode 100644
index 00000000..7555ce25
--- /dev/null
+++ b/ftnoir_tracker_ht/images/ht.ico
Binary files differ
diff --git a/ftnoir_tracker_ht/trackercontrols.ui b/ftnoir_tracker_ht/trackercontrols.ui
index 0a1bc3ae..2f4b1915 100644
--- a/ftnoir_tracker_ht/trackercontrols.ui
+++ b/ftnoir_tracker_ht/trackercontrols.ui
@@ -9,19 +9,19 @@
<rect>
<x>0</x>
<y>0</y>
- <width>500</width>
+ <width>724</width>
<height>160</height>
</rect>
</property>
<property name="sizePolicy">
- <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
- <width>500</width>
+ <width>750</width>
<height>160</height>
</size>
</property>
@@ -38,7 +38,7 @@
</rect>
</property>
<property name="text">
- <string>Horizontal field of view</string>
+ <string>Horizontal FOV</string>
</property>
</widget>
<widget class="QDoubleSpinBox" name="cameraFOV">
@@ -68,7 +68,7 @@
<rect>
<x>10</x>
<y>40</y>
- <width>101</width>
+ <width>137</width>
<height>16</height>
</rect>
</property>
@@ -111,7 +111,7 @@
<rect>
<x>10</x>
<y>70</y>
- <width>71</width>
+ <width>133</width>
<height>16</height>
</rect>
</property>
@@ -122,7 +122,7 @@
<widget class="QPushButton" name="buttonOK">
<property name="geometry">
<rect>
- <x>340</x>
+ <x>220</x>
<y>130</y>
<width>75</width>
<height>23</height>
@@ -135,7 +135,7 @@
<widget class="QPushButton" name="buttonCancel">
<property name="geometry">
<rect>
- <x>420</x>
+ <x>300</x>
<y>130</y>
<width>75</width>
<height>23</height>
@@ -251,7 +251,7 @@
<rect>
<x>10</x>
<y>100</y>
- <width>61</width>
+ <width>128</width>
<height>16</height>
</rect>
</property>
@@ -289,6 +289,289 @@
</property>
</item>
</widget>
+ <widget class="QGroupBox" name="groupBox_2">
+ <property name="geometry">
+ <rect>
+ <x>500</x>
+ <y>10</y>
+ <width>221</width>
+ <height>141</height>
+ </rect>
+ </property>
+ <property name="title">
+ <string>Bashed coordinates</string>
+ </property>
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="checked">
+ <bool>false</bool>
+ </property>
+ <widget class="QDoubleSpinBox" name="doubleSpinBox_1">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>20</y>
+ <width>61</width>
+ <height>22</height>
+ </rect>
+ </property>
+ <property name="frame">
+ <bool>true</bool>
+ </property>
+ <property name="buttonSymbols">
+ <enum>QAbstractSpinBox::NoButtons</enum>
+ </property>
+ <property name="decimals">
+ <number>5</number>
+ </property>
+ <property name="minimum">
+ <double>-99.000000000000000</double>
+ </property>
+ </widget>
+ <widget class="QDoubleSpinBox" name="doubleSpinBox_2">
+ <property name="geometry">
+ <rect>
+ <x>80</x>
+ <y>20</y>
+ <width>61</width>
+ <height>22</height>
+ </rect>
+ </property>
+ <property name="frame">
+ <bool>true</bool>
+ </property>
+ <property name="buttonSymbols">
+ <enum>QAbstractSpinBox::NoButtons</enum>
+ </property>
+ <property name="decimals">
+ <number>5</number>
+ </property>
+ <property name="minimum">
+ <double>-99.000000000000000</double>
+ </property>
+ </widget>
+ <widget class="QDoubleSpinBox" name="doubleSpinBox_3">
+ <property name="geometry">
+ <rect>
+ <x>150</x>
+ <y>20</y>
+ <width>61</width>
+ <height>22</height>
+ </rect>
+ </property>
+ <property name="frame">
+ <bool>true</bool>
+ </property>
+ <property name="buttonSymbols">
+ <enum>QAbstractSpinBox::NoButtons</enum>
+ </property>
+ <property name="decimals">
+ <number>5</number>
+ </property>
+ <property name="minimum">
+ <double>-99.000000000000000</double>
+ </property>
+ </widget>
+ <widget class="QDoubleSpinBox" name="doubleSpinBox_6">
+ <property name="geometry">
+ <rect>
+ <x>150</x>
+ <y>50</y>
+ <width>61</width>
+ <height>22</height>
+ </rect>
+ </property>
+ <property name="frame">
+ <bool>true</bool>
+ </property>
+ <property name="buttonSymbols">
+ <enum>QAbstractSpinBox::NoButtons</enum>
+ </property>
+ <property name="decimals">
+ <number>5</number>
+ </property>
+ <property name="minimum">
+ <double>-99.000000000000000</double>
+ </property>
+ </widget>
+ <widget class="QDoubleSpinBox" name="doubleSpinBox_4">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>50</y>
+ <width>61</width>
+ <height>22</height>
+ </rect>
+ </property>
+ <property name="frame">
+ <bool>true</bool>
+ </property>
+ <property name="buttonSymbols">
+ <enum>QAbstractSpinBox::NoButtons</enum>
+ </property>
+ <property name="decimals">
+ <number>5</number>
+ </property>
+ <property name="minimum">
+ <double>-99.000000000000000</double>
+ </property>
+ </widget>
+ <widget class="QDoubleSpinBox" name="doubleSpinBox_5">
+ <property name="geometry">
+ <rect>
+ <x>80</x>
+ <y>50</y>
+ <width>61</width>
+ <height>22</height>
+ </rect>
+ </property>
+ <property name="frame">
+ <bool>true</bool>
+ </property>
+ <property name="buttonSymbols">
+ <enum>QAbstractSpinBox::NoButtons</enum>
+ </property>
+ <property name="decimals">
+ <number>5</number>
+ </property>
+ <property name="minimum">
+ <double>-99.000000000000000</double>
+ </property>
+ </widget>
+ <widget class="QDoubleSpinBox" name="doubleSpinBox_9">
+ <property name="geometry">
+ <rect>
+ <x>150</x>
+ <y>80</y>
+ <width>61</width>
+ <height>22</height>
+ </rect>
+ </property>
+ <property name="frame">
+ <bool>true</bool>
+ </property>
+ <property name="buttonSymbols">
+ <enum>QAbstractSpinBox::NoButtons</enum>
+ </property>
+ <property name="decimals">
+ <number>5</number>
+ </property>
+ <property name="minimum">
+ <double>-99.000000000000000</double>
+ </property>
+ </widget>
+ <widget class="QDoubleSpinBox" name="doubleSpinBox_7">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>80</y>
+ <width>61</width>
+ <height>22</height>
+ </rect>
+ </property>
+ <property name="frame">
+ <bool>true</bool>
+ </property>
+ <property name="buttonSymbols">
+ <enum>QAbstractSpinBox::NoButtons</enum>
+ </property>
+ <property name="decimals">
+ <number>5</number>
+ </property>
+ <property name="minimum">
+ <double>-99.000000000000000</double>
+ </property>
+ </widget>
+ <widget class="QDoubleSpinBox" name="doubleSpinBox_8">
+ <property name="geometry">
+ <rect>
+ <x>80</x>
+ <y>80</y>
+ <width>61</width>
+ <height>22</height>
+ </rect>
+ </property>
+ <property name="frame">
+ <bool>true</bool>
+ </property>
+ <property name="buttonSymbols">
+ <enum>QAbstractSpinBox::NoButtons</enum>
+ </property>
+ <property name="decimals">
+ <number>5</number>
+ </property>
+ <property name="minimum">
+ <double>-99.000000000000000</double>
+ </property>
+ </widget>
+ <widget class="QDoubleSpinBox" name="doubleSpinBox_12">
+ <property name="geometry">
+ <rect>
+ <x>150</x>
+ <y>110</y>
+ <width>61</width>
+ <height>22</height>
+ </rect>
+ </property>
+ <property name="frame">
+ <bool>true</bool>
+ </property>
+ <property name="buttonSymbols">
+ <enum>QAbstractSpinBox::NoButtons</enum>
+ </property>
+ <property name="decimals">
+ <number>5</number>
+ </property>
+ <property name="minimum">
+ <double>-99.000000000000000</double>
+ </property>
+ </widget>
+ <widget class="QDoubleSpinBox" name="doubleSpinBox_11">
+ <property name="geometry">
+ <rect>
+ <x>80</x>
+ <y>110</y>
+ <width>61</width>
+ <height>22</height>
+ </rect>
+ </property>
+ <property name="frame">
+ <bool>true</bool>
+ </property>
+ <property name="buttonSymbols">
+ <enum>QAbstractSpinBox::NoButtons</enum>
+ </property>
+ <property name="decimals">
+ <number>5</number>
+ </property>
+ <property name="minimum">
+ <double>-99.000000000000000</double>
+ </property>
+ </widget>
+ <widget class="QDoubleSpinBox" name="doubleSpinBox_10">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>110</y>
+ <width>61</width>
+ <height>22</height>
+ </rect>
+ </property>
+ <property name="frame">
+ <bool>true</bool>
+ </property>
+ <property name="buttonSymbols">
+ <enum>QAbstractSpinBox::NoButtons</enum>
+ </property>
+ <property name="decimals">
+ <number>5</number>
+ </property>
+ <property name="minimum">
+ <double>-99.000000000000000</double>
+ </property>
+ </widget>
+ </widget>
</widget>
<resources/>
<connections/>
diff --git a/ftnoir_tracker_ht/video_widget.cpp b/ftnoir_tracker_ht/video_widget.cpp
new file mode 100644
index 00000000..51d92967
--- /dev/null
+++ b/ftnoir_tracker_ht/video_widget.cpp
@@ -0,0 +1,69 @@
+/* Copyright (c) 2012 Patrick Ruoff
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ */
+
+#include "video_widget.h"
+
+#include <QDebug>
+
+using namespace std;
+
+// ----------------------------------------------------------------------------
+void VideoWidget::initializeGL()
+{
+ glClearColor(0.0, 0.0, 0.0, 0.0);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+}
+
+void VideoWidget::resizeGL(int w, int h)
+{
+ // setup 1 to 1 projection
+ glViewport(0, 0, w, h);
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glOrtho(0, w, 0, h, -1, 1);
+ resize_frame(resized_qframe);
+ glDisable(GL_DEPTH_TEST);
+ glBegin(GL_QUADS);
+ glVertex2f(0,0);
+ glVertex2f(1,0);
+ glVertex2f(1,1);
+ glVertex2f(0,1);
+ glEnd();
+}
+
+void VideoWidget::paintGL()
+{
+ QMutexLocker lck(&mtx);
+ if (resized_qframe.size() == size() || (resized_qframe.width() <= width() && resized_qframe.height() <= height()))
+ {
+ glDrawPixels(resized_qframe.width(), resized_qframe.height(), GL_RGB, GL_UNSIGNED_BYTE, resized_qframe.bits());
+ }
+ else
+ glClear(GL_DEPTH_BUFFER_BIT);
+ glFlush();
+}
+
+void VideoWidget::resize_frame(QImage& qframe)
+{
+ QMutexLocker lck(&mtx);
+ if (qframe.size() == size() || (qframe.width() <= width() && qframe.height() <= height()))
+ resized_qframe = qframe.copy();
+ else
+ resized_qframe = qframe.scaled(size(), Qt::IgnoreAspectRatio, Qt::FastTransformation).copy();
+}
+
+
+void VideoWidget::updateImage(unsigned char *frame, int width, int height)
+{
+ QImage foo = QImage(frame, width, height, 3 * width, QImage::Format_RGB888).rgbSwapped().mirrored();
+ resize_frame(foo);
+}
+
+void VideoWidget::update() {
+ updateGL();
+}
diff --git a/ftnoir_tracker_ht/video_widget.h b/ftnoir_tracker_ht/video_widget.h
new file mode 100644
index 00000000..adc57335
--- /dev/null
+++ b/ftnoir_tracker_ht/video_widget.h
@@ -0,0 +1,42 @@
+/* Copyright (c) 2012 Patrick Ruoff
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ */
+
+#ifndef VIDEOWIDGET_H
+#define VIDEOWIDGET_H
+
+#include <QGLWidget>
+#include <QTime>
+#include <QFrame>
+#include <QImage>
+#include <QWidget>
+#include <QMutex>
+#include <QMutexLocker>
+// ----------------------------------------------------------------------------
+class VideoWidget : public QGLWidget
+{
+ Q_OBJECT
+
+public:
+ VideoWidget(QWidget *parent) : QGLWidget(parent) {
+#if !defined(_WIN32)
+ setAttribute(Qt::WA_NativeWindow, true);
+#endif
+ }
+
+ void initializeGL();
+ void resizeGL(int w, int h);
+ void paintGL();
+
+ void updateImage(unsigned char* frame, int width, int height);
+ void update();
+private:
+ void resize_frame(QImage& qframe);
+ QImage resized_qframe;
+ QMutex mtx;
+};
+
+#endif // VIDEOWIDGET_H