diff options
Diffstat (limited to 'ftnoir_tracker_ht')
-rw-r--r-- | ftnoir_tracker_ht/ftnoir_tracker_ht.cpp | 291 | ||||
-rw-r--r-- | ftnoir_tracker_ht/ftnoir_tracker_ht.h | 78 | ||||
-rw-r--r-- | ftnoir_tracker_ht/ftnoir_tracker_ht_dll.h | 19 | ||||
-rw-r--r-- | ftnoir_tracker_ht/headtracker-ftnoir.h | 24 | ||||
-rw-r--r-- | ftnoir_tracker_ht/ht-api.h | 49 | ||||
-rw-r--r-- | ftnoir_tracker_ht/ht-tracker.qrc | 5 | ||||
-rw-r--r-- | ftnoir_tracker_ht/ht-trackercontrols.ui | 228 | ||||
-rw-r--r-- | ftnoir_tracker_ht/ht_video_widget.cpp | 44 | ||||
-rw-r--r-- | ftnoir_tracker_ht/ht_video_widget.h | 47 | ||||
-rw-r--r-- | ftnoir_tracker_ht/images/ht.png | bin | 0 -> 2010 bytes | |||
-rw-r--r-- | ftnoir_tracker_ht/stdafx.h | 13 |
11 files changed, 798 insertions, 0 deletions
diff --git a/ftnoir_tracker_ht/ftnoir_tracker_ht.cpp b/ftnoir_tracker_ht/ftnoir_tracker_ht.cpp new file mode 100644 index 00000000..76a6ba71 --- /dev/null +++ b/ftnoir_tracker_ht/ftnoir_tracker_ht.cpp @@ -0,0 +1,291 @@ +#include "stdafx.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_ht-trackercontrols.h" +#include "facetracknoir/global-settings.h" +#include <cmath> + +#if defined(_WIN32) +#include <dshow.h> +#else +#include <unistd.h> +#endif + +// delicious copypasta +static QList<QString> get_camera_names(void) { + QList<QString> ret; +#if defined(_WIN32) + // Create the System Device Enumerator. + HRESULT hr; + ICreateDevEnum *pSysDevEnum = NULL; + hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (void **)&pSysDevEnum); + if (FAILED(hr)) + { + return ret; + } + // Obtain a class enumerator for the video compressor category. + IEnumMoniker *pEnumCat = NULL; + hr = pSysDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnumCat, 0); + + if (hr == S_OK) { + // Enumerate the monikers. + IMoniker *pMoniker = NULL; + ULONG cFetched; + while (pEnumCat->Next(1, &pMoniker, &cFetched) == S_OK) { + IPropertyBag *pPropBag; + hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pPropBag); + if (SUCCEEDED(hr)) { + // To retrieve the filter's friendly name, do the following: + VARIANT varName; + VariantInit(&varName); + hr = pPropBag->Read(L"FriendlyName", &varName, 0); + if (SUCCEEDED(hr)) + { + // Display the name in your UI somehow. + QString str((QChar*)varName.bstrVal, wcslen(varName.bstrVal)); + ret.append(str); + } + VariantClear(&varName); + + ////// To create an instance of the filter, do the following: + ////IBaseFilter *pFilter; + ////hr = pMoniker->BindToObject(NULL, NULL, IID_IBaseFilter, + //// (void**)&pFilter); + // Now add the filter to the graph. + //Remember to release pFilter later. + pPropBag->Release(); + } + pMoniker->Release(); + } + pEnumCat->Release(); + } + pSysDevEnum->Release(); +#elif !defined(__APPLE__) + for (int i = 0; i < 16; i++) { + char buf[128]; + sprintf(buf, "/dev/video%d", i); + if (access(buf, R_OK | W_OK) == 0) { + ret.append(buf); + } else { + continue; + } + } +#endif + return ret; +} + +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->pyrlk_pyramids = 0; + config->pyrlk_win_size_w = config->pyrlk_win_size_h = 21; + config->max_keypoints = 150; + config->keypoint_distance = 6; + config->force_fps = nframes; + config->camera_index = s.camera_idx - 1; + config->ransac_num_iters = 100; + config->ransac_max_reprojection_error = 10; + config->ransac_max_inlier_error = 10; + config->ransac_abs_max_mean_error = 14; + config->ransac_max_mean_error = 8; + config->debug = 0; + config->ransac_min_features = 0.86; + 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 = 500; + for (int i = 0; i < 5; i++) + config->dist_coeffs[i] = 0; +} + +Tracker::Tracker() : + lck_shm(HT_SHM_NAME, HT_MUTEX_NAME, sizeof(ht_shm_t)), + shm(reinterpret_cast<ht_shm_t*>(lck_shm.mem)), + videoWidget(nullptr), + layout(nullptr) +{ + shm->terminate = 0; + shm->result.filled = false; +} + +Tracker::~Tracker() +{ + if (shm) { + shm->terminate = true; + subprocess.waitForFinished(5000); + } + subprocess.kill(); + if (shm) + shm->terminate = true; + if (layout) + delete layout; + if (videoWidget) + delete videoWidget; +} + +void Tracker::StartTracker(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(&shm->config); + shm->frame.channels = shm->frame.width = shm->frame.height = 0; + shm->pause = shm->terminate = shm->running = false; + shm->timer = 0; + subprocess.setWorkingDirectory(QCoreApplication::applicationDirPath() + "/tracker-ht"); +#if defined(_WIN32) + subprocess.start("\"" + QCoreApplication::applicationDirPath() + "/tracker-ht/headtracker-ftnoir" + "\""); +#else + subprocess.start(QCoreApplication::applicationDirPath() + "/tracker-ht/headtracker-ftnoir"); +#endif +} + +void Tracker::GetHeadPoseData(double *data) +{ + lck_shm.lock(); + shm->timer = 0; + if (shm->frame.width > 0) + { + videoWidget->update_image(shm->frame.frame, shm->frame.width, shm->frame.height); + //memcpy(foo, shm->frame.frame, shm->frame.width * shm->frame.height * 3); + shm->frame.width = 0; + } + if (shm->result.filled) { + if (s.enableRX) + data[Yaw] = shm->result.rotx; + if (s.enableRY) { + data[Pitch] = shm->result.roty; + } + if (s.enableRZ) { + data[Roll] = shm->result.rotz; + } + if (s.enableTX) + data[TX] = shm->result.tx; + if (s.enableTY) + data[TY] = shm->result.ty; + if (s.enableTZ) + data[TZ] = shm->result.tz; + if (fabs(data[Yaw]) > 60 || fabs(data[Pitch]) > 50 || fabs(data[Roll]) > 40) + { + shm->pause = true; + } + } else { + shm->pause = false; + } + lck_shm.unlock(); +} + +//----------------------------------------------------------------------------- +void TrackerDll::getFullName(QString *strToBeFilled) +{ + *strToBeFilled = "HT 1.0"; +} + +void TrackerDll::getShortName(QString *strToBeFilled) +{ + *strToBeFilled = "HT"; +} + +void TrackerDll::getDescription(QString *strToBeFilled) +{ + *strToBeFilled = ""; +} + +void TrackerDll::getIcon(QIcon *icon) +{ + *icon = QIcon(":/images/ht.png"); +} + +extern "C" FTNOIR_TRACKER_BASE_EXPORT Metadata* CALLING_CONVENTION GetMetadata() +{ + return new TrackerDll; +} + +extern "C" FTNOIR_TRACKER_BASE_EXPORT ITracker* CALLING_CONVENTION GetConstructor() +{ + return new Tracker; +} + +extern "C" FTNOIR_TRACKER_BASE_EXPORT ITrackerDialog* CALLING_CONVENTION GetDialog( ) +{ + return new TrackerControls; +} + +TrackerControls::TrackerControls() +{ + ui.setupUi(this); + ui.cameraName->clear(); + QList<QString> names = get_camera_names(); + names.prepend("Any available"); + ui.cameraName->addItems(names); + tie_setting(s.camera_idx, ui.cameraName); + tie_setting(s.fps, ui.cameraFPS); + tie_setting(s.fov, ui.cameraFOV); + tie_setting(s.enableTX, ui.tx); + tie_setting(s.enableTY, ui.ty); + tie_setting(s.enableTZ, ui.tz); + tie_setting(s.enableRX, ui.rx); + tie_setting(s.enableRY, ui.ry); + tie_setting(s.enableRZ, ui.rz); + tie_setting(s.resolution, ui.resolution); + connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel())); + connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK())); +} + +void TrackerControls::doOK() +{ + s.b->save(); + this->close(); +} + +void TrackerControls::doCancel() +{ + s.b->revert(); + this->close(); +} diff --git a/ftnoir_tracker_ht/ftnoir_tracker_ht.h b/ftnoir_tracker_ht/ftnoir_tracker_ht.h new file mode 100644 index 00000000..583249dc --- /dev/null +++ b/ftnoir_tracker_ht/ftnoir_tracker_ht.h @@ -0,0 +1,78 @@ +/* Copyright (c) 2013 Stanislaw 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 + * copyright notice and this permission notice appear in all copies. + */ + +#ifndef FTNOIR_TRACKER_HT_H +#define FTNOIR_TRACKER_HT_H + +#include "stdafx.h" +#include "ftnoir_tracker_base/ftnoir_tracker_base.h" +#include "headtracker-ftnoir.h" +#include "ui_ht-trackercontrols.h" +#include "ht_video_widget.h" +#include "compat/compat.h" +#include <QObject> +#include "facetracknoir/options.h" +using namespace options; + +struct settings { + pbundle b; + value<bool> enableTX, enableTY, enableTZ, enableRX, enableRY, enableRZ; + value<double> fov; + value<int> fps, camera_idx, resolution; + settings() : + b(bundle("HT-Tracker")), + enableTX(b, "enable-tx", true), + enableTY(b, "enable-ty", true), + enableTZ(b, "enable-tz", true), + enableRX(b, "enable-rx", true), + enableRY(b, "enable-ry", true), + enableRZ(b, "enable-rz", true), + fov(b, "fov", 56), + fps(b, "fps", 0), + camera_idx(b, "camera-index", 0), + resolution(b, "resolution", 0) + {} +}; + +class Tracker : public QObject, public ITracker +{ + Q_OBJECT +public: + Tracker(); + virtual ~Tracker(); + void StartTracker(QFrame* frame); + void GetHeadPoseData(double *data); + void load_settings(ht_config_t* config); +private: + settings s; + PortableLockedShm lck_shm; + ht_shm_t* shm; + QProcess subprocess; + HTVideoWidget* videoWidget; + QHBoxLayout* layout; +}; + +// Widget that has controls for FTNoIR protocol client-settings. +class TrackerControls : public QWidget, public ITrackerDialog +{ + Q_OBJECT +public: + explicit TrackerControls(); + void registerTracker(ITracker *) {} + void unRegisterTracker() {} + +private: + Ui::Form ui; + settings s; + +private slots: + void doOK(); + void doCancel(); +}; + +#endif + diff --git a/ftnoir_tracker_ht/ftnoir_tracker_ht_dll.h b/ftnoir_tracker_ht/ftnoir_tracker_ht_dll.h new file mode 100644 index 00000000..ffdc5262 --- /dev/null +++ b/ftnoir_tracker_ht/ftnoir_tracker_ht_dll.h @@ -0,0 +1,19 @@ +/* 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 + * copyright notice and this permission notice appear in all copies. + */ + +#include "ftnoir_tracker_base/ftnoir_tracker_base.h" +#include "facetracknoir/global-settings.h" + +//----------------------------------------------------------------------------- +class TrackerDll : public Metadata +{ + // ITrackerDll interface + void getFullName(QString *strToBeFilled); + void getShortName(QString *strToBeFilled); + void getDescription(QString *strToBeFilled); + void getIcon(QIcon *icon); +}; diff --git a/ftnoir_tracker_ht/headtracker-ftnoir.h b/ftnoir_tracker_ht/headtracker-ftnoir.h new file mode 100644 index 00000000..9a343bae --- /dev/null +++ b/ftnoir_tracker_ht/headtracker-ftnoir.h @@ -0,0 +1,24 @@ +#pragma once +#include <stdlib.h> +#include <stdio.h> +#include "ht-api.h" + +#define HT_SHM_NAME "ftnoir-tracker-ht-shm" +#define HT_MUTEX_NAME "ftnoir-tracker-ht-mutex" + +#define HT_MAX_VIDEO_WIDTH 640 +#define HT_MAX_VIDEO_HEIGHT 480 +#define HT_MAX_VIDEO_CHANNELS 3 + +typedef struct { + int width, height, channels; + unsigned char frame[HT_MAX_VIDEO_WIDTH * HT_MAX_VIDEO_HEIGHT * HT_MAX_VIDEO_CHANNELS]; +} ht_video_t; + +typedef struct { + ht_video_t frame; + ht_config_t config; + ht_result_t result; + volatile int timer; + volatile bool pause, terminate, running; +} ht_shm_t; diff --git a/ftnoir_tracker_ht/ht-api.h b/ftnoir_tracker_ht/ht-api.h new file mode 100644 index 00000000..2ab2e840 --- /dev/null +++ b/ftnoir_tracker_ht/ht-api.h @@ -0,0 +1,49 @@ +#pragma once +#ifndef HT_API +# if defined(_WIN32) && !defined(MINGW) +# define HT_API(t) __declspec(dllexport) t __stdcall +# else +# define HT_API(t) t +# endif +#endif +#if !defined(_WIN32) && !defined(_isnan) +# define _isnan isnan +#endif +#include <opencv2/core/core.hpp> +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 ransac_max_inlier_error; + float ransac_max_reprojection_error; + int max_keypoints; + float keypoint_distance; + int force_width; + 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; + float flandmark_delay; + double dist_coeffs[5]; +} ht_config_t; + +typedef struct { + double rotx, roty, rotz; + double tx, ty, tz; + bool filled; +} ht_result_t; + +HT_API(headtracker_t*) ht_make_context(const ht_config_t* config, const char* filename); +HT_API(void) ht_free_context(headtracker_t* ctx); +HT_API(const cv::Mat) ht_get_bgr_frame(headtracker_t* ctx); +HT_API(bool) ht_cycle(headtracker_t* ctx, ht_result_t* euler); +HT_API(void) ht_reset(headtracker_t* ctx); diff --git a/ftnoir_tracker_ht/ht-tracker.qrc b/ftnoir_tracker_ht/ht-tracker.qrc new file mode 100644 index 00000000..b6af7a18 --- /dev/null +++ b/ftnoir_tracker_ht/ht-tracker.qrc @@ -0,0 +1,5 @@ +<RCC> + <qresource prefix="/"> + <file>images/ht.png</file> + </qresource> +</RCC> diff --git a/ftnoir_tracker_ht/ht-trackercontrols.ui b/ftnoir_tracker_ht/ht-trackercontrols.ui new file mode 100644 index 00000000..f57022c8 --- /dev/null +++ b/ftnoir_tracker_ht/ht-trackercontrols.ui @@ -0,0 +1,228 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>Form</class> + <widget class="QWidget" name="Form"> + <property name="windowModality"> + <enum>Qt::NonModal</enum> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>531</width> + <height>166</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maximumSize"> + <size> + <width>750</width> + <height>280</height> + </size> + </property> + <property name="windowTitle"> + <string>HT tracker settings</string> + </property> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="1"> + <widget class="QDoubleSpinBox" name="cameraFOV"> + <property name="locale"> + <locale language="English" country="UnitedStates"/> + </property> + <property name="minimum"> + <double>35.000000000000000</double> + </property> + <property name="maximum"> + <double>180.000000000000000</double> + </property> + <property name="value"> + <double>52.000000000000000</double> + </property> + </widget> + </item> + <item row="0" column="0"> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Horizontal FOV</string> + </property> + </widget> + </item> + <item row="0" column="2" rowspan="3"> + <widget class="QGroupBox" name="groupBox"> + <property name="title"> + <string>Enable axes</string> + </property> + <widget class="QCheckBox" name="rx"> + <property name="geometry"> + <rect> + <x>10</x> + <y>20</y> + <width>70</width> + <height>17</height> + </rect> + </property> + <property name="text"> + <string>RX</string> + </property> + </widget> + <widget class="QCheckBox" name="ry"> + <property name="geometry"> + <rect> + <x>10</x> + <y>40</y> + <width>70</width> + <height>17</height> + </rect> + </property> + <property name="text"> + <string>RY</string> + </property> + </widget> + <widget class="QCheckBox" name="rz"> + <property name="geometry"> + <rect> + <x>10</x> + <y>60</y> + <width>70</width> + <height>17</height> + </rect> + </property> + <property name="text"> + <string>RZ</string> + </property> + </widget> + <widget class="QCheckBox" name="tx"> + <property name="geometry"> + <rect> + <x>60</x> + <y>20</y> + <width>70</width> + <height>17</height> + </rect> + </property> + <property name="text"> + <string>TX</string> + </property> + </widget> + <widget class="QCheckBox" name="ty"> + <property name="geometry"> + <rect> + <x>60</x> + <y>40</y> + <width>70</width> + <height>17</height> + </rect> + </property> + <property name="text"> + <string>TY</string> + </property> + </widget> + <widget class="QCheckBox" name="tz"> + <property name="geometry"> + <rect> + <x>60</x> + <y>60</y> + <width>70</width> + <height>17</height> + </rect> + </property> + <property name="text"> + <string>TZ</string> + </property> + </widget> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>Frames per second</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QComboBox" name="cameraFPS"> + <item> + <property name="text"> + <string notr="true">Default</string> + </property> + </item> + <item> + <property name="text"> + <string>30</string> + </property> + </item> + <item> + <property name="text"> + <string>60</string> + </property> + </item> + <item> + <property name="text"> + <string>120</string> + </property> + </item> + <item> + <property name="text"> + <string>180</string> + </property> + </item> + </widget> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="label_3"> + <property name="text"> + <string>Camera name</string> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QComboBox" name="cameraName"/> + </item> + <item row="3" column="0"> + <widget class="QLabel" name="label_4"> + <property name="text"> + <string>Resolution</string> + </property> + </widget> + </item> + <item row="3" column="1"> + <widget class="QComboBox" name="resolution"> + <item> + <property name="text"> + <string>640x480</string> + </property> + </item> + <item> + <property name="text"> + <string>320x240</string> + </property> + </item> + <item> + <property name="text"> + <string>320x200</string> + </property> + </item> + <item> + <property name="text"> + <string>Default (not recommended!)</string> + </property> + </item> + </widget> + </item> + <item row="4" column="2"> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/ftnoir_tracker_ht/ht_video_widget.cpp b/ftnoir_tracker_ht/ht_video_widget.cpp new file mode 100644 index 00000000..c6d59b34 --- /dev/null +++ b/ftnoir_tracker_ht/ht_video_widget.cpp @@ -0,0 +1,44 @@ +/* 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 "ht_video_widget.h" + +#include <QDebug> + +using namespace std; + +void HTVideoWidget::update_image(unsigned char *frame, int width, int height) +{ + QMutexLocker foo(&mtx); + memcpy(fb, frame, width * height * 3); + this->width = width; + this->height = height; +} + +void HTVideoWidget::update_and_repaint() +{ + QMutexLocker foo(&mtx); + if (width*height <= 0) + return; + QImage qframe = QImage(width, height, QImage::Format_RGB888); + uchar* data = qframe.bits(); + const int pitch = qframe.bytesPerLine(); + for (int y = 0; y < height; y++) + { + const int part = y*width; + for (int x = 0; x < width; x++) + { + const int pos = 3 * (part + x); + data[y * pitch + x * 3 + 0] = fb[pos + 2]; + data[y * pitch + x * 3 + 1] = fb[pos + 1]; + data[y * pitch + x * 3 + 2] = fb[pos + 0]; + } + } + auto qframe2 = qframe.scaled(size(), Qt::IgnoreAspectRatio, Qt::FastTransformation); + texture = qframe2; + update(); +} diff --git a/ftnoir_tracker_ht/ht_video_widget.h b/ftnoir_tracker_ht/ht_video_widget.h new file mode 100644 index 00000000..cbfe6ddc --- /dev/null +++ b/ftnoir_tracker_ht/ht_video_widget.h @@ -0,0 +1,47 @@ +/* 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 <QTime> +#include <QWidget> +#include <QMutex> +#include <QMutexLocker> +#include <QLabel> +#include <QPainter> +#include <QPaintEvent> +#include <QTimer> + +// ---------------------------------------------------------------------------- +class HTVideoWidget : public QWidget +{ + Q_OBJECT + +public: + HTVideoWidget(QWidget *parent) : QWidget(parent), fb(), width(0), height(0) { + connect(&timer, SIGNAL(timeout()), this, SLOT(update_and_repaint())); + timer.start(60); + } + void update_image(unsigned char* frame, int width, int height); +protected slots: + void paintEvent( QPaintEvent* e ) { + QMutexLocker foo(&mtx); + QPainter painter(this); + painter.drawImage(e->rect(), texture); + } + void update_and_repaint(); + +private: + QMutex mtx; + QImage texture; + QTimer timer; + char fb[2048*2048*3]; + int width,height; +}; + +#endif // VIDEOWIDGET_H diff --git a/ftnoir_tracker_ht/images/ht.png b/ftnoir_tracker_ht/images/ht.png Binary files differnew file mode 100644 index 00000000..19c73d21 --- /dev/null +++ b/ftnoir_tracker_ht/images/ht.png diff --git a/ftnoir_tracker_ht/stdafx.h b/ftnoir_tracker_ht/stdafx.h new file mode 100644 index 00000000..6f1539b7 --- /dev/null +++ b/ftnoir_tracker_ht/stdafx.h @@ -0,0 +1,13 @@ +#include <QWidget> +#include <QMessageBox> +#include <QProcess> +#include <QImage> +#include <QLabel> +#include <QCoreApplication> +#include <QIcon> +#include <QHBoxLayout> +#include <QTimer> +#include <QPainter> +#include <QPaintEvent> +#include <QList> +#include <QString> |