summaryrefslogtreecommitdiffhomepage
path: root/tracker-ht/ftnoir_tracker_ht.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tracker-ht/ftnoir_tracker_ht.cpp')
-rw-r--r--tracker-ht/ftnoir_tracker_ht.cpp225
1 files changed, 225 insertions, 0 deletions
diff --git a/tracker-ht/ftnoir_tracker_ht.cpp b/tracker-ht/ftnoir_tracker_ht.cpp
new file mode 100644
index 00000000..cc9d2ba1
--- /dev/null
+++ b/tracker-ht/ftnoir_tracker_ht.cpp
@@ -0,0 +1,225 @@
+#include "headtracker-ftnoir.h"
+#include "ftnoir_tracker_ht.h"
+#include "ui_ht-trackercontrols.h"
+#include "opentrack/plugin-api.hpp"
+#include <cmath>
+#include "opentrack/camera-names.hpp"
+#include "opentrack-compat/sleep.hpp"
+
+typedef struct {
+ int width;
+ int height;
+} resolution_tuple;
+
+static resolution_tuple resolution_choices[] = {
+ { 640, 480 },
+ { 320, 240 },
+ { 320, 200 },
+ { 0, 0 }
+};
+
+void Tracker::load_settings(ht_config_t* config)
+{
+ int nframes = 0;
+ switch (static_cast<int>(s.fps))
+ {
+ default:
+ case 0:
+ nframes = 0;
+ break;
+ case 1:
+ nframes = 30;
+ break;
+ case 2:
+ nframes = 60;
+ break;
+ case 3:
+ nframes = 120;
+ break;
+ case 4:
+ nframes = 180;
+ break;
+ }
+
+ config->classification_delay = 500;
+ config->field_of_view = s.fov;
+ config->max_keypoints = 150;
+ config->keypoint_distance = 3.5;
+ config->force_fps = nframes;
+ config->camera_index = camera_name_to_index(s.camera_name);
+
+ config->ransac_max_reprojection_error = 25;
+ config->ransac_max_inlier_error = config->ransac_max_reprojection_error;
+
+ config->pyrlk_pyramids = 0;
+ config->pyrlk_win_size_w = config->pyrlk_win_size_h = 21;
+
+ config->ransac_max_mean_error = 999;
+ config->ransac_abs_max_mean_error = 999;
+
+ config->debug = 1;
+ config->ransac_min_features = 0.95;
+ config->ransac_num_iters = 300;
+
+ int res = s.resolution;
+ 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->flandmark_delay = 50;
+ for (int i = 0; i < 5; i++)
+ config->dist_coeffs[i] = 0;
+}
+
+Tracker::Tracker() :
+ ht(nullptr),
+ ypr {0,0,0, 0,0,0},
+ videoWidget(nullptr),
+ layout(nullptr),
+ should_stop(false)
+{
+}
+
+Tracker::~Tracker()
+{
+ should_stop = true;
+ wait();
+ ht_free_context(ht);
+ if (layout)
+ delete layout;
+ if (videoWidget)
+ delete videoWidget;
+}
+
+void Tracker::start_tracker(QFrame* videoframe)
+{
+ videoframe->show();
+ videoWidget = new HTVideoWidget(videoframe);
+ QHBoxLayout* layout = new QHBoxLayout();
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->addWidget(videoWidget);
+ if (videoframe->layout())
+ delete videoframe->layout();
+ videoframe->setLayout(layout);
+ videoWidget->show();
+ this->layout = layout;
+
+ load_settings(&conf);
+ ht = ht_make_context(&conf, nullptr);
+ start();
+}
+
+void Tracker::run()
+{
+ while (!should_stop)
+ {
+ ht_result_t euler;
+ euler.filled = false;
+ {
+ QMutexLocker l(&camera_mtx);
+
+ if (!ht_cycle(ht, &euler))
+ break;
+ }
+ if (euler.filled)
+ {
+ QMutexLocker l(&ypr_mtx);
+ ypr[TX] = euler.tx;
+ ypr[TY] = euler.ty;
+ ypr[TZ] = euler.tz;
+ ypr[Yaw] = euler.rotx;
+ ypr[Pitch] = euler.roty;
+ ypr[Roll] = euler.rotz;
+ }
+ {
+ const cv::Mat frame_ = ht_get_bgr_frame(ht);
+ if (frame_.cols <= HT_MAX_VIDEO_WIDTH && frame_.rows <= HT_MAX_VIDEO_HEIGHT && frame_.channels() <= HT_MAX_VIDEO_CHANNELS)
+ {
+ QMutexLocker l(&frame_mtx);
+
+ const int cols = frame_.cols;
+ const int rows = frame_.rows;
+ const int pitch = cols * 3;
+ for (int y = 0; y < rows; y++)
+ {
+ for (int x = 0; x < cols; x++)
+ {
+ unsigned char* dest = &frame.frame[y * pitch + 3 * x];
+ const cv::Vec3b& elt = frame_.at<cv::Vec3b>(y, x);
+ const cv::Scalar elt2 = static_cast<cv::Scalar>(elt);
+ dest[0] = elt2.val[0];
+ dest[1] = elt2.val[1];
+ dest[2] = elt2.val[2];
+ }
+ }
+ frame.channels = frame_.channels();
+ frame.width = frame_.cols;
+ frame.height = frame_.rows;
+ }
+ }
+ }
+ // give opencv time to exit camera threads, etc.
+ portable::sleep(500);
+}
+
+void Tracker::data(double* data)
+{
+ {
+ QMutexLocker l(&frame_mtx);
+
+ if (frame.width > 0)
+ {
+ videoWidget->update_image(frame.frame, frame.width, frame.height);
+ frame.width = 0;
+ }
+ }
+
+ {
+ QMutexLocker l(&ypr_mtx);
+
+ for (int i = 0; i < 6; i++)
+ data[i] = ypr[i];
+ }
+}
+
+TrackerControls::TrackerControls() : tracker(nullptr)
+{
+ ui.setupUi(this);
+ ui.cameraName->clear();
+ QList<QString> names = get_camera_names();
+ names.prepend("Any available");
+ ui.cameraName->addItems(names);
+ tie_setting(s.camera_name, ui.cameraName);
+ tie_setting(s.fps, ui.cameraFPS);
+ tie_setting(s.fov, ui.cameraFOV);
+ tie_setting(s.resolution, ui.resolution);
+ connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel()));
+ connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK()));
+ connect(ui.camera_settings, SIGNAL(pressed()), this, SLOT(camera_settings()));
+}
+
+void TrackerControls::doOK()
+{
+ s.b->save();
+ this->close();
+}
+
+void TrackerControls::doCancel()
+{
+ s.b->reload();
+ this->close();
+}
+
+void TrackerControls::camera_settings()
+{
+ if (tracker)
+ {
+ cv::VideoCapture* cap = ht_capture(tracker->ht);
+ open_camera_settings(cap, s.camera_name, &tracker->camera_mtx);
+ }
+ else
+ open_camera_settings(nullptr, s.camera_name, nullptr);
+}
+
+OPENTRACK_DECLARE_TRACKER(Tracker, TrackerControls, TrackerDll)