diff options
author | Stanislaw Halik <sthalik@misaki.pl> | 2013-09-15 12:39:32 +0200 |
---|---|---|
committer | Stanislaw Halik <sthalik@misaki.pl> | 2013-09-15 12:39:32 +0200 |
commit | bef7aff31e5ea073f0f160ca6a2f1e56b7dd881a (patch) | |
tree | 2f6122f682427322f925736e87a0bd68b658972c | |
parent | 3734ab61a6f0d4d8aad32a17a2eb5fc49245626e (diff) |
Initial PT 1.1 import
Codebase broken at this stage
-rw-r--r-- | CMakeLists.txt | 8 | ||||
-rw-r--r-- | FTNoIR_Tracker_PT/FTNoIR_PT_Controls.ui (renamed from ftnoir_tracker_pt/ftnoir_pt_controls.ui) | 671 | ||||
-rw-r--r-- | FTNoIR_Tracker_PT/FTNoIR_Tracker_PT.rc (renamed from ftnoir_tracker_pt/ftnoir_tracker_pt.rc) | 0 | ||||
-rw-r--r-- | FTNoIR_Tracker_PT/FTNoIR_Tracker_PT_vc10.vcxproj | 212 | ||||
-rw-r--r-- | FTNoIR_Tracker_PT/Resources/Logo_IR.png (renamed from ftnoir_tracker_pt/resources/logo_ir.png) | bin | 10386 -> 10386 bytes | |||
-rw-r--r-- | FTNoIR_Tracker_PT/Resources/cap_front.png (renamed from ftnoir_tracker_pt/resources/cap_front.png) | bin | 1164 -> 1164 bytes | |||
-rw-r--r-- | FTNoIR_Tracker_PT/Resources/cap_side.png (renamed from ftnoir_tracker_pt/resources/cap_side.png) | bin | 1733 -> 1733 bytes | |||
-rw-r--r-- | FTNoIR_Tracker_PT/Resources/clip_front.png (renamed from ftnoir_tracker_pt/resources/clip_front.png) | bin | 571 -> 571 bytes | |||
-rw-r--r-- | FTNoIR_Tracker_PT/Resources/clip_side.png (renamed from ftnoir_tracker_pt/resources/clip_side.png) | bin | 2677 -> 2677 bytes | |||
-rw-r--r-- | FTNoIR_Tracker_PT/Resources/icon.ico | bin | 0 -> 4286 bytes | |||
-rw-r--r-- | FTNoIR_Tracker_PT/camera.cpp (renamed from ftnoir_tracker_pt/camera.cpp) | 476 | ||||
-rw-r--r-- | FTNoIR_Tracker_PT/camera.h (renamed from ftnoir_tracker_pt/camera.h) | 258 | ||||
-rw-r--r-- | FTNoIR_Tracker_PT/doc/index.htm | 262 | ||||
-rw-r--r-- | FTNoIR_Tracker_PT/doc/logo.png | bin | 0 -> 10386 bytes | |||
-rw-r--r-- | FTNoIR_Tracker_PT/doc/ptrack.ico | bin | 0 -> 4286 bytes | |||
-rw-r--r-- | FTNoIR_Tracker_PT/doc/settings1.png | bin | 0 -> 25013 bytes | |||
-rw-r--r-- | FTNoIR_Tracker_PT/doc/settings2.png | bin | 0 -> 26841 bytes | |||
-rw-r--r-- | FTNoIR_Tracker_PT/doc/settings3.png | bin | 0 -> 29547 bytes | |||
-rw-r--r-- | FTNoIR_Tracker_PT/doc/style.css | 131 | ||||
-rw-r--r-- | FTNoIR_Tracker_PT/frame_observer.cpp | 18 | ||||
-rw-r--r-- | FTNoIR_Tracker_PT/frame_observer.h | 72 | ||||
-rw-r--r-- | FTNoIR_Tracker_PT/ftnoir_tracker_pt.cpp | 265 | ||||
-rw-r--r-- | FTNoIR_Tracker_PT/ftnoir_tracker_pt.h (renamed from ftnoir_tracker_pt/ftnoir_tracker_pt.h) | 195 | ||||
-rw-r--r-- | FTNoIR_Tracker_PT/ftnoir_tracker_pt.qrc | 10 | ||||
-rw-r--r-- | FTNoIR_Tracker_PT/ftnoir_tracker_pt_dialog.cpp (renamed from ftnoir_tracker_pt/ftnoir_tracker_pt_dialog.cpp) | 743 | ||||
-rw-r--r-- | FTNoIR_Tracker_PT/ftnoir_tracker_pt_dialog.h (renamed from ftnoir_tracker_pt/ftnoir_tracker_pt_dialog.h) | 218 | ||||
-rw-r--r-- | FTNoIR_Tracker_PT/ftnoir_tracker_pt_dll.cpp (renamed from ftnoir_tracker_pt/ftnoir_tracker_pt_dll.cpp) | 80 | ||||
-rw-r--r-- | FTNoIR_Tracker_PT/ftnoir_tracker_pt_dll.h (renamed from ftnoir_tracker_pt/ftnoir_tracker_pt_dll.h) | 37 | ||||
-rw-r--r-- | FTNoIR_Tracker_PT/ftnoir_tracker_pt_settings.cpp (renamed from ftnoir_tracker_pt/ftnoir_tracker_pt_settings.cpp) | 302 | ||||
-rw-r--r-- | FTNoIR_Tracker_PT/ftnoir_tracker_pt_settings.h (renamed from ftnoir_tracker_pt/ftnoir_tracker_pt_settings.h) | 170 | ||||
-rw-r--r-- | FTNoIR_Tracker_PT/point_extractor.cpp (renamed from ftnoir_tracker_pt/point_extractor.cpp) | 197 | ||||
-rw-r--r-- | FTNoIR_Tracker_PT/point_extractor.h (renamed from ftnoir_tracker_pt/point_extractor.h) | 62 | ||||
-rw-r--r-- | FTNoIR_Tracker_PT/point_tracker.cpp (renamed from ftnoir_tracker_pt/point_tracker.cpp) | 711 | ||||
-rw-r--r-- | FTNoIR_Tracker_PT/point_tracker.h (renamed from ftnoir_tracker_pt/point_tracker.h) | 239 | ||||
-rw-r--r-- | FTNoIR_Tracker_PT/resource.h (renamed from ftnoir_tracker_pt/resource.h) | 28 | ||||
-rw-r--r-- | FTNoIR_Tracker_PT/timer.cpp (renamed from ftnoir_tracker_pt/timer.cpp) | 129 | ||||
-rw-r--r-- | FTNoIR_Tracker_PT/timer.h (renamed from ftnoir_tracker_pt/timer.h) | 86 | ||||
-rw-r--r-- | FTNoIR_Tracker_PT/trans_calib.cpp (renamed from ftnoir_tracker_pt/trans_calib.cpp) | 86 | ||||
-rw-r--r-- | FTNoIR_Tracker_PT/trans_calib.h (renamed from ftnoir_tracker_pt/trans_calib.h) | 76 | ||||
-rw-r--r-- | FTNoIR_Tracker_PT/video_widget.cpp | 119 | ||||
-rw-r--r-- | FTNoIR_Tracker_PT/video_widget.h | 58 | ||||
-rw-r--r-- | ftnoir_protocol_fg/ftnoir_protocol_fg.cpp.autosave | 222 | ||||
-rw-r--r-- | ftnoir_tracker_pt/ftnoir_tracker_pt.cpp | 261 | ||||
-rw-r--r-- | ftnoir_tracker_pt/ftnoir_tracker_pt.qrc | 10 | ||||
-rw-r--r-- | ftnoir_tracker_pt/resources/icon.png | bin | 1701 -> 0 bytes | |||
-rw-r--r-- | ftnoir_tracker_pt/video_widget.cpp | 52 | ||||
-rw-r--r-- | ftnoir_tracker_pt/video_widget.h | 42 | ||||
-rw-r--r-- | ftnoir_tracker_pt/videoinput/videoinput.h | 385 | ||||
-rw-r--r-- | ftnoir_tracker_pt/videoinput/videoinput_vc8.lib | bin | 2145206 -> 0 bytes | |||
-rw-r--r-- | ftnoir_tracker_pt/videoinput/videoinput_vc9.lib | bin | 2119546 -> 0 bytes |
50 files changed, 3895 insertions, 2996 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 29baf906..0669fb74 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -216,11 +216,11 @@ if(NOT SDK_FACEAPI_ONLY) QT4_WRAP_UI(opentrack-tracker-aruco-uih ${opentrack-tracker-aruco-ui}) QT4_ADD_RESOURCES(opentrack-tracker-aruco-rcc ${opentrack-tracker-aruco-rc}) - file(GLOB opentrack-tracker-pt-c "ftnoir_tracker_pt/*.cpp") - file(GLOB opentrack-tracker-pt-h "ftnoir_tracker_pt/*.h") + file(GLOB opentrack-tracker-pt-c "FTNoIR_Tracker_PT/*.cpp") + file(GLOB opentrack-tracker-pt-h "FTNoIR_Tracker_PT/*.h") QT4_WRAP_CPP(opentrack-tracker-pt-moc ${opentrack-tracker-pt-h}) - file(GLOB opentrack-tracker-pt-ui "ftnoir_tracker_pt/*.ui") - file(GLOB opentrack-tracker-pt-rc "ftnoir_tracker_pt/*.qrc") + file(GLOB opentrack-tracker-pt-ui "FTNoIR_Tracker_PT/*.ui") + file(GLOB opentrack-tracker-pt-rc "FTNoIR_Tracker_PT/*.qrc") QT4_WRAP_UI(opentrack-tracker-pt-uih ${opentrack-tracker-pt-ui}) QT4_ADD_RESOURCES(opentrack-tracker-pt-rcc ${opentrack-tracker-pt-rc}) diff --git a/ftnoir_tracker_pt/ftnoir_pt_controls.ui b/FTNoIR_Tracker_PT/FTNoIR_PT_Controls.ui index 6a183eae..7bb7eb50 100644 --- a/ftnoir_tracker_pt/ftnoir_pt_controls.ui +++ b/FTNoIR_Tracker_PT/FTNoIR_PT_Controls.ui @@ -3,14 +3,14 @@ <class>UICPTClientControls</class>
<widget class="QWidget" name="UICPTClientControls">
<property name="windowModality">
- <enum>Qt::NonModal</enum>
+ <enum>Qt::ApplicationModal</enum>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
- <width>468</width>
- <height>528</height>
+ <width>395</width>
+ <height>552</height>
</rect>
</property>
<property name="sizePolicy">
@@ -23,8 +23,8 @@ <string>PointTracker Settings</string>
</property>
<property name="windowIcon">
- <iconset>
- <normaloff>:/Resources/icon.png</normaloff>:/Resources/icon.png</iconset>
+ <iconset resource="ftnoir_tracker_pt.qrc">
+ <normaloff>:/Resources/icon.ico</normaloff>:/Resources/icon.ico</iconset>
</property>
<property name="layoutDirection">
<enum>Qt::LeftToRight</enum>
@@ -54,7 +54,7 @@ <locale language="English" country="UnitedStates"/>
</property>
<property name="currentIndex">
- <number>1</number>
+ <number>0</number>
</property>
<widget class="QWidget" name="tab">
<attribute name="title">
@@ -161,7 +161,7 @@ </property>
<property name="sizeHint" stdset="0">
<size>
- <width>40</width>
+ <width>30</width>
<height>20</height>
</size>
</property>
@@ -174,7 +174,7 @@ </property>
<property name="sizeHint" stdset="0">
<size>
- <width>40</width>
+ <width>30</width>
<height>20</height>
</size>
</property>
@@ -450,259 +450,337 @@ </property>
</spacer>
</item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="tab_2">
+ <attribute name="title">
+ <string>Camera</string>
+ </attribute>
+ <layout class="QVBoxLayout" name="verticalLayout_7">
<item>
- <widget class="QGroupBox" name="groupBox_11">
+ <widget class="QGroupBox" name="groupBox">
+ <property name="toolTip">
+ <string>The camera device used as input</string>
+ </property>
<property name="title">
- <string>Status</string>
+ <string>Camera Settings</string>
</property>
- <layout class="QVBoxLayout" name="verticalLayout_8">
+ <layout class="QVBoxLayout" name="verticalLayout">
<item>
- <layout class="QFormLayout" name="formLayout_2">
- <property name="fieldGrowthPolicy">
- <enum>QFormLayout::AllNonFixedFieldsGrow</enum>
- </property>
- <item row="0" column="0">
- <widget class="QLabel" name="label_65">
+ <layout class="QHBoxLayout" name="horizontalLayout_3">
+ <item>
+ <widget class="QLabel" name="label_2">
+ <property name="minimumSize">
+ <size>
+ <width>55</width>
+ <height>0</height>
+ </size>
+ </property>
<property name="text">
- <string>Camera Info:</string>
+ <string>Device</string>
+ </property>
+ <property name="buddy">
+ <cstring>camdevice_combo</cstring>
</property>
</widget>
</item>
- <item row="0" column="1">
- <widget class="QLabel" name="caminfo_label_2">
+ <item>
+ <widget class="QComboBox" name="camdevice_combo">
<property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+ <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
+ <property name="toolTip">
+ <string>Camera device used as input</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_8">
+ <item>
+ <layout class="QGridLayout" name="gridLayout_8">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label_36">
+ <property name="minimumSize">
+ <size>
+ <width>55</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Resolution</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="5">
+ <widget class="QLabel" name="label_37">
+ <property name="text">
+ <string>FPS</string>
+ </property>
+ <property name="buddy">
+ <cstring>fps_spin</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="6">
+ <widget class="QSpinBox" name="fps_spin">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip">
+ <string>Desired capture framerate</string>
+ </property>
+ <property name="maximum">
+ <number>999</number>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="2">
+ <widget class="QLabel" name="label_41">
+ <property name="text">
+ <string>x</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QSpinBox" name="res_x_spin">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip">
+ <string>Desired capture width</string>
+ </property>
+ <property name="maximum">
+ <number>2000</number>
+ </property>
+ <property name="singleStep">
+ <number>10</number>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="3">
+ <widget class="QSpinBox" name="res_y_spin">
+ <property name="toolTip">
+ <string>Desired capture height</string>
+ </property>
+ <property name="maximum">
+ <number>2000</number>
+ </property>
+ <property name="singleStep">
+ <number>10</number>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_34">
+ <property name="text">
+ <string>F/W</string>
+ </property>
+ <property name="buddy">
+ <cstring>f_dspin</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QDoubleSpinBox" name="f_dspin">
+ <property name="toolTip">
+ <string>The camera's focal length devided by its sensor width</string>
+ </property>
+ <property name="decimals">
+ <number>2</number>
+ </property>
+ <property name="singleStep">
+ <double>0.100000000000000</double>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="4">
+ <spacer name="horizontalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="0" column="7">
+ <spacer name="horizontalSpacer_9">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_7">
+ <item>
+ <widget class="QPushButton" name="videowidget_button">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
<property name="minimumSize">
<size>
- <width>120</width>
+ <width>130</width>
<height>0</height>
</size>
</property>
- <property name="text">
- <string/>
+ <property name="locale">
+ <locale language="English" country="UnitedStates"/>
</property>
- </widget>
- </item>
- <item row="1" column="0">
- <widget class="QLabel" name="label_17">
<property name="text">
- <string>Extracted Points:</string>
+ <string>VideoWidget</string>
</property>
</widget>
</item>
- <item row="1" column="1">
- <widget class="QLabel" name="pointinfo_label_2">
- <property name="minimumSize">
+ <item>
+ <spacer name="horizontalSpacer_12">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
<size>
- <width>50</width>
- <height>0</height>
+ <width>0</width>
+ <height>20</height>
</size>
</property>
- <property name="text">
- <string/>
- </property>
- </widget>
+ </spacer>
</item>
</layout>
</item>
</layout>
</widget>
</item>
- </layout>
- </widget>
- <widget class="QWidget" name="tab_2">
- <attribute name="title">
- <string>Camera</string>
- </attribute>
- <layout class="QVBoxLayout" name="verticalLayout_7">
<item>
- <widget class="QGroupBox" name="groupBox">
+ <widget class="QGroupBox" name="groupBox_4">
<property name="title">
- <string>Camera Settings</string>
+ <string>Camera Orientation</string>
</property>
- <layout class="QVBoxLayout" name="verticalLayout">
+ <layout class="QVBoxLayout" name="verticalLayout_8">
<item>
- <layout class="QHBoxLayout" name="horizontalLayout_3">
+ <layout class="QHBoxLayout" name="horizontalLayout_6">
<item>
- <layout class="QFormLayout" name="formLayout_4">
+ <layout class="QGridLayout" name="gridLayout_3">
<item row="1" column="0">
- <widget class="QLabel" name="label_2">
+ <widget class="QLabel" name="label_4">
<property name="text">
- <string>Index</string>
+ <string>Pitch</string>
</property>
<property name="buddy">
- <cstring>camindex_spin</cstring>
+ <cstring>campitch_spin</cstring>
</property>
</widget>
</item>
<item row="1" column="1">
- <widget class="QSpinBox" name="camindex_spin">
+ <widget class="QSpinBox" name="campitch_spin">
+ <property name="contextMenuPolicy">
+ <enum>Qt::DefaultContextMenu</enum>
+ </property>
<property name="toolTip">
- <string>Capture device index</string>
+ <string>The angle the camera is facing upwards</string>
+ </property>
+ <property name="minimum">
+ <number>-99</number>
</property>
</widget>
</item>
<item row="2" column="0">
- <widget class="QLabel" name="label_37">
+ <widget class="QLabel" name="label_20">
<property name="text">
- <string>FPS</string>
+ <string>Yaw</string>
</property>
<property name="buddy">
- <cstring>fps_spin</cstring>
+ <cstring>camyaw_spin</cstring>
</property>
</widget>
</item>
<item row="2" column="1">
- <widget class="QSpinBox" name="fps_spin">
+ <widget class="QSpinBox" name="camyaw_spin">
+ <property name="contextMenuPolicy">
+ <enum>Qt::DefaultContextMenu</enum>
+ </property>
<property name="toolTip">
- <string>Desired capture framerate</string>
+ <string>The angle the camera is facing leftwards</string>
</property>
- <property name="maximum">
- <number>300</number>
+ <property name="minimum">
+ <number>-99</number>
</property>
</widget>
</item>
- </layout>
- </item>
- <item>
- <spacer name="horizontalSpacer_2">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- <item>
- <layout class="QVBoxLayout" name="verticalLayout_10">
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout_13">
- <item>
- <widget class="QLabel" name="label_36">
- <property name="text">
- <string>Resolution</string>
- </property>
- </widget>
- </item>
- <item>
- <spacer name="horizontalSpacer_9">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- <item>
- <widget class="QSpinBox" name="res_x_spin">
- <property name="toolTip">
- <string>Desired capture width</string>
- </property>
- <property name="maximum">
- <number>2000</number>
- </property>
- <property name="singleStep">
- <number>10</number>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QLabel" name="label_41">
- <property name="text">
- <string>x</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QSpinBox" name="res_y_spin">
- <property name="toolTip">
- <string>Desired capture height</string>
- </property>
- <property name="maximum">
- <number>2000</number>
- </property>
- <property name="singleStep">
- <number>10</number>
- </property>
- </widget>
- </item>
- </layout>
+ <item row="2" column="2">
+ <widget class="QLabel" name="label_21">
+ <property name="text">
+ <string>deg (positve = leftwards)</string>
+ </property>
+ </widget>
</item>
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout_9">
- <item>
- <widget class="QLabel" name="label_34">
- <property name="text">
- <string>(Focal length)/(Sensor width)</string>
- </property>
- <property name="buddy">
- <cstring>f_dspin</cstring>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QDoubleSpinBox" name="f_dspin">
- <property name="toolTip">
- <string>The camera's focal length devided by its sensor width</string>
- </property>
- <property name="decimals">
- <number>2</number>
- </property>
- <property name="singleStep">
- <double>0.100000000000000</double>
- </property>
- </widget>
- </item>
- </layout>
+ <item row="0" column="1">
+ <widget class="QComboBox" name="camroll_combo">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Rotation of the camera image</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="2">
+ <widget class="QLabel" name="label_5">
+ <property name="text">
+ <string>deg (positive = upwards)</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="2">
+ <widget class="QLabel" name="label_19">
+ <property name="text">
+ <string>deg</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0">
+ <widget class="QLabel" name="label_18">
+ <property name="text">
+ <string>Roll</string>
+ </property>
+ <property name="buddy">
+ <cstring>camroll_combo</cstring>
+ </property>
+ </widget>
</item>
</layout>
</item>
- </layout>
- </item>
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout_6">
- <item>
- <widget class="QLabel" name="label_4">
- <property name="text">
- <string>Camera Pitch (upwards = positive)</string>
- </property>
- <property name="buddy">
- <cstring>campitch_spin</cstring>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QSpinBox" name="campitch_spin">
- <property name="contextMenuPolicy">
- <enum>Qt::DefaultContextMenu</enum>
- </property>
- <property name="toolTip">
- <string>The angle the camera is facing upwards</string>
- </property>
- <property name="minimum">
- <number>-99</number>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QLabel" name="label_5">
- <property name="text">
- <string>deg</string>
- </property>
- </widget>
- </item>
<item>
<spacer name="horizontalSpacer_10">
<property name="orientation">
@@ -710,7 +788,7 @@ </property>
<property name="sizeHint" stdset="0">
<size>
- <width>20</width>
+ <width>0</width>
<height>20</height>
</size>
</property>
@@ -722,6 +800,19 @@ </widget>
</item>
<item>
+ <spacer name="verticalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>0</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>Point Extraction</string>
@@ -825,81 +916,6 @@ </layout>
</widget>
</item>
- <item>
- <spacer name="verticalSpacer_2">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>40</height>
- </size>
- </property>
- </spacer>
- </item>
- <item>
- <widget class="QGroupBox" name="groupBox_5">
- <property name="title">
- <string>Status</string>
- </property>
- <layout class="QVBoxLayout" name="verticalLayout_5">
- <item>
- <layout class="QFormLayout" name="formLayout">
- <property name="fieldGrowthPolicy">
- <enum>QFormLayout::AllNonFixedFieldsGrow</enum>
- </property>
- <item row="0" column="0">
- <widget class="QLabel" name="label_38">
- <property name="text">
- <string>Camera Info:</string>
- </property>
- </widget>
- </item>
- <item row="0" column="1">
- <widget class="QLabel" name="caminfo_label">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="minimumSize">
- <size>
- <width>120</width>
- <height>0</height>
- </size>
- </property>
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- <item row="1" column="0">
- <widget class="QLabel" name="label_3">
- <property name="text">
- <string>Extracted Points:</string>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
- <widget class="QLabel" name="pointinfo_label">
- <property name="minimumSize">
- <size>
- <width>50</width>
- <height>0</height>
- </size>
- </property>
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- </layout>
- </widget>
- </item>
</layout>
</widget>
<widget class="QWidget" name="tab_4">
@@ -946,7 +962,7 @@ <property name="minimumSize">
<size>
<width>150</width>
- <height>170</height>
+ <height>160</height>
</size>
</property>
<widget class="QLabel" name="label_44">
@@ -962,7 +978,7 @@ <string/>
</property>
<property name="pixmap">
- <pixmap>:/resources/clip_side.png</pixmap>
+ <pixmap resource="ftnoir_tracker_pt.qrc">:/Resources/clip_side.png</pixmap>
</property>
</widget>
<widget class="QSpinBox" name="clip_theight_spin">
@@ -1085,7 +1101,7 @@ <string/>
</property>
<property name="pixmap">
- <pixmap>:/resources/clip_front.png</pixmap>
+ <pixmap resource="ftnoir_tracker_pt.qrc">:/Resources/clip_front.png</pixmap>
</property>
</widget>
<widget class="QLabel" name="label_53">
@@ -1140,7 +1156,7 @@ <string/>
</property>
<property name="pixmap">
- <pixmap>:/resources/cap_side.png</pixmap>
+ <pixmap resource="ftnoir_tracker_pt.qrc">:/Resources/cap_side.png</pixmap>
</property>
</widget>
<widget class="QSpinBox" name="cap_height_spin">
@@ -1250,7 +1266,7 @@ <string/>
</property>
<property name="pixmap">
- <pixmap>:/resources/cap_front.png</pixmap>
+ <pixmap resource="ftnoir_tracker_pt.qrc">:/Resources/cap_front.png</pixmap>
</property>
</widget>
<widget class="QSpinBox" name="cap_width_spin">
@@ -1299,7 +1315,7 @@ <property name="sizeHint" stdset="0">
<size>
<width>20</width>
- <height>20</height>
+ <height>0</height>
</size>
</property>
</spacer>
@@ -1313,7 +1329,7 @@ </property>
<property name="sizeHint" stdset="0">
<size>
- <width>20</width>
+ <width>10</width>
<height>20</height>
</size>
</property>
@@ -1466,7 +1482,7 @@ </property>
<property name="sizeHint" stdset="0">
<size>
- <width>20</width>
+ <width>10</width>
<height>20</height>
</size>
</property>
@@ -1482,7 +1498,7 @@ <property name="sizeHint" stdset="0">
<size>
<width>20</width>
- <height>20</height>
+ <height>0</height>
</size>
</property>
</spacer>
@@ -1516,7 +1532,7 @@ </property>
<property name="sizeHint" stdset="0">
<size>
- <width>20</width>
+ <width>10</width>
<height>20</height>
</size>
</property>
@@ -1613,7 +1629,7 @@ </property>
<property name="sizeHint" stdset="0">
<size>
- <width>20</width>
+ <width>10</width>
<height>20</height>
</size>
</property>
@@ -1640,7 +1656,7 @@ </rect>
</property>
<property name="text">
- <string><html><head/><body><p><span style=" font-weight:600;">FTNoIR PointTracker Plugin<br/>Version 1.0</span></p><p><span style=" font-weight:600;">by Patrick Ruoff</span></p><p><a href="http://ftnoirpt.sourceforge.net/"><span style=" font-weight:600; text-decoration: underline; color:#0000ff;">Manual (external)</span></a></p></body></html></string>
+ <string><html><head/><body><p><span style=" font-weight:600;">FTNoIR PointTracker Plugin<br/>Version 1.1</span></p><p><span style=" font-weight:600;">by Patrick Ruoff</span></p><p><a href="http://ftnoirpt.sourceforge.net/"><span style=" font-weight:600; text-decoration: underline; color:#0000ff;">Manual (external)</span></a></p></body></html></string>
</property>
<property name="openExternalLinks">
<bool>true</bool>
@@ -1659,13 +1675,75 @@ <string/>
</property>
<property name="pixmap">
- <pixmap>:/resources/logo_ir.png</pixmap>
+ <pixmap resource="ftnoir_tracker_pt.qrc">:/Resources/Logo_IR.png</pixmap>
</property>
</widget>
</widget>
</widget>
</item>
<item>
+ <widget class="QGroupBox" name="groupBox_5">
+ <property name="title">
+ <string>Status</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_5">
+ <item>
+ <layout class="QFormLayout" name="formLayout">
+ <property name="fieldGrowthPolicy">
+ <enum>QFormLayout::AllNonFixedFieldsGrow</enum>
+ </property>
+ <item row="0" column="0">
+ <widget class="QLabel" name="label_38">
+ <property name="text">
+ <string>Camera Info:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLabel" name="caminfo_label">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>120</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>Extracted Points:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLabel" name="pointinfo_label">
+ <property name="minimumSize">
+ <size>
+ <width>50</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<spacer name="horizontalSpacer_6">
@@ -1682,6 +1760,9 @@ </item>
<item>
<widget class="QPushButton" name="ok_button">
+ <property name="locale">
+ <locale language="English" country="UnitedStates"/>
+ </property>
<property name="text">
<string>Ok</string>
</property>
@@ -1689,6 +1770,9 @@ </item>
<item>
<widget class="QPushButton" name="cancel_button">
+ <property name="locale">
+ <locale language="English" country="UnitedStates"/>
+ </property>
<property name="text">
<string>Cancel</string>
</property>
@@ -1700,20 +1784,25 @@ </widget>
<tabstops>
<tabstop>tabWidget</tabstop>
+ <tabstop>videowidget_check</tabstop>
<tabstop>sleep_spin</tabstop>
+ <tabstop>dynpose_check</tabstop>
<tabstop>reset_spin</tabstop>
+ <tabstop>reset_button</tabstop>
<tabstop>chkEnableRoll</tabstop>
<tabstop>chkEnablePitch</tabstop>
<tabstop>chkEnableYaw</tabstop>
<tabstop>chkEnableX</tabstop>
<tabstop>chkEnableY</tabstop>
<tabstop>chkEnableZ</tabstop>
- <tabstop>camindex_spin</tabstop>
+ <tabstop>camdevice_combo</tabstop>
<tabstop>res_x_spin</tabstop>
<tabstop>res_y_spin</tabstop>
<tabstop>fps_spin</tabstop>
<tabstop>f_dspin</tabstop>
+ <tabstop>camroll_combo</tabstop>
<tabstop>campitch_spin</tabstop>
+ <tabstop>camyaw_spin</tabstop>
<tabstop>threshold_slider</tabstop>
<tabstop>mindiam_spin</tabstop>
<tabstop>maxdiam_spin</tabstop>
@@ -1738,7 +1827,9 @@ <tabstop>ok_button</tabstop>
<tabstop>cancel_button</tabstop>
</tabstops>
- <resources/>
+ <resources>
+ <include location="ftnoir_tracker_pt.qrc"/>
+ </resources>
<connections>
<connection>
<sender>dynpose_check</sender>
@@ -1747,12 +1838,12 @@ <slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
- <x>285</x>
- <y>105</y>
+ <x>172</x>
+ <y>110</y>
</hint>
<hint type="destinationlabel">
- <x>139</x>
- <y>111</y>
+ <x>351</x>
+ <y>112</y>
</hint>
</hints>
</connection>
diff --git a/ftnoir_tracker_pt/ftnoir_tracker_pt.rc b/FTNoIR_Tracker_PT/FTNoIR_Tracker_PT.rc index 11c5d52f..11c5d52f 100644 --- a/ftnoir_tracker_pt/ftnoir_tracker_pt.rc +++ b/FTNoIR_Tracker_PT/FTNoIR_Tracker_PT.rc diff --git a/FTNoIR_Tracker_PT/FTNoIR_Tracker_PT_vc10.vcxproj b/FTNoIR_Tracker_PT/FTNoIR_Tracker_PT_vc10.vcxproj new file mode 100644 index 00000000..b777077b --- /dev/null +++ b/FTNoIR_Tracker_PT/FTNoIR_Tracker_PT_vc10.vcxproj @@ -0,0 +1,212 @@ +<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Template|Win32">
+ <Configuration>Template</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectName>FTNoIR_Tracker_PT</ProjectName>
+ <ProjectGuid>{7A2A2560-9253-4CC8-A9D5-4B9D9C224D9D}</ProjectGuid>
+ <RootNamespace>FTNoIR_Tracker_PT</RootNamespace>
+ <Keyword>Qt4VSv1.0</Keyword>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)\bin\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)\$(Configuration)\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)/bin_dbg\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)\$(Configuration)\</IntDir>
+ <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
+ <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
+ <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
+ <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
+ <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Template|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Template|Win32'" />
+ <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Template|Win32'" />
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <AdditionalIncludeDirectories>.;.\GeneratedFiles;.\GeneratedFiles\$(Configuration);$(QTDIR)\include;$(QTDIR)\include\QtCore;$(QTDIR)\include\QtGui;$(OPENCV_DIR)\include;$(BOOST_DIR);$(QTDIR)\include\QtOpenGL;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>UNICODE;WIN32;QT_DLL;QT_NO_DEBUG;NDEBUG;QT_CORE_LIB;QT_GUI_LIB;FTNOIR_TRACKER_BASE_LIB;QT_OPENGL_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <TreatWChar_tAsBuiltInType>false</TreatWChar_tAsBuiltInType>
+ <DebugInformationFormat>
+ </DebugInformationFormat>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>qtmain.lib;QtCore4.lib;QtGui4.lib;QtOpenGL4.lib;opengl32.lib;glu32.lib;opencv_core242.lib;opencv_imgproc242.lib;opencv_calib3d242.lib;videoInput_vc10.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(ProjectName).dll</OutputFile>
+ <AdditionalLibraryDirectories>$(QTDIR)\lib;$(OPENCV_DIR)\x86\vc10\lib;$(ProjectDir)\videoInput;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <IgnoreSpecificDefaultLibraries>atlthunk.lib;libcmt;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <SubSystem>Windows</SubSystem>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>.;.\GeneratedFiles;.\GeneratedFiles\$(Configuration);$(QTDIR)\include;$(QTDIR)\include\QtCore;$(QTDIR)\include\QtGui;$(OPENCV_DIR)\include;$(BOOST_DIR);$(QTDIR)\include\QtOpenGL;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>UNICODE;WIN32;QT_DLL;QT_CORE_LIB;QT_GUI_LIB;FTNOIR_TRACKER_BASE_LIB;QT_OPENGL_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <TreatWChar_tAsBuiltInType>false</TreatWChar_tAsBuiltInType>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>qtmaind.lib;QtCored4.lib;QtGuid4.lib;QtOpenGLd4.lib;opengl32.lib;glu32.lib;opencv_core242d.lib;opencv_imgproc242d.lib;opencv_calib3d242d.lib;videoInput_vc10.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(ProjectName).dll</OutputFile>
+ <AdditionalLibraryDirectories>$(QTDIR)\lib;$(OPENCV_DIR)\x86\vc10\lib;$(ProjectDir)\videoInput;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <IgnoreSpecificDefaultLibraries>atlthunk.lib;libcmt;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Windows</SubSystem>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="camera.cpp" />
+ <ClCompile Include="frame_observer.cpp" />
+ <ClCompile Include="ftnoir_tracker_pt.cpp" />
+ <ClCompile Include="ftnoir_tracker_pt_dialog.cpp" />
+ <ClCompile Include="ftnoir_tracker_pt_dll.cpp" />
+ <ClCompile Include="ftnoir_tracker_pt_settings.cpp" />
+ <ClCompile Include="point_extractor.cpp" />
+ <ClCompile Include="point_tracker.cpp" />
+ <ClCompile Include="timer.cpp" />
+ <ClCompile Include="trans_calib.cpp" />
+ <ClCompile Include="video_widget.cpp" />
+ <ClCompile Include="GeneratedFiles\qrc_ftnoir_tracker_pt.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ </PrecompiledHeader>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ </PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="GeneratedFiles\Release\moc_ftnoir_tracker_pt_dialog.cpp">
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Template|Win32'">true</ExcludedFromBuild>
+ </ClCompile>
+ <ClCompile Include="GeneratedFiles\Release\moc_video_widget.cpp">
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Template|Win32'">true</ExcludedFromBuild>
+ </ClCompile>
+ <ClCompile Include="GeneratedFiles\Debug\moc_ftnoir_tracker_pt_dialog.cpp">
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Template|Win32'">true</ExcludedFromBuild>
+ </ClCompile>
+ <ClCompile Include="GeneratedFiles\Debug\moc_video_widget.cpp">
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Template|Win32'">true</ExcludedFromBuild>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="camera.h" />
+ <ClInclude Include="..\FTNoIR_Tracker_Base\ftnoir_tracker_base.h" />
+ <ClInclude Include="..\FTNoIR_Tracker_Base\ftnoir_tracker_base_global.h" />
+ <CustomBuild Include="ftnoir_tracker_pt.h">
+ <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ </Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(Outputs)</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ </Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(Outputs)</Outputs>
+ </CustomBuild>
+ <CustomBuild Include="ftnoir_tracker_pt_dialog.h">
+ <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Moc%27ing ftnoir_tracker_pt_dialog.h...</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DFTNOIR_TRACKER_BASE_LIB -DQT_OPENGL_LIB -D_WINDLL "-I." "-I.\GeneratedFiles" "-I.\GeneratedFiles\$(Configuration)\." "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(OPENCV_DIR)\include" "-I$(BOOST_DIR)\." "-I$(QTDIR)\include\QtOpenGL"</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(QTDIR)\bin\moc.exe;%(FullPath);%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\GeneratedFiles\$(Configuration)\moc_%(Filename).cpp;%(Outputs)</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Moc%27ing ftnoir_tracker_pt_dialog.h...</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DFTNOIR_TRACKER_BASE_LIB -DQT_OPENGL_LIB -D_WINDLL "-I." "-I.\GeneratedFiles" "-I.\GeneratedFiles\$(Configuration)\." "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(OPENCV_DIR)\include" "-I$(BOOST_DIR)\." "-I$(QTDIR)\include\QtOpenGL"</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(QTDIR)\bin\moc.exe;%(FullPath);%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\GeneratedFiles\$(Configuration)\moc_%(Filename).cpp;%(Outputs)</Outputs>
+ </CustomBuild>
+ <ClInclude Include="frame_observer.h" />
+ <ClInclude Include="ftnoir_tracker_pt_settings.h" />
+ <ClInclude Include="point_extractor.h" />
+ <ClInclude Include="point_tracker.h" />
+ <ClInclude Include="resource.h" />
+ <ClInclude Include="timer.h" />
+ <ClInclude Include="trans_calib.h" />
+ <CustomBuild Include="video_widget.h">
+ <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Moc%27ing video_widget.h...</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DFTNOIR_TRACKER_BASE_LIB -DQT_OPENGL_LIB -D_WINDLL "-I." "-I.\GeneratedFiles" "-I.\GeneratedFiles\$(Configuration)\." "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(OPENCV_DIR)\include" "-I$(BOOST_DIR)\." "-I$(QTDIR)\include\QtOpenGL"</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(QTDIR)\bin\moc.exe;%(FullPath);%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\GeneratedFiles\$(Configuration)\moc_%(Filename).cpp;%(Outputs)</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Moc%27ing video_widget.h...</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DFTNOIR_TRACKER_BASE_LIB -DQT_OPENGL_LIB -D_WINDLL "-I." "-I.\GeneratedFiles" "-I.\GeneratedFiles\$(Configuration)\." "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(OPENCV_DIR)\include" "-I$(BOOST_DIR)\." "-I$(QTDIR)\include\QtOpenGL"</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(QTDIR)\bin\moc.exe;%(FullPath);%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\GeneratedFiles\$(Configuration)\moc_%(Filename).cpp;%(Outputs)</Outputs>
+ </CustomBuild>
+ <ClInclude Include="GeneratedFiles\ui_FTNoIR_PT_Controls.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <CustomBuild Include="FTNoIR_PT_Controls.ui">
+ <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Uic%27ing %(Filename)%(Extension)...</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">"$(QTDIR)\bin\uic.exe" -o ".\GeneratedFiles\ui_%(Filename).h" "%(FullPath)"
+</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(QTDIR)\bin\uic.exe;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\GeneratedFiles\ui_%(Filename).h;%(Outputs)</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Uic%27ing %(Filename)%(Extension)...</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">"$(QTDIR)\bin\uic.exe" -o ".\GeneratedFiles\ui_%(Filename).h" "%(FullPath)"
+</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(QTDIR)\bin\uic.exe;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\GeneratedFiles\ui_%(Filename).h;%(Outputs)</Outputs>
+ </CustomBuild>
+ <CustomBuild Include="ftnoir_tracker_pt.qrc">
+ <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Rcc%27ing %(Filename)%(Extension)...</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">"$(QTDIR)\bin\rcc.exe" -name "%(Filename)" -no-compress "%(FullPath)" -o .\GeneratedFiles\qrc_%(Filename).cpp
+</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(FullPath);.\Resources\icon.ico;.\Resources\Logo_IR.png;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\GeneratedFiles\qrc_%(Filename).cpp;%(Outputs)</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Rcc%27ing %(Filename)%(Extension)...</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">"$(QTDIR)\bin\rcc.exe" -name "%(Filename)" -no-compress "%(FullPath)" -o .\GeneratedFiles\qrc_%(Filename).cpp
+</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(FullPath);.\Resources\icon.ico;.\Resources\Logo_IR.png;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\GeneratedFiles\qrc_%(Filename).cpp;%(Outputs)</Outputs>
+ </CustomBuild>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="FTNoIR_Tracker_PT.rc" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+ <ProjectExtensions>
+ <VisualStudio>
+ <UserProperties lreleaseOptions="" lupdateOnBuild="0" lupdateOptions="" MocDir=".\GeneratedFiles\$(ConfigurationName)" MocOptions="" QtVersion_x0020_Win32="$(DefaultQtVersion)" RccDir=".\GeneratedFiles" UicDir=".\GeneratedFiles" />
+ </VisualStudio>
+ </ProjectExtensions>
+</Project>
\ No newline at end of file diff --git a/ftnoir_tracker_pt/resources/logo_ir.png b/FTNoIR_Tracker_PT/Resources/Logo_IR.png Binary files differindex 95032a25..95032a25 100644 --- a/ftnoir_tracker_pt/resources/logo_ir.png +++ b/FTNoIR_Tracker_PT/Resources/Logo_IR.png diff --git a/ftnoir_tracker_pt/resources/cap_front.png b/FTNoIR_Tracker_PT/Resources/cap_front.png Binary files differindex 14207a67..14207a67 100644 --- a/ftnoir_tracker_pt/resources/cap_front.png +++ b/FTNoIR_Tracker_PT/Resources/cap_front.png diff --git a/ftnoir_tracker_pt/resources/cap_side.png b/FTNoIR_Tracker_PT/Resources/cap_side.png Binary files differindex 5ad4ee65..5ad4ee65 100644 --- a/ftnoir_tracker_pt/resources/cap_side.png +++ b/FTNoIR_Tracker_PT/Resources/cap_side.png diff --git a/ftnoir_tracker_pt/resources/clip_front.png b/FTNoIR_Tracker_PT/Resources/clip_front.png Binary files differindex 04880138..04880138 100644 --- a/ftnoir_tracker_pt/resources/clip_front.png +++ b/FTNoIR_Tracker_PT/Resources/clip_front.png diff --git a/ftnoir_tracker_pt/resources/clip_side.png b/FTNoIR_Tracker_PT/Resources/clip_side.png Binary files differindex 72667ac7..72667ac7 100644 --- a/ftnoir_tracker_pt/resources/clip_side.png +++ b/FTNoIR_Tracker_PT/Resources/clip_side.png diff --git a/FTNoIR_Tracker_PT/Resources/icon.ico b/FTNoIR_Tracker_PT/Resources/icon.ico Binary files differnew file mode 100644 index 00000000..c4b2aedc --- /dev/null +++ b/FTNoIR_Tracker_PT/Resources/icon.ico diff --git a/ftnoir_tracker_pt/camera.cpp b/FTNoIR_Tracker_PT/camera.cpp index 46dd20c5..21a910c1 100644 --- a/ftnoir_tracker_pt/camera.cpp +++ b/FTNoIR_Tracker_PT/camera.cpp @@ -1,213 +1,263 @@ -/* 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 "camera.h" -#include <QDebug> - -using namespace cv; - -// ---------------------------------------------------------------------------- -void Camera::set_index(int index) -{ - if (desired_index != index) - { - desired_index = index; - _set_index(); - - // reset fps - dt_valid = 0; - dt_mean = 0; - active_index = index; - } -} - -void Camera::set_f(float f) -{ - if (cam_desired.f != f) - { - cam_desired.f = f; - _set_f(); - } -} -void Camera::set_fps(int fps) -{ - if (cam_desired.fps != fps) - { - cam_desired.fps = fps; - _set_fps(); - } -} - -void Camera::set_res(int x_res, int y_res) -{ - if (cam_desired.res_x != x_res || cam_desired.res_y != y_res) - { - cam_desired.res_x = x_res; - cam_desired.res_y = y_res; - _set_res(); - } -} - -bool Camera::get_frame(float dt, cv::Mat* frame) -{ - bool new_frame = _get_frame(frame); - // measure fps of valid frames - const float dt_smoothing_const = 0.9; - dt_valid += dt; - if (new_frame) - { - dt_mean = dt_smoothing_const * dt_mean + (1.0 - dt_smoothing_const) * dt_valid; - cam_info.fps = 1.0 / dt_mean; - dt_valid = 0; - } - return new_frame; -} - -// ---------------------------------------------------------------------------- -void CVCamera::start() -{ - cap = new VideoCapture(desired_index); -// extract camera info - active = true; - active_index = desired_index; - cam_info.res_x = cap->get(CV_CAP_PROP_FRAME_WIDTH); - cam_info.res_y = cap->get(CV_CAP_PROP_FRAME_HEIGHT); -} - -void CVCamera::stop() -{ - if (cap) { - cap->release(); - delete cap; - cap = NULL; - } - active = false; -} - -bool CVCamera::_get_frame(Mat* frame) -{ - bool ret = cap->read(*frame); - //if (ret) - // flip(tmp, *frame, 0); - return ret; -} - -void CVCamera::_set_index() -{ - if (active) restart(); -} - -void CVCamera::_set_f() -{ - cam_info.f = cam_desired.f; -} - -void CVCamera::_set_fps() -{ - if (cap) cap->set(CV_CAP_PROP_FPS, cam_desired.fps); -} - -void CVCamera::_set_res() -{ - if (cap) - { - cap->set(CV_CAP_PROP_FRAME_WIDTH, cam_desired.res_x); - cap->set(CV_CAP_PROP_FRAME_HEIGHT, cam_desired.res_y); - cam_info.res_x = cap->get(CV_CAP_PROP_FRAME_WIDTH); - cam_info.res_y = cap->get(CV_CAP_PROP_FRAME_HEIGHT); - } -} - -#if 0 -// ---------------------------------------------------------------------------- -VICamera::VICamera() : frame_buffer(NULL) -{ - VI.listDevices(); -} - -void VICamera::start() -{ - if (desired_index >= 0) - { - - - if (cam_desired.res_x == 0 || cam_desired.res_y == 0) - VI.setupDevice(desired_index); - else - VI.setupDevice(desired_index, cam_desired.res_x, cam_desired.res_y); - - active = true; - active_index = desired_index; - - cam_info.res_x = VI.getWidth(active_index); - cam_info.res_y = VI.getHeight(active_index); - new_frame = cv::Mat(cam_info.res_y, cam_info.res_x, CV_8UC3); - // If matrix is not continuous we have to copy manually via frame_buffer - if (!new_frame.isContinuous()) { - unsigned int size = VI.getSize(active_index); - frame_buffer = new unsigned char[size]; - } - } -} - -void VICamera::stop() -{ - if (active) - { - VI.stopDevice(active_index); - } - if (frame_buffer) - { - delete[] frame_buffer; - frame_buffer = NULL; - } - active = false; -} - -bool VICamera::_get_frame(Mat* frame) -{ - if (active && VI.isFrameNew(active_index)) - { - if (new_frame.isContinuous()) - { - VI.getPixels(active_index, new_frame.data, false, true); - } - else - { - // If matrix is not continuous we have to copy manually via frame_buffer - VI.getPixels(active_index, frame_buffer, false, true); - new_frame = cv::Mat(cam_info.res_y, cam_info.res_x, CV_8UC3, frame_buffer).clone(); - } - *frame = new_frame; - return true; - } - return false; -} - -void VICamera::_set_index() -{ - if (active) restart(); -} - -void VICamera::_set_f() -{ - cam_info.f = cam_desired.f; -} - -void VICamera::_set_fps() -{ - bool was_active = active; - if (active) stop(); - VI.setIdealFramerate(desired_index, cam_desired.fps); - if (was_active) start(); -} - -void VICamera::_set_res() -{ - if (active) restart(); -} -#endif +/* 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 "camera.h"
+#include <QDebug>
+
+using namespace cv;
+
+// ----------------------------------------------------------------------------
+void get_camera_device_names(std::vector<std::string>& device_names)
+{
+ videoInput VI;
+ VI.listDevices();
+ std::string device_name;
+ for(int index = 0; ; ++index) {
+ device_name = VI.getDeviceName(index);
+ if (device_name.empty()) break;
+ device_names.push_back(device_name);
+ }
+}
+
+// ----------------------------------------------------------------------------
+void Camera::set_device_index(int index)
+{
+ if (desired_index != index)
+ {
+ desired_index = index;
+ _set_device_index();
+
+ // reset fps
+ dt_valid = 0;
+ dt_mean = 0;
+ active_index = index;
+ }
+}
+
+void Camera::set_f(float f)
+{
+ if (cam_desired.f != f)
+ {
+ cam_desired.f = f;
+ _set_f();
+ }
+}
+void Camera::set_fps(int fps)
+{
+ if (cam_desired.fps != fps)
+ {
+ cam_desired.fps = fps;
+ _set_fps();
+ }
+}
+
+void Camera::set_res(int x_res, int y_res)
+{
+ if (cam_desired.res_x != x_res || cam_desired.res_y != y_res)
+ {
+ cam_desired.res_x = x_res;
+ cam_desired.res_y = y_res;
+ _set_res();
+ }
+}
+
+bool Camera::get_frame(float dt, cv::Mat* frame)
+{
+ bool new_frame = _get_frame(frame);
+ // measure fps of valid frames
+ const float dt_smoothing_const = 0.9;
+ dt_valid += dt;
+ if (new_frame)
+ {
+ dt_mean = dt_smoothing_const * dt_mean + (1.0 - dt_smoothing_const) * dt_valid;
+ cam_info.fps = 1.0 / dt_mean;
+ dt_valid = 0;
+ }
+ return new_frame;
+}
+
+// ----------------------------------------------------------------------------
+/*
+void CVCamera::start()
+{
+ cap = cvCreateCameraCapture(desired_index);
+ // extract camera info
+ if (cap)
+ {
+ active = true;
+ active_index = desired_index;
+ cam_info.res_x = cvGetCaptureProperty(cap, CV_CAP_PROP_FRAME_WIDTH);
+ cam_info.res_y = cvGetCaptureProperty(cap, CV_CAP_PROP_FRAME_HEIGHT);
+ }
+}
+
+void CVCamera::stop()
+{
+ if (cap) cvReleaseCapture(&cap);
+ active = false;
+}
+
+bool CVCamera::_get_frame(Mat* frame)
+{
+ if (cap && cvGrabFrame(cap) != 0)
+ {
+ // retrieve frame
+ IplImage* _img = cvRetrieveFrame(cap, 0);
+ if(_img)
+ {
+ if(_img->origin == IPL_ORIGIN_TL)
+ *frame = Mat(_img);
+ else
+ {
+ Mat temp(_img);
+ flip(temp, *frame, 0);
+ }
+ return true;
+ }
+ }
+ return false;
+}
+
+void CVCamera::_set_index()
+{
+ if (active) restart();
+}
+
+void CVCamera::_set_f()
+{
+ cam_info.f = cam_desired.f;
+}
+
+void CVCamera::_set_fps()
+{
+ if (cap) cvSetCaptureProperty(cap, CV_CAP_PROP_FPS, cam_desired.fps);
+}
+
+void CVCamera::_set_res()
+{
+ if (cap)
+ {
+ cvSetCaptureProperty(cap, CV_CAP_PROP_FRAME_WIDTH, cam_desired.res_x);
+ cvSetCaptureProperty(cap, CV_CAP_PROP_FRAME_HEIGHT, cam_desired.res_y);
+ cam_info.res_x = cvGetCaptureProperty(cap, CV_CAP_PROP_FRAME_WIDTH);
+ cam_info.res_y = cvGetCaptureProperty(cap, CV_CAP_PROP_FRAME_HEIGHT);
+ }
+}
+*/
+
+// ----------------------------------------------------------------------------
+VICamera::VICamera() : frame_buffer(NULL)
+{
+ VI.listDevices();
+}
+
+void VICamera::start()
+{
+ if (desired_index >= 0)
+ {
+ if (cam_desired.res_x == 0 || cam_desired.res_y == 0)
+ VI.setupDevice(desired_index);
+ else
+ VI.setupDevice(desired_index, cam_desired.res_x, cam_desired.res_y);
+
+ active = true;
+ active_index = desired_index;
+
+ cam_info.res_x = VI.getWidth(active_index);
+ cam_info.res_y = VI.getHeight(active_index);
+ new_frame = cv::Mat(cam_info.res_y, cam_info.res_x, CV_8UC3);
+ // If matrix is not continuous we have to copy manually via frame_buffer
+ if (!new_frame.isContinuous()) {
+ unsigned int size = VI.getSize(active_index);
+ frame_buffer = new unsigned char[size];
+ }
+ }
+}
+
+void VICamera::stop()
+{
+ if (active)
+ {
+ VI.stopDevice(active_index);
+ }
+ if (frame_buffer)
+ {
+ delete[] frame_buffer;
+ frame_buffer = NULL;
+ }
+ active = false;
+}
+
+bool VICamera::_get_frame(Mat* frame)
+{
+ if (active && VI.isFrameNew(active_index))
+ {
+ if (new_frame.isContinuous())
+ {
+ VI.getPixels(active_index, new_frame.data, false, true);
+ }
+ else
+ {
+ // If matrix is not continuous we have to copy manually via frame_buffer
+ VI.getPixels(active_index, frame_buffer, false, true);
+ new_frame = cv::Mat(cam_info.res_y, cam_info.res_x, CV_8UC3, frame_buffer).clone();
+ }
+ *frame = new_frame;
+ return true;
+ }
+ return false;
+}
+
+void VICamera::_set_device_index()
+{
+ if (active) restart();
+}
+
+void VICamera::_set_f()
+{
+ cam_info.f = cam_desired.f;
+}
+
+void VICamera::_set_fps()
+{
+ bool was_active = active;
+ if (active) stop();
+ VI.setIdealFramerate(desired_index, cam_desired.fps);
+ if (was_active) start();
+}
+
+void VICamera::_set_res()
+{
+ if (active) restart();
+}
+
+
+// ----------------------------------------------------------------------------
+Mat FrameRotation::rotate_frame(Mat frame)
+{
+ switch (rotation)
+ {
+ case CLOCKWISE:
+ {
+ Mat dst;
+ transpose(frame, dst);
+ flip(dst, dst, 1);
+ return dst;
+ }
+
+ case COUNTER_CLOCKWISE:
+ {
+ Mat dst;
+ transpose(frame, dst);
+ flip(dst, dst, 0);
+ return dst;
+ }
+
+ default:
+ return frame;
+ }
+}
\ No newline at end of file diff --git a/ftnoir_tracker_pt/camera.h b/FTNoIR_Tracker_PT/camera.h index 5f1f56b0..c0876d0a 100644 --- a/ftnoir_tracker_pt/camera.h +++ b/FTNoIR_Tracker_PT/camera.h @@ -1,119 +1,139 @@ -/* 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 CAMERA_H -#define CAMERA_H - -#include <opencv2/opencv.hpp> -#include <opencv/highgui.h> -//#include "videoInput/videoInput.h" - -// ---------------------------------------------------------------------------- -struct CamInfo -{ - CamInfo() : res_x(0), res_y(0), fps(0), f(1) {} - - int res_x; - int res_y; - int fps; - float f; // (focal length) / (sensor width) -}; - -// ---------------------------------------------------------------------------- -// base class for cameras -class Camera -{ -public: - Camera() : desired_index(0), active_index(-1), active(false), dt_valid(0), dt_mean(0) {} - virtual ~Camera() {} - - // start/stop capturing - virtual void start() = 0; - virtual void stop() = 0; - void restart() { stop(); start(); } - - void set_index(int index); - void set_f(float f); - void set_fps(int fps); - void set_res(int x_res, int y_res); - - // gets a frame from the camera, dt: time since last call in seconds - bool get_frame(float dt, cv::Mat* frame); - - // WARNING: returned references are valid as long as object - const CamInfo& get_info() const { return cam_info; } - const CamInfo& get_desired() const { return cam_desired; } - -protected: - // get a frame from the camera - virtual bool _get_frame(cv::Mat* frame) = 0; - - // update the camera - virtual void _set_index() = 0; - virtual void _set_f() = 0; - virtual void _set_fps() = 0; - virtual void _set_res() = 0; - - int desired_index; - int active_index; - bool active; - float dt_valid; - float dt_mean; - CamInfo cam_info; - CamInfo cam_desired; -}; - - -// ---------------------------------------------------------------------------- -// OpenCV camera - -class CVCamera : public Camera -{ -public: - CVCamera() : cap(NULL) {} - ~CVCamera() { stop(); } - - void start(); - void stop(); - -protected: - bool _get_frame(cv::Mat* frame); - void _set_index(); - void _set_f(); - void _set_fps(); - void _set_res(); - - cv::VideoCapture* cap; -}; - - -// ---------------------------------------------------------------------------- -// videoInput camera -#if 0 -class VICamera : public Camera -{ -public: - VICamera(); - ~VICamera() { stop(); } - - void start(); - void stop(); - -protected: - bool _get_frame(cv::Mat* frame); - void _set_index(); - void _set_f(); - void _set_fps(); - void _set_res(); - - videoInput VI; - cv::Mat new_frame; - unsigned char* frame_buffer; -}; -#endif - -#endif //CAMERA_H +/* 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 CAMERA_H
+#define CAMERA_H
+
+#include <opencv2/opencv.hpp>
+#include "videoInput/videoInput.h"
+#include <boost/shared_ptr.hpp>
+#include <string>
+
+// ----------------------------------------------------------------------------
+void get_camera_device_names(std::vector<std::string>& device_names);
+
+
+// ----------------------------------------------------------------------------
+struct CamInfo
+{
+ CamInfo() : res_x(0), res_y(0), fps(0), f(1) {}
+
+ int res_x;
+ int res_y;
+ int fps;
+ float f; // (focal length) / (sensor width)
+};
+
+// ----------------------------------------------------------------------------
+// Base class for cameras, calculates the frame rate
+class Camera
+{
+public:
+ Camera() : dt_valid(0), dt_mean(0), desired_index(0), active_index(-1), active(false) {}
+ virtual ~Camera() {}
+
+ // start/stop capturing
+ virtual void start() = 0;
+ virtual void stop() = 0;
+ void restart() { stop(); start(); }
+
+ // calls corresponding template methods and reinitializes frame rate calculation
+ void set_device_index(int index);
+ void set_f(float f);
+ void set_fps(int fps);
+ void set_res(int x_res, int y_res);
+
+ // gets a frame from the camera, dt: time since last call in seconds
+ bool get_frame(float dt, cv::Mat* frame);
+
+ // WARNING: returned references are valid as long as object
+ const CamInfo& get_info() const { return cam_info; }
+ const CamInfo& get_desired() const { return cam_desired; }
+
+protected:
+ // get a frame from the camera
+ virtual bool _get_frame(cv::Mat* frame) = 0;
+
+ // update the camera using cam_desired, write res and f to cam_info if successful
+ virtual void _set_device_index() = 0;
+ virtual void _set_f() = 0;
+ virtual void _set_fps() = 0;
+ virtual void _set_res() = 0;
+
+ bool active;
+ int desired_index;
+ int active_index;
+ CamInfo cam_info;
+ CamInfo cam_desired;
+ float dt_valid;
+ float dt_mean;
+};
+
+
+// ----------------------------------------------------------------------------
+// camera based on OpenCV's videoCapture
+/*
+class CVCamera : public Camera
+{
+public:
+ CVCamera() : cap(NULL) {}
+ ~CVCamera() { stop(); }
+
+ virtual void start();
+ virtual void stop();
+
+protected:
+ virtual bool _get_frame(cv::Mat* frame);
+ virtual void _set_index();
+ virtual void _set_f();
+ virtual void _set_fps();
+ virtual void _set_res();
+
+ CvCapture* cap;
+};
+*/
+
+// ----------------------------------------------------------------------------
+// Camera based on the videoInput library
+class VICamera : public Camera
+{
+public:
+ VICamera();
+ ~VICamera() { stop(); }
+
+ virtual void start();
+ virtual void stop();
+
+protected:
+ virtual bool _get_frame(cv::Mat* frame);
+ virtual void _set_device_index();
+ virtual void _set_f();
+ virtual void _set_fps();
+ virtual void _set_res();
+
+ videoInput VI;
+ cv::Mat new_frame;
+ unsigned char* frame_buffer;
+};
+
+
+// ----------------------------------------------------------------------------
+class FrameRotation
+{
+public:
+ typedef enum Rotation
+ {
+ CLOCKWISE = -1,
+ ZERO = 0,
+ COUNTER_CLOCKWISE = 1
+ };
+ Rotation rotation;
+
+ cv::Mat rotate_frame(cv::Mat frame);
+};
+
+#endif //CAMERA_H
diff --git a/FTNoIR_Tracker_PT/doc/index.htm b/FTNoIR_Tracker_PT/doc/index.htm new file mode 100644 index 00000000..87b7356f --- /dev/null +++ b/FTNoIR_Tracker_PT/doc/index.htm @@ -0,0 +1,262 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> + +<head> + <title>FTNoIR PointTracker Help</title> + + <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" /> + + <meta name="author" + content="Patrick Ruoff (C14)"/> + <meta name="keywords" + content="facetracknoir infrared point model tracker plugin"/> + <meta name="description" + content="Pointtracker plugin for FaceTrackNoIR"/> + + <link rel="shortcut icon" href="ptrack.ico" type="image/vnd.microsoft.icon" /> + <link rel="stylesheet" type="text/css" href="style.css" /> +</head> + +<body> +<div id="navbar"> +<ul class="navbar"> +<li class="navbar"><a class="navbar" href="#about">About</a></li> +<li class="navbar"><a class="navbar" href="#settings">Settings</a></li> +<li class="navbar"><a class="navbar" href="#setup">Filter Setup</a></li> +<li class="navbar"><a class="navbar" href="#support">Support</a></li> +<li class="navbar"><a class="navbar" href="#changelog">ChangeLog</a></li> +<li class="navbar"><a class="navbar" href="#build_instructions">Build Instructions</a></li> +</ul> +</div> + +<div id="content"> +<div style="text-align:center"><h1>FaceTrackNoIR PointTracker Plugin</h1><img src="logo.png" alt="PointTracker Plugin Logo" /></div> + +<a class="nav" id="about"></a> +<h2>About</h2> +<div class="indent"> +<p> +PointTracker is a plugin for the free head tracking software <a href="http://facetracknoir.sourceforge.net">FaceTrackNoIR</a> +which introduces the capability to track a (typically IR-) point model comprising 3 bright points to FaceTrackNoIR, +much like the popular free tracking software <a href="http://www.free-track.net/">Freetrack</a> does.<br/> +It was created as a stable modular alternative to Freetrack, which has some stability issues with newer systems and seems to be no longer actively developped. +</p> +</div> + +<a class="nav" id="settings"></a> +<h2>Settings</h2> +<div class="indent"> +<p> +This section desribes the various settings of the PointTracker plugin in detail. +</p> + +<img src="settings1.png" alt="Settings Pane 1"/> +<dl> +<dt>Show VideoWidget</dt><dd>Whether the video widget is updated or not. It may save some performance to turn this off when not needed</dd> +<dt>Sleep time</dt><dd>Time the tracking thread sleeps after each processed image. It's inverse should be below the framefrate you want to achieve. +(check the framerate in the status region when tracker is active, in case the sleep time is too high, the framerate will decrease). +Low values will result in more CPU-load.</dd> +<dt>Dynamic Pose Resolution</dt><dd>Whether the point correspondence and pose ambiquity is resolved using a more sophisticated dynamic algorithm (constant velocity prediction) or a simple static resolution. +Dynamic pose resolution can capture more extreme poses but may occasionally get stuck in a wrong pose estimates so that a reset of the internal state becomes neccessary.</dd> +<dt>Auto-reset time</dt><dd>If no valid tracking result can be found when using dynamic pose resolution, the tracker will automatically reset its internal state (used for resolving the pose ambiguity and point correspondence) +and return to a fail-safe initialization phase that assumes a neutral pose after this time. +Decrease this time, if you get stuck in a wrong pose too often.</dd> +<dt>Reset</dt><dd>Manually reset the trackers internal state used for dynamic pose resolution and return to a fail-safe initialization phase that assumes a neutral pose. +You may use this in case you get stuck in a wrong pose.</dd> +<dt>Enable Axis ...</dt><dd>Which axis to use for FTNoIR.</dd> +</dl> + +<img src="settings2.png" alt="Settings Pane 2"/> +<dl> +<dt>Device</dt><dd>The camera used for tracking.</dd> +<dt>Resolution</dt><dd>The desired capture resolution. If your camera does not support the entered resolution the true output resolution may be different or even invalid. +You may check the true capture resolution in the status area while the tracker is running. A higher resolution results in more accurate point positions and will increase the +stability of the tracking result, as long as the signal/noise ratio is sufficiently high.</dd> +<dt>FPS</dt><dd>The desired capture framerate. Again, if your camera does not support the entered framerate, the true caputre framerate may be different or invalid. +You may check the true processing framerate in the status area while the tracker is running.</dd> +<dt>F/W</dt><dd>The focal length of the camera divided by the sensor width (of course in the same units). +In case you don't have access to your camera's specifications, you can measure this yourself by placing a plane object of known width (for example a piece of cardboard) in front of the camera until it fills the whole image width. +Then measure the distance between the object and the camera and divide by the object width.</dd> +<dt>VideoWidget</dt><dd>Shows a resizable stand-alone video widget that shows the same content as the integrated video widget in FTNoIR. +Update rate is only 10 fps and may lag behind a bit. Mainly useful during calibration of the point extraction. Same as for the integrated wiget, to save resources, this widget should only be shown when needed.</dd> +<dt>Roll Pitch Yaw...</dt><dd>The orientation of the camera relative to the reference frame. +If these angles are setup properly, the direction of translations may not be correct. +Roll is treated in a special way since it is implemented as a frame rotation by +/- 90 deg that is transparent to the rest of the processing pipeline. +</dd> +<dt>Threshold</dt><dd>The threshold for point recognition. Areas above the threshold are shown in blue in the VideoWidget. +Since point accuracy is best if the points are as big as possible in pixels, the theshold should be chosen as low as possible (stop before the contour of the points becomes "noisy"). +If small reflections are being falsely classified as points, increasing the minimum point diameter (see below) may help.</dd> +<dt>Min Diameter</dt><dd>Minimum diameter of blobs to be classified as a pointmodel-point.</dd> +<dt>Max Diameter</dt><dd>Maximum diameter of blobs to be classified as a pointmodel-point.</dd> +<dt>Status</dt><dd>The tracker's status is shown in this area while the tracker is running. +The FPS shown here correspond to the framerate of the whole tracker processing chain and may be lower than what your camera is able to provide, when<br/> +1. The processing gets not enough CPU time<br/> +2. The sleep time of the tracking thread is set too high<br/></dd> +</dl> + +<img src="settings3.png" alt="Settings Pane 3"/> +<dl> +<dt>Model Selection and Dimensions ...</dt><dd> +First select your model type (point, clip, custom), then enter the dimensions of your model in milimeters here.<br/> +For the custom setting, the coordinates of the two remaining model points have to be entered (reference point M0 is at (0,0,0)) in a pose where the model roughly faces the camera. +For orientation, the coordinates for the standard Freetrack clip are (0,40,-30), (0,-70,-80) and the ones for the cap (40,-60,-100), (-40,-60,-100).<br/> +When using a custom point-model configuration, the following restrictions should be observed:<br/> +The plane in which the 3 points lie should never be parallel to the image plane, M0-M1 and M0-M2 should be roughly perpendicular.</dd> + +<dt>Model Position</dt><dd>The vector from the model to the center of the head in the model frame. Can be calibrated automatically.</dd> +<dt>Calibrate</dt><dd>In order to automatically calibrate the model-head offset, do the following:<br/>Press the Calibrate button, then look around while not moving your shoulder. (i.e. only rotation, no translation). +Do not stay in one pose for too long. The current translation estimate will be updated in real time. As soon as the values stabilized sufficiently, press the Calibrate button again to stop the calibration process.</dd> +</dl> +</div> + +<a class="nav" id="setup"></a> +<h2>Filter Setup</h2> +<div class="indent"> +<p> +This section desribes how the FTNoIR filter work and what the recommended settings for PointTracker are. +</p> +<p> +Filtering is always a tradeoff between stability, accuracy and responsiveness. +</p> +<p> +The <q>Smoothing</q> filter in FTNoIR is just a simple average over the last n samples. +Since this filter produces input lag no matter how fast the head-movements are, it is recommended to turn it off by setting samples to 1. +</p> +<p> +In the filter tab, it is recommended to select <q>Accela Filter Mk2</q>. +Accela is a non-linear filter that works as follows:<br/> +It looks at the difference between the new raw values <i>new_val</i> from the tracker and the last filtered value <i>old_val</i> +and maps this difference via the customizable response function <i>f</i> via:<br/> +</p> +<p style="text-align: center"> +<i>new_val = old_val + f(new_val - old_val) / reduction_factor</i> +</p> +<p> +So by setting <i>f(x) = reduction_factor * x</i>, one will get no filtering at all.<br/> +If you set lower values for small x, small deviations (usually noise) will get dampened. +This results in a dynamic dead-zone around the current position. +</p> +<p> +The last two points are used by accela to extrapolate for large deviations. +So in order to get a fast unfiltered response for large deviations, the line connecting the last two points should have a slope >= <i>reduction_factor</i>. +</p> +<p> +More aggressive accela settings than the default FTNoIR accela settings are recommended in order to decrease the filtering lag and fully use the potential of point tracking.<br/> +My current settings are: +</p> +<pre class="indent"><code> +[Accela] +Reduction=20 + +[Curves-Accela-Scaling-Rotation] +point-count=4 +point-0-x=0.1 +point-0-y=0 +point-1-x=1.43 +point-1-y=2.45 +point-2-x=2.0 +point-2-y=5.44 +point-3-x=2.06 +point-3-y=6 +</code></pre> +<p> +The curve is not too different from the standard one (except that I like a small dynamic dead zone for steady aiming, that's why the curve has a slope of 0 at the beginning).<br/> +However, the reduction factor is decreased to a value of 20 (compared to the standard value of 100). This implies that each value of the curve is effectively 5 times higher than in standard FTNoIR (see formula above), which means higher responsiveness but can also lead to jitter/shaking.<br/> +Keep in mind that there are no <q>best filter settings</q>. Since filtering is always a compromise it's a matter of personal taste and +playing around with the filter settings is highly recommended. +</p> +</div> + +<a class="nav" id="support"></a> +<h2>Support</h2> +<div class="indent"> +<p> +For questions/feedback about the plugin, post to the <a href="https://sourceforge.net/projects/facetracknoir/forums">FTNoIR-Forum</a>.<br/> +In case you like this plugin and would like to support the author, you may consider making a donation. +</p> +<div style="text-align:center"> +<form action="https://www.paypal.com/cgi-bin/webscr" method="post"> +<fieldset class="blind"> +<input type="hidden" name="cmd" value="_s-xclick"/> +<input type="hidden" name="encrypted" value="-----BEGIN PKCS7-----MIIHJwYJKoZIhvcNAQcEoIIHGDCCBxQCAQExggEwMIIBLAIBADCBlDCBjjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRQwEgYDVQQKEwtQYXlQYWwgSW5jLjETMBEGA1UECxQKbGl2ZV9jZXJ0czERMA8GA1UEAxQIbGl2ZV9hcGkxHDAaBgkqhkiG9w0BCQEWDXJlQHBheXBhbC5jb20CAQAwDQYJKoZIhvcNAQEBBQAEgYCa+2zPZ+6vFPqveJsBIjFLpy54m7tl0AdojRr/K5qa3QJDyRBhGwGAP2jRihkmZFE2oKlfLpkz7nrwOQY/wFEPkggO+cABxUfjcQVpIupHEtwdV0hMklLs0RmACJy802yfi1yTiCpJ4hvWN+VfUI3gOiZ9uRZ3L4iGXES7xtqJbDELMAkGBSsOAwIaBQAwgaQGCSqGSIb3DQEHATAUBggqhkiG9w0DBwQIeopHzcJ8XBOAgYCYJFyTejSplEOwF21aQ01qQOads9Z+RUVI+hlvM/pHTjimaZPKSis3poAeqv6wKn40DpLNxDnmcT+Y9KXhrV+Gy4GZCPaeNzq2vquQ2ZVN0fTr84QVmKqPkjMBGmJAHSLCcZswUddemJgoD1uyvS0kNbchvxw7gDXJnJeBRNyXXKCCA4cwggODMIIC7KADAgECAgEAMA0GCSqGSIb3DQEBBQUAMIGOMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExFjAUBgNVBAcTDU1vdW50YWluIFZpZXcxFDASBgNVBAoTC1BheVBhbCBJbmMuMRMwEQYDVQQLFApsaXZlX2NlcnRzMREwDwYDVQQDFAhsaXZlX2FwaTEcMBoGCSqGSIb3DQEJARYNcmVAcGF5cGFsLmNvbTAeFw0wNDAyMTMxMDEzMTVaFw0zNTAyMTMxMDEzMTVaMIGOMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExFjAUBgNVBAcTDU1vdW50YWluIFZpZXcxFDASBgNVBAoTC1BheVBhbCBJbmMuMRMwEQYDVQQLFApsaXZlX2NlcnRzMREwDwYDVQQDFAhsaXZlX2FwaTEcMBoGCSqGSIb3DQEJARYNcmVAcGF5cGFsLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwUdO3fxEzEtcnI7ZKZL412XvZPugoni7i7D7prCe0AtaHTc97CYgm7NsAtJyxNLixmhLV8pyIEaiHXWAh8fPKW+R017+EmXrr9EaquPmsVvTywAAE1PMNOKqo2kl4Gxiz9zZqIajOm1fZGWcGS0f5JQ2kBqNbvbg2/Za+GJ/qwUCAwEAAaOB7jCB6zAdBgNVHQ4EFgQUlp98u8ZvF71ZP1LXChvsENZklGswgbsGA1UdIwSBszCBsIAUlp98u8ZvF71ZP1LXChvsENZklGuhgZSkgZEwgY4xCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEUMBIGA1UEChMLUGF5UGFsIEluYy4xEzARBgNVBAsUCmxpdmVfY2VydHMxETAPBgNVBAMUCGxpdmVfYXBpMRwwGgYJKoZIhvcNAQkBFg1yZUBwYXlwYWwuY29tggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAgV86VpqAWuXvX6Oro4qJ1tYVIT5DgWpE692Ag422H7yRIr/9j/iKG4Thia/Oflx4TdL+IFJBAyPK9v6zZNZtBgPBynXb048hsP16l2vi0k5Q2JKiPDsEfBhGI+HnxLXEaUWAcVfCsQFvd2A1sxRr67ip5y2wwBelUecP3AjJ+YcxggGaMIIBlgIBATCBlDCBjjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRQwEgYDVQQKEwtQYXlQYWwgSW5jLjETMBEGA1UECxQKbGl2ZV9jZXJ0czERMA8GA1UEAxQIbGl2ZV9hcGkxHDAaBgkqhkiG9w0BCQEWDXJlQHBheXBhbC5jb20CAQAwCQYFKw4DAhoFAKBdMBgGCSqGSIb3DQEJAzELBgkqhkiG9w0BBwEwHAYJKoZIhvcNAQkFMQ8XDTEyMDkyMzA5NTcwOFowIwYJKoZIhvcNAQkEMRYEFG/qW7uo4R4m5uFYegcZaZsTPAcUMA0GCSqGSIb3DQEBAQUABIGAGygLfrR6IQbG2xZY2OrwKkfmRwiwtnXpLBnSbnWb7XxUOMhvM6962RiKBQBGP0+XYw0S9yu8ZHx7tqz/3bcMfGjtz7PwixYx6Rm8Z29ja78aUy5FmU7fc9yAWFxLHptSliK1dJBPxdQa9J2YSDvPQPAj+AdB9sJvqJoMoxTFGM4=-----END PKCS7----- +"/> +<input type="image" src="https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif" name="submit" alt="PayPal - The safer, easier way to pay online!"/> +<img alt="" src="https://www.paypalobjects.com/de_DE/i/scr/pixel.gif" width="1" height="1"/> +</fieldset> +</form> +</div> +</div> + +<a class="nav" id="changelog"></a> +<h2>ChangeLog</h2> +<div class="indent"> +<h3>1.1</h3> +<ul> +<li>Added camera yaw and roll correction (intended for vertically mounted cameras)</li> +<li>Improved point extraction algorithm, thanks to Michael Welter</li> +<li>UI improvements: Select camera by device name, different VideoWidget architecture</li> +<li>Bugfixes: Removed 99 FPS limitation</li> +</ul> + +<h3>1.0</h3> +<ul> +<li>Added camera pitch correction</li> +<li>Better communication with FTNoIR: output axis configuration, status report</li> +</ul> + +<h3>1.0 beta</h3> +<ul> +<li>Switchted to videoInput library for capture. Desired capture resolution and fps can now be customized</li> +<li>Introduced dynamic point-correspondence and POSIT-ambiguity resolution, which allows for the reconstruction of more extreme poses</li> +<li>More convenient freetrack-like model dimension GUI</li> +<li>Bugfixes: VideoWidget skipping frames, Timer resolution too low for accurate FPS measurement</li> +</ul> +</div> + +<a class="nav" id="build_instructions"></a> +<h2>Build Instructions</h2> +<div class="indent"> +<p> +This section describes what you need to do in order to build PointTracker yourself.<br/> +You can find the sources at the <a href="https://sourceforge.net/projects/ftnoirpt/">project site</a> +or as part of the <a href="https://sourceforge.net/projects/facetracknoir/">FTNoIR sources</a>. +</p> +<p> The project was created with Visual Studio. </p> + +<h3>Dependencies</h3> +<ul> +<li>Qt 4.8.2 library</li> +<li>Qt plugin for Visual studio</li> +<li>OpenCV 2.4 prebuilt for Windows</li> +<li>Boost 1.47</li> +</ul> + +<h3>Details</h3> +<div class="indent"> +<h4>Common</h4> +<ul> +<li>setup environment variable "QTDIR" (example value "D:\Devel\Libs\Qt\4.8.2")</li> +<li>add "%QTDIR%\bin" to PATH</li> +<li>setup environment variable "BOOST_DIR" (example value "D:\Devel\Libs\boost_1_47_0")</li> +<li>setup environment variable "OPENCV_DIR" (example value "D:\Devel\Libs\opencv\build")</li> +</ul> +<h4>Debug</h4> +<p>opencv linked dynamically:</p> +<ul> +<li>add "%OPENCV_DIR%\x86\vc9\bin" to PATH</li> +</ul> +<p>(in case of different Visual studio, change PATH and linker dependencies accordingly)</p> +<h4>Release</h4> +<p>opencv linked statically:</p> +<ul> +<li>custom build a statically linked version of opencv with the buil-option BUILD_WITH_STATIC_CRT set to OFF!</li> +<li>copy resulting libaries to "%OPENCV_DIR%\x86\vc9\static_lib"</li> +</ul> +<p>(in case of different Visual studio, change PATH and linker dependencies accordingly)</p> +</div> +</div> + +</div> + +</body> +</html>
\ No newline at end of file diff --git a/FTNoIR_Tracker_PT/doc/logo.png b/FTNoIR_Tracker_PT/doc/logo.png Binary files differnew file mode 100644 index 00000000..95032a25 --- /dev/null +++ b/FTNoIR_Tracker_PT/doc/logo.png diff --git a/FTNoIR_Tracker_PT/doc/ptrack.ico b/FTNoIR_Tracker_PT/doc/ptrack.ico Binary files differnew file mode 100644 index 00000000..c4b2aedc --- /dev/null +++ b/FTNoIR_Tracker_PT/doc/ptrack.ico diff --git a/FTNoIR_Tracker_PT/doc/settings1.png b/FTNoIR_Tracker_PT/doc/settings1.png Binary files differnew file mode 100644 index 00000000..35b84c5c --- /dev/null +++ b/FTNoIR_Tracker_PT/doc/settings1.png diff --git a/FTNoIR_Tracker_PT/doc/settings2.png b/FTNoIR_Tracker_PT/doc/settings2.png Binary files differnew file mode 100644 index 00000000..c6cfd1f3 --- /dev/null +++ b/FTNoIR_Tracker_PT/doc/settings2.png diff --git a/FTNoIR_Tracker_PT/doc/settings3.png b/FTNoIR_Tracker_PT/doc/settings3.png Binary files differnew file mode 100644 index 00000000..5922403d --- /dev/null +++ b/FTNoIR_Tracker_PT/doc/settings3.png diff --git a/FTNoIR_Tracker_PT/doc/style.css b/FTNoIR_Tracker_PT/doc/style.css new file mode 100644 index 00000000..a8d3e333 --- /dev/null +++ b/FTNoIR_Tracker_PT/doc/style.css @@ -0,0 +1,131 @@ +body {
+ width: 1000px;
+ font-size: 13px;
+ color: #000000;
+ padding: 0;
+ margin: 0 auto;
+ background: #444444;
+ font-family: verdana,arial;
+}
+
+table {
+ border-width: 3px;
+ border-color: #0000FF;
+ border-style: ridge;
+ margin-top: 5px;
+ background-color: #E0E0FF;
+}
+
+table.blind {
+ border: none;
+ background-color: #E6E6E6;
+}
+
+fieldset.blind {
+ border: none;
+}
+
+h1 { font-size: 160%; }
+h2 { font-size: 140%; }
+h3 { font-size: 115%; }
+
+.indent {
+ margin-left: 25px;
+}
+
+p
+{
+ margin-left: 10px;
+}
+
+li
+{
+ margin: 10px;
+}
+
+
+dl
+{
+ /*width: 80%;*/
+ border-bottom: 1px solid #999;
+}
+
+dt
+{
+ padding-top: 5px;
+ font-weight: bold;
+ border-top: 1px solid #999;
+}
+
+dd
+{
+ padding: 5px;
+}
+
+
+hr {
+ color: #688938;
+}
+
+a:link, a:visited {
+ color: #0000BF;
+}
+a:hover {
+ color: #0000FF;
+}
+
+a.nav {
+ position: relative;
+ top: -30px;
+ display: block;
+ visibility: hidden;
+}
+
+#navbar {
+ width: 1000px;
+ height: 30px;
+ background-color:#1a1a1b;
+ position: fixed;
+ margin: 0 auto;
+ padding: 0;
+}
+
+#navbar ul
+{
+ list-style-type: none;
+ margin: 0 auto;
+ padding: 0;
+ overflow: hidden;
+}
+
+#navbar li
+{
+ margin: 0 auto;
+ padding: 5px;
+ float:left;
+}
+
+#navbar a:link,a:visited
+{
+ display:block;
+ width:150px;
+ font-weight:bold;
+ color:#e85d02;
+ text-align:center;
+ /*padding:4px;*/
+ text-decoration:none;
+ /*text-transform:uppercase;*/
+}
+
+#navbar a:hover,a:active
+{
+ color:#ffffff;
+}
+
+#content {
+ background-color:#ffffff;
+ padding: 15px;
+ padding-top: 40px;
+ padding-right: 40px;
+ margin: 0 auto;
+}
diff --git a/FTNoIR_Tracker_PT/frame_observer.cpp b/FTNoIR_Tracker_PT/frame_observer.cpp new file mode 100644 index 00000000..7e4bb3e3 --- /dev/null +++ b/FTNoIR_Tracker_PT/frame_observer.cpp @@ -0,0 +1,18 @@ +/* Copyright (c) 2013 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 "frame_observer.h"
+
+//-----------------------------------------------------------------------------
+FrameProvider::~FrameProvider()
+{
+ QMutexLocker lock(&observer_mutex);
+ for (auto iter=frame_observers.begin(); iter!=frame_observers.end(); ++iter)
+ {
+ (*iter)->on_frame_provider_destroy();
+ }
+}
\ No newline at end of file diff --git a/FTNoIR_Tracker_PT/frame_observer.h b/FTNoIR_Tracker_PT/frame_observer.h new file mode 100644 index 00000000..4afbd72c --- /dev/null +++ b/FTNoIR_Tracker_PT/frame_observer.h @@ -0,0 +1,72 @@ +/* Copyright (c) 2013 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 FRAME_OBSERVER_H
+#define FRAME_OBSERVER_H
+
+#include <QMutex>
+#include <opencv2/opencv.hpp>
+#include <boost/shared_ptr.hpp>
+#include <set>
+
+//-----------------------------------------------------------------------------
+// Forward declarations
+class FrameObserver;
+
+//-----------------------------------------------------------------------------
+// Provides means to copy frame and point information if it has observers
+// Instantiate a FrameObserver to get the information
+class FrameProvider
+{
+ friend class FrameObserver;
+public:
+ ~FrameProvider();
+
+protected:
+ virtual bool get_frame_and_points(cv::Mat& frame, boost::shared_ptr< std::vector<cv::Vec2f> >& points) = 0;
+
+ bool has_observers() const { QMutexLocker lock(&observer_mutex); return !frame_observers.empty(); }
+
+private:
+ mutable QMutex observer_mutex;
+ void add_observer(FrameObserver* obs) { QMutexLocker lock(&observer_mutex); frame_observers.insert(obs); }
+ void remove_observer(FrameObserver* obs) { QMutexLocker lock(&observer_mutex); frame_observers.erase(obs); }
+ std::set<FrameObserver*> frame_observers;
+};
+
+//-----------------------------------------------------------------------------
+// Used to get frame and point information from MutexedFrameProvider
+// Destroy instance if not interested anymore since a living
+// FrameObserver instance causes MutexedFrameProvider to provide the information,
+// potentially reducing its performance
+class FrameObserver
+{
+public:
+ FrameObserver(FrameProvider* provider) : provider(provider) {
+ provider->add_observer(this);
+ }
+
+ ~FrameObserver() {
+ if (provider) provider->remove_observer(this);
+ }
+
+ bool get_frame_and_points(cv::Mat& frame, boost::shared_ptr< std::vector<cv::Vec2f> >& points) {
+ return provider ? provider->get_frame_and_points(frame, points) : false;
+ }
+
+ void on_frame_provider_destroy() {
+ provider = NULL;
+ }
+
+protected:
+ FrameProvider* provider;
+
+private:
+ FrameObserver(const FrameObserver&);
+};
+
+#endif //FRAME_OBSERVER_H
\ No newline at end of file diff --git a/FTNoIR_Tracker_PT/ftnoir_tracker_pt.cpp b/FTNoIR_Tracker_PT/ftnoir_tracker_pt.cpp new file mode 100644 index 00000000..88a3fc8d --- /dev/null +++ b/FTNoIR_Tracker_PT/ftnoir_tracker_pt.cpp @@ -0,0 +1,265 @@ +/* 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 "ftnoir_tracker_pt.h"
+#include <QHBoxLayout>
+#include <cmath>
+#include <QDebug>
+#include <QFile>
+#include <QCoreApplication>
+
+using namespace std;
+using namespace cv;
+using namespace boost;
+
+//#define PT_PERF_LOG //log performance
+
+const float rad2deg = 180.0/3.14159265;
+const float deg2rad = 1.0/rad2deg;
+
+//-----------------------------------------------------------------------------
+Tracker::Tracker()
+ : frame_count(0),
+ commands(0),
+ video_widget(NULL),
+ video_frame(NULL),
+ tracking_valid(false)
+{
+ qDebug()<<"Tracker::Tracker";
+ TrackerSettings settings;
+ settings.load_ini();
+ apply(settings);
+ camera.start();
+ start();
+}
+
+Tracker::~Tracker()
+{
+ qDebug()<<"Tracker::~Tracker";
+ // terminate tracker thread
+ set_command(ABORT);
+ wait();
+ // destroy video widget
+ show_video_widget = false;
+ update_show_video_widget();
+}
+
+void Tracker::set_command(Command command)
+{
+ QMutexLocker lock(&mutex);
+ commands |= command;
+}
+
+void Tracker::reset_command(Command command)
+{
+ QMutexLocker lock(&mutex);
+ commands &= ~command;
+}
+
+void Tracker::run()
+{
+ qDebug()<<"Tracker:: Thread started";
+
+#ifdef PT_PERF_LOG
+ QFile log_file(QCoreApplication::applicationDirPath() + "/PointTrackerPerformance.txt");
+ if (!log_file.open(QIODevice::WriteOnly | QIODevice::Text)) return;
+ QTextStream log_stream(&log_file);
+#endif
+
+ time.start();
+ float dt;
+ bool new_frame;
+ forever
+ {
+ {
+ QMutexLocker lock(&mutex);
+
+ if (commands & ABORT) break;
+ if (commands & PAUSE) continue;
+ commands = 0;
+
+ dt = time.elapsed() / 1000.0;
+ time.restart();
+
+ new_frame = camera.get_frame(dt, &frame);
+ if (new_frame && !frame.empty())
+ {
+ frame = frame_rotation.rotate_frame(frame);
+ const std::vector<cv::Vec2f>& points = point_extractor.extract_points(frame, dt, has_observers());
+ tracking_valid = point_tracker.track(points, camera.get_info().f, dt);
+ frame_count++;
+ }
+#ifdef PT_PERF_LOG
+ log_stream<<"dt: "<<dt;
+ if (!frame.empty()) log_stream<<" fps: "<<camera.get_info().fps;
+ log_stream<<"\n";
+#endif
+ }
+ msleep(sleep_time);
+ }
+
+ qDebug()<<"Tracker:: Thread stopping";
+}
+
+void Tracker::apply(const TrackerSettings& settings)
+{
+ qDebug()<<"Tracker:: Applying settings";
+ QMutexLocker lock(&mutex);
+ camera.set_device_index(settings.cam_index);
+ camera.set_res(settings.cam_res_x, settings.cam_res_y);
+ camera.set_fps(settings.cam_fps);
+ camera.set_f(settings.cam_f);
+ frame_rotation.rotation = static_cast<FrameRotation::Rotation>(settings.cam_roll);
+ point_extractor.threshold_val = settings.threshold;
+ point_extractor.min_size = settings.min_point_size;
+ point_extractor.max_size = settings.max_point_size;
+ point_tracker.point_model = boost::shared_ptr<PointModel>(new PointModel(settings.M01, settings.M02));
+ point_tracker.dynamic_pose_resolution = settings.dyn_pose_res;
+ sleep_time = settings.sleep_time;
+ point_tracker.dt_reset = settings.reset_time / 1000.0;
+ show_video_widget = settings.video_widget;
+ update_show_video_widget();
+ bEnableRoll = settings.bEnableRoll;
+ bEnablePitch = settings.bEnablePitch;
+ bEnableYaw = settings.bEnableYaw;
+ bEnableX = settings.bEnableX;
+ bEnableY = settings.bEnableY;
+ bEnableZ = settings.bEnableZ;
+
+ t_MH = settings.t_MH;
+ R_GC = Matx33f( cos(deg2rad*settings.cam_yaw), 0, sin(deg2rad*settings.cam_yaw),
+ 0, 1, 0,
+ -sin(deg2rad*settings.cam_yaw), 0, cos(deg2rad*settings.cam_yaw));
+ R_GC = R_GC * Matx33f( 1, 0, 0,
+ 0, cos(deg2rad*settings.cam_pitch), sin(deg2rad*settings.cam_pitch),
+ 0, -sin(deg2rad*settings.cam_pitch), cos(deg2rad*settings.cam_pitch));
+
+ FrameTrafo X_MH(Matx33f::eye(), t_MH);
+ X_GH_0 = R_GC * X_MH;
+
+ qDebug()<<"Tracker::apply ends";
+}
+
+void Tracker::reset()
+{
+ QMutexLocker lock(&mutex);
+ point_tracker.reset();
+}
+
+void Tracker::center()
+{
+ point_tracker.reset(); // we also do a reset here since there is no reset shortkey yet
+ QMutexLocker lock(&mutex);
+ FrameTrafo X_CM_0 = point_tracker.get_pose();
+ FrameTrafo X_MH(Matx33f::eye(), t_MH);
+ X_GH_0 = R_GC * X_CM_0 * X_MH;
+}
+
+bool Tracker::get_frame_and_points(cv::Mat& frame_copy, boost::shared_ptr< std::vector<Vec2f> >& points)
+{
+ QMutexLocker lock(&mutex);
+ if (frame.empty()) return false;
+
+ // copy the frame and points from the tracker thread
+ frame_copy = frame.clone();
+ points = boost::shared_ptr< vector<Vec2f> >(new vector<Vec2f>(point_extractor.get_points()));
+ return true;
+}
+
+void Tracker::update_show_video_widget()
+{
+ if (!show_video_widget && video_widget) {
+ delete video_widget;
+ video_widget = NULL;
+ if (video_frame->layout()) delete video_frame->layout();
+ }
+ else if (video_frame && show_video_widget && !video_widget)
+ {
+ const int VIDEO_FRAME_WIDTH = 252;
+ const int VIDEO_FRAME_HEIGHT = 189;
+
+ video_widget = new VideoWidget(video_frame, this);
+ QHBoxLayout* video_layout = new QHBoxLayout();
+ video_layout->setContentsMargins(0, 0, 0, 0);
+ video_layout->addWidget(video_widget);
+ video_frame->setLayout(video_layout);
+ video_widget->resize(VIDEO_FRAME_WIDTH, VIDEO_FRAME_HEIGHT);
+ }
+}
+
+//-----------------------------------------------------------------------------
+// ITracker interface
+void Tracker::Initialize(QFrame *video_frame)
+{
+ qDebug("Tracker::Initialize");
+ // setup video frame
+ this->video_frame = video_frame;
+ video_frame->setAttribute(Qt::WA_NativeWindow);
+ video_frame->show();
+ update_show_video_widget();
+}
+
+void Tracker::refreshVideo()
+{
+ if (video_widget) video_widget->update_frame_and_points();
+}
+
+void Tracker::StartTracker(HWND parent_window)
+{
+ reset_command(PAUSE);
+}
+
+void Tracker::StopTracker(bool exit)
+{
+ set_command(PAUSE);
+}
+
+bool Tracker::GiveHeadPoseData(THeadPoseData *data)
+{
+ {
+ QMutexLocker lock(&mutex);
+
+ if (!tracking_valid) return false;
+
+ FrameTrafo X_CM = point_tracker.get_pose();
+ FrameTrafo X_MH(Matx33f::eye(), t_MH);
+ FrameTrafo X_GH = R_GC * X_CM * X_MH;
+ Matx33f R = X_GH.R * X_GH_0.R.t();
+ Vec3f t = X_GH.t - X_GH_0.t;
+
+ // get translation(s)
+ if (bEnableX) data->x = t[0] / 10.0; // convert to cm
+ if (bEnableY) data->y = t[1] / 10.0;
+ if (bEnableZ) data->z = t[2] / 10.0;
+
+ // translate rotation matrix from opengl (G) to roll-pitch-yaw (E) frame
+ // -z -> x, y -> z, x -> -y
+ Matx33f R_EG( 0, 0,-1,
+ -1, 0, 0,
+ 0, 1, 0);
+ R = R_EG * R * R_EG.t();
+
+ // extract rotation angles
+ float alpha, beta, gamma;
+ beta = atan2( -R(2,0), sqrt(R(2,1)*R(2,1) + R(2,2)*R(2,2)) );
+ alpha = atan2( R(1,0), R(0,0));
+ gamma = atan2( R(2,1), R(2,2));
+
+ if (bEnableYaw) data->yaw = rad2deg * alpha;
+ if (bEnablePitch) data->pitch = - rad2deg * beta; // FTNoIR expects a minus here
+ if (bEnableRoll) data->roll = rad2deg * gamma;
+ }
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+#pragma comment(linker, "/export:GetTracker=_GetTracker@0")
+
+FTNOIR_TRACKER_BASE_EXPORT ITrackerPtr __stdcall GetTracker()
+{
+ return new Tracker;
+}
\ No newline at end of file diff --git a/ftnoir_tracker_pt/ftnoir_tracker_pt.h b/FTNoIR_Tracker_PT/ftnoir_tracker_pt.h index 3825fce7..6eef945a 100644 --- a/ftnoir_tracker_pt/ftnoir_tracker_pt.h +++ b/FTNoIR_Tracker_PT/ftnoir_tracker_pt.h @@ -1,96 +1,99 @@ -/* 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 FTNOIR_TRACKER_PT_H -#define FTNOIR_TRACKER_PT_H - -#include "ftnoir_tracker_base/ftnoir_tracker_base.h" -#include "ftnoir_tracker_pt_settings.h" -#include "camera.h" -#include "point_extractor.h" -#include "point_tracker.h" -#include "video_widget.h" -#include "timer.h" - -#include <QThread> -#include <QMutex> -#include <QTime> -#include <opencv2/opencv.hpp> -#include <QFrame> -#include <QTimer> - -//----------------------------------------------------------------------------- -class Tracker : public QThread, public ITracker -{ - Q_OBJECT -public: - Tracker(); - ~Tracker(); - - // ITracker interface - void StartTracker(QFrame* videoFrame); - bool GiveHeadPoseData(double *data); - - void refreshVideo(); - - void apply(const TrackerSettings& settings); - void center(); - void reset(); // reset the trackers internal state variables - void run(); - void WaitForExit() { - should_quit = true; - wait(); - } - - void get_pose(FrameTrafo* X_CM) { QMutexLocker lock(&mutex); *X_CM = point_tracker.get_pose(); } - int get_n_points() { QMutexLocker lock(&mutex); return point_extractor.get_points().size(); } - void get_cam_info(CamInfo* info) { QMutexLocker lock(&mutex); *info = camera.get_info(); } - -protected: - FrameTrafo X_CH_0; // for centering - cv::Mat frame; // the output frame for display - - enum Command { - ABORT = 1<<0, - PAUSE = 1<<1 - }; - void set_command(Command command); - void reset_command(Command command); - - CVCamera camera; - PointExtractor point_extractor; - PointTracker point_tracker; - bool tracking_valid; - - cv::Vec3f t_MH; - int cam_pitch; - - bool draw_frame; - int sleep_time; - - bool bEnableRoll; - bool bEnablePitch; - bool bEnableYaw; - bool bEnableX; - bool bEnableY; - bool bEnableZ; - - long frame_count; - volatile int commands; - - VideoWidget* video_widget; - Timer time; - QMutex mutex; - volatile bool should_quit; - volatile bool fresh; - QTimer timer; - -protected slots: - void paint_widget(); -}; - -#endif // FTNOIR_TRACKER_PT_H +/* 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 FTNOIR_TRACKER_PT_H
+#define FTNOIR_TRACKER_PT_H
+
+#include "..\ftnoir_tracker_base\ftnoir_tracker_base.h"
+#include "ftnoir_tracker_pt_settings.h"
+#include "frame_observer.h"
+#include "camera.h"
+#include "point_extractor.h"
+#include "point_tracker.h"
+#include "video_widget.h"
+#include "timer.h"
+
+#include <QThread>
+#include <QMutex>
+#include <QTime>
+#include <opencv2/opencv.hpp>
+#include <boost/shared_ptr.hpp>
+#include <vector>
+
+//-----------------------------------------------------------------------------
+// Constantly processes the tracking chain in a separate thread
+class Tracker : public ITracker, QThread, public FrameProvider
+{
+public:
+ Tracker();
+ ~Tracker();
+
+ // --- ITracker interface ---
+ virtual void Initialize(QFrame *videoframe);
+ virtual void StartTracker(HWND parent_window);
+ virtual void StopTracker(bool exit);
+ virtual bool GiveHeadPoseData(THeadPoseData *data);
+ virtual void refreshVideo();
+
+ void apply(const TrackerSettings& settings);
+ void center();
+ void reset(); // reset the trackers internal state variables
+ void run();
+
+ void get_pose(FrameTrafo* X_CM) { QMutexLocker lock(&mutex); *X_CM = point_tracker.get_pose(); }
+ int get_n_points() { QMutexLocker lock(&mutex); return point_extractor.get_points().size(); }
+ void get_cam_info(CamInfo* info) { QMutexLocker lock(&mutex); *info = camera.get_info(); }
+
+protected:
+ // --- MutexedFrameProvider interface ---
+ virtual bool get_frame_and_points(cv::Mat& frame, boost::shared_ptr< std::vector<cv::Vec2f> >& points);
+
+ // --- thread ---
+ QMutex mutex;
+ // thread commands
+ enum Command {
+ ABORT = 1<<0,
+ PAUSE = 1<<1
+ };
+ void set_command(Command command);
+ void reset_command(Command command);
+ int commands;
+
+ int sleep_time;
+
+ // --- tracking chain ---
+ VICamera camera;
+ FrameRotation frame_rotation;
+ PointExtractor point_extractor;
+ PointTracker point_tracker;
+ bool tracking_valid;
+
+ FrameTrafo X_GH_0; // for centering
+ cv::Vec3f t_MH; // translation from model frame to head frame
+ cv::Matx33f R_GC; // rotation from opengl reference frame to camera frame
+
+ // --- ui ---
+ cv::Mat frame; // the output frame for display
+
+ void update_show_video_widget();
+ bool show_video_widget;
+ VideoWidget* video_widget;
+ QFrame* video_frame;
+
+ // --- misc ---
+ bool bEnableRoll;
+ bool bEnablePitch;
+ bool bEnableYaw;
+ bool bEnableX;
+ bool bEnableY;
+ bool bEnableZ;
+
+ long frame_count;
+ Timer time;
+};
+
+#endif // FTNOIR_TRACKER_PT_H
diff --git a/FTNoIR_Tracker_PT/ftnoir_tracker_pt.qrc b/FTNoIR_Tracker_PT/ftnoir_tracker_pt.qrc new file mode 100644 index 00000000..9b510981 --- /dev/null +++ b/FTNoIR_Tracker_PT/ftnoir_tracker_pt.qrc @@ -0,0 +1,10 @@ +<RCC>
+ <qresource prefix="/">
+ <file>Resources/icon.ico</file>
+ <file>Resources/cap_front.png</file>
+ <file>Resources/cap_side.png</file>
+ <file>Resources/clip_front.png</file>
+ <file>Resources/clip_side.png</file>
+ <file>Resources/Logo_IR.png</file>
+ </qresource>
+</RCC>
diff --git a/ftnoir_tracker_pt/ftnoir_tracker_pt_dialog.cpp b/FTNoIR_Tracker_PT/ftnoir_tracker_pt_dialog.cpp index f222085e..c99f4d67 100644 --- a/ftnoir_tracker_pt/ftnoir_tracker_pt_dialog.cpp +++ b/FTNoIR_Tracker_PT/ftnoir_tracker_pt_dialog.cpp @@ -1,337 +1,406 @@ -/* 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 "ftnoir_tracker_pt_dialog.h" - -#include <QMessageBox> -#include <QDebug> -#include "facetracknoir/global-settings.h" - -//----------------------------------------------------------------------------- -TrackerDialog::TrackerDialog() - : settings_dirty(false), tracker(NULL), trans_calib_running(false), timer(this) -{ - qDebug()<<"TrackerDialog::TrackerDialog"; - setAttribute(Qt::WA_DeleteOnClose, false); - - ui.setupUi( this ); - - settings.load_ini(); - dialog_settings.load_ini(); - - // initialize ui values - ui.videowidget_check->setChecked(settings.video_widget); - ui.dynpose_check->setChecked(settings.dyn_pose_res); - ui.sleep_spin->setValue(settings.sleep_time); - ui.reset_spin->setValue(settings.reset_time); - ui.camindex_spin->setValue(settings.cam_index); - ui.f_dspin->setValue(settings.cam_f); - ui.res_x_spin->setValue(settings.cam_res_x); - ui.res_y_spin->setValue(settings.cam_res_y); - ui.fps_spin->setValue(settings.cam_fps); - ui.campitch_spin->setValue(settings.cam_pitch); - ui.threshold_slider->setValue(settings.threshold); - - ui.chkEnableRoll->setChecked(settings.bEnableRoll); - ui.chkEnablePitch->setChecked(settings.bEnablePitch); - ui.chkEnableYaw->setChecked(settings.bEnableYaw); - ui.chkEnableX->setChecked(settings.bEnableX); - ui.chkEnableY->setChecked(settings.bEnableY); - ui.chkEnableZ->setChecked(settings.bEnableZ); - - ui.mindiam_spin->setValue(settings.min_point_size); - ui.maxdiam_spin->setValue(settings.max_point_size); - ui.model_tabs->setCurrentIndex(dialog_settings.active_model_panel); - ui.clip_bheight_spin->setValue(dialog_settings.clip_by); - ui.clip_blength_spin->setValue(dialog_settings.clip_bz); - ui.clip_theight_spin->setValue(dialog_settings.clip_ty); - ui.clip_tlength_spin->setValue(dialog_settings.clip_tz); - ui.cap_width_spin->setValue(dialog_settings.cap_x); - ui.cap_height_spin->setValue(dialog_settings.cap_y); - ui.cap_length_spin->setValue(dialog_settings.cap_z); - ui.m1x_spin->setValue(dialog_settings.M01x); - ui.m1y_spin->setValue(dialog_settings.M01y); - ui.m1z_spin->setValue(dialog_settings.M01z); - ui.m2x_spin->setValue(dialog_settings.M02x); - ui.m2y_spin->setValue(dialog_settings.M02y); - ui.m2z_spin->setValue(dialog_settings.M02z); - ui.tx_spin->setValue(settings.t_MH[0]); - ui.ty_spin->setValue(settings.t_MH[1]); - ui.tz_spin->setValue(settings.t_MH[2]); - - // connect Qt signals and slots - connect( ui.videowidget_check,SIGNAL(toggled(bool)), this,SLOT(set_video_widget(bool)) ); - connect( ui.dynpose_check,SIGNAL(toggled(bool)), this,SLOT(set_dyn_pose_res(bool)) ); - connect( ui.sleep_spin,SIGNAL(valueChanged(int)), this,SLOT(set_sleep_time(int)) ); - connect( ui.reset_spin,SIGNAL(valueChanged(int)), this,SLOT(set_reset_time(int)) ); - connect( ui.camindex_spin,SIGNAL(valueChanged(int)), this,SLOT(set_cam_index(int)) ); - connect( ui.f_dspin,SIGNAL(valueChanged(double)), this,SLOT(set_cam_f(double)) ); - connect( ui.res_x_spin,SIGNAL(valueChanged(int)), this,SLOT(set_cam_res_x(int)) ); - connect( ui.res_y_spin,SIGNAL(valueChanged(int)), this,SLOT(set_cam_res_y(int)) ); - connect( ui.fps_spin,SIGNAL(valueChanged(int)), this,SLOT(set_cam_fps(int)) ); - connect( ui.campitch_spin,SIGNAL(valueChanged(int)), this,SLOT(set_cam_pitch(int)) ); - connect( ui.threshold_slider,SIGNAL(sliderMoved(int)), this,SLOT(set_threshold(int)) ); - - connect( ui.chkEnableRoll,SIGNAL(toggled(bool)), this,SLOT(set_ena_roll(bool)) ); - connect( ui.chkEnablePitch,SIGNAL(toggled(bool)), this,SLOT(set_ena_pitch(bool)) ); - connect( ui.chkEnableYaw,SIGNAL(toggled(bool)), this,SLOT(set_ena_yaw(bool)) ); - connect( ui.chkEnableX,SIGNAL(toggled(bool)), this,SLOT(set_ena_x(bool)) ); - connect( ui.chkEnableY,SIGNAL(toggled(bool)), this,SLOT(set_ena_y(bool)) ); - connect( ui.chkEnableZ,SIGNAL(toggled(bool)), this,SLOT(set_ena_z(bool)) ); - - connect( ui.mindiam_spin,SIGNAL(valueChanged(int)), this,SLOT(set_min_point_size(int)) ); - connect( ui.maxdiam_spin,SIGNAL(valueChanged(int)), this,SLOT(set_max_point_size(int)) ); - connect( ui.model_tabs,SIGNAL(currentChanged(int)), this,SLOT(set_model(int)) ); - connect( ui.clip_theight_spin,SIGNAL(valueChanged(int)), this,SLOT(set_clip_t_height(int)) ); - connect( ui.clip_tlength_spin,SIGNAL(valueChanged(int)), this,SLOT(set_clip_t_length(int)) ); - connect( ui.clip_bheight_spin,SIGNAL(valueChanged(int)), this,SLOT(set_clip_b_height(int)) ); - connect( ui.clip_blength_spin,SIGNAL(valueChanged(int)), this,SLOT(set_clip_b_length(int)) ); - connect( ui.cap_width_spin,SIGNAL(valueChanged(int)), this,SLOT(set_cap_width(int)) ); - connect( ui.cap_height_spin,SIGNAL(valueChanged(int)), this,SLOT(set_cap_height(int)) ); - connect( ui.cap_length_spin,SIGNAL(valueChanged(int)), this,SLOT(set_cap_length(int)) ); - connect( ui.m1x_spin,SIGNAL(valueChanged(int)), this,SLOT(set_m1x(int)) ); - connect( ui.m1y_spin,SIGNAL(valueChanged(int)), this,SLOT(set_m1y(int)) ); - connect( ui.m1z_spin,SIGNAL(valueChanged(int)), this,SLOT(set_m1z(int)) ); - connect( ui.m2x_spin,SIGNAL(valueChanged(int)), this,SLOT(set_m2x(int)) ); - connect( ui.m2y_spin,SIGNAL(valueChanged(int)), this,SLOT(set_m2y(int)) ); - connect( ui.m2z_spin,SIGNAL(valueChanged(int)), this,SLOT(set_m2z(int)) ); - connect( ui.tx_spin,SIGNAL(valueChanged(int)), this,SLOT(set_tx(int)) ); - connect( ui.ty_spin,SIGNAL(valueChanged(int)), this,SLOT(set_ty(int)) ); - connect( ui.tz_spin,SIGNAL(valueChanged(int)), this,SLOT(set_tz(int)) ); - - connect( ui.tcalib_button,SIGNAL(toggled(bool)), this,SLOT(startstop_trans_calib(bool)) ); - - connect(ui.reset_button, SIGNAL(clicked()), this, SLOT(doReset())); - //connect(ui.center_button, SIGNAL(clicked()), this, SLOT(doCenter())); - - connect(ui.ok_button, SIGNAL(clicked()), this, SLOT(doOK())); - connect(ui.cancel_button, SIGNAL(clicked()), this, SLOT(doCancel())); - - connect(&timer,SIGNAL(timeout()), this,SLOT(poll_tracker_info())); - timer.start(100); -} - -TrackerDialog::~TrackerDialog() -{ - qDebug()<<"TrackerDialog::~TrackerDialog"; -} - -void TrackerDialog::set_clip() -{ - settings.M01[0] = 0; - settings.M01[1] = dialog_settings.clip_ty; - settings.M01[2] = -dialog_settings.clip_tz; - settings.M02[0] = 0; - settings.M02[1] = -dialog_settings.clip_by; - settings.M02[2] = -dialog_settings.clip_bz; - - settings_changed(); -} - -void TrackerDialog::set_cap() -{ - settings.M01[0] = -dialog_settings.cap_x; - settings.M01[1] = -dialog_settings.cap_y; - settings.M01[2] = -dialog_settings.cap_z; - settings.M02[0] = dialog_settings.cap_x; - settings.M02[1] = -dialog_settings.cap_y; - settings.M02[2] = -dialog_settings.cap_z; - - settings_changed(); -} - -void TrackerDialog::set_custom() -{ - settings.M01[0] = dialog_settings.M01x; - settings.M01[1] = dialog_settings.M01y; - settings.M01[2] = dialog_settings.M01z; - settings.M02[0] = dialog_settings.M02x; - settings.M02[1] = dialog_settings.M02y; - settings.M02[2] = dialog_settings.M02z; - - settings_changed(); -} - -void TrackerDialog::set_model(int val) -{ - dialog_settings.active_model_panel = val; - - switch (val) { - - case TrackerDialogSettings::MODEL_CLIP: - set_clip(); - break; - - case TrackerDialogSettings::MODEL_CAP: - set_cap(); - break; - - case TrackerDialogSettings::MODEL_CUSTOM: - set_custom(); - break; - - default: - break; - } -} - -void TrackerDialog::startstop_trans_calib(bool start) -{ - if (start) - { - qDebug()<<"TrackerDialog:: Starting translation calibration"; - trans_calib.reset(); - trans_calib_running = true; - } - else - { - qDebug()<<"TrackerDialog:: Stoppping translation calibration"; - trans_calib_running = false; - settings.t_MH = trans_calib.get_estimate(); - settings_changed(); - } -} - -void TrackerDialog::trans_calib_step() -{ - if (tracker) - { - FrameTrafo X_CM; - tracker->get_pose(&X_CM); - trans_calib.update(X_CM.R, X_CM.t); - cv::Vec3f t_MH = trans_calib.get_estimate(); - //qDebug()<<"TrackerDialog:: Current translation estimate: "<<t_MH[0]<<t_MH[1]<<t_MH[2]; - ui.tx_spin->setValue(t_MH[0]); - ui.ty_spin->setValue(t_MH[1]); - ui.tz_spin->setValue(t_MH[2]); - } -} - -void TrackerDialog::settings_changed() -{ - settings_dirty = true; - if (tracker) tracker->apply(settings); -} - -void TrackerDialog::doCenter() -{ - if (tracker) tracker->center(); -} - -void TrackerDialog::doReset() -{ - if (tracker) tracker->reset(); -} - -void TrackerDialog::doOK() -{ - settings.save_ini(); - dialog_settings.save_ini(); - close(); -} - -void TrackerDialog::doCancel() -{ - if (settings_dirty) { - int ret = QMessageBox::question ( this, "Settings have changed", "Do you want to save the settings?", - QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel, QMessageBox::Discard ); - switch (ret) { - case QMessageBox::Save: - settings.save_ini(); - dialog_settings.save_ini(); - close(); - break; - case QMessageBox::Discard: - close(); - break; - case QMessageBox::Cancel: - // Cancel was clicked - break; - default: - // should never be reached - break; - } - } - else { - close(); - } -} - -void TrackerDialog::poll_tracker_info() -{ - if (tracker) - { - QString to_print; - - // display caminfo - CamInfo info; - tracker->get_cam_info(&info); - to_print = QString::number(info.res_x)+"x"+QString::number(info.res_y)+" @ "+QString::number(info.fps)+" FPS"; - ui.caminfo_label->setText(to_print); - ui.caminfo_label_2->setText(to_print); - - // display pointinfo - int n_points = tracker->get_n_points(); - to_print = QString::number(n_points); - if (n_points == 3) - to_print += " OK!"; - else - to_print += " BAD!"; - ui.pointinfo_label->setText(to_print); - ui.pointinfo_label_2->setText(to_print); - - // update calibration - if (trans_calib_running) trans_calib_step(); - } - else - { - QString to_print = "Tracker offline"; - ui.caminfo_label->setText(to_print); - ui.caminfo_label_2->setText(to_print); - ui.pointinfo_label->setText(to_print); - ui.pointinfo_label_2->setText(to_print); - } -} - - -//----------------------------------------------------------------------------- -// ITrackerDialog interface -void TrackerDialog::Initialize(QWidget *parent) -{ - QPoint offsetpos(200, 200); - if (parent) { - this->move(parent->pos() + offsetpos); - } - show(); -} - -void TrackerDialog::registerTracker(ITracker *t) -{ - qDebug()<<"TrackerDialog:: Tracker registered"; - tracker = static_cast<Tracker*>(t); - if (isVisible() && settings_dirty) tracker->apply(settings); - ui.tcalib_button->setEnabled(true); - //ui.center_button->setEnabled(true); - ui.reset_button->setEnabled(true); -} - -void TrackerDialog::unRegisterTracker() -{ - qDebug()<<"TrackerDialog:: Tracker un-registered"; - tracker = NULL; - ui.tcalib_button->setEnabled(false); - //ui.center_button->setEnabled(false); - ui.reset_button->setEnabled(false); -} - -//----------------------------------------------------------------------------- -//#pragma comment(linker, "/export:GetTrackerDialog=_GetTrackerDialog@0") - -extern "C" FTNOIR_TRACKER_BASE_EXPORT ITrackerDialog* CALLING_CONVENTION GetDialog( ) -{ - return new TrackerDialog; -} +/* 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 "ftnoir_tracker_pt_dialog.h"
+
+#include <QMessageBox>
+#include <QDebug>
+#include <opencv2/opencv.hpp>
+#include <boost/shared_ptr.hpp>
+#include <vector>
+
+using namespace std;
+
+//-----------------------------------------------------------------------------
+TrackerDialog::TrackerDialog()
+ : settings_dirty(false),
+ tracker(NULL),
+ video_widget_dialog(NULL),
+ timer(this),
+ trans_calib_running(false)
+{
+ qDebug()<<"TrackerDialog::TrackerDialog";
+ setAttribute(Qt::WA_DeleteOnClose, false);
+
+ ui.setupUi( this );
+
+ settings.load_ini();
+ dialog_settings.load_ini();
+
+ // initialize ui values
+ ui.videowidget_check->setChecked(settings.video_widget);
+ ui.dynpose_check->setChecked(settings.dyn_pose_res);
+ ui.sleep_spin->setValue(settings.sleep_time);
+ ui.reset_spin->setValue(settings.reset_time);
+
+ vector<string> device_names;
+ get_camera_device_names(device_names);
+ for (auto iter = device_names.begin(); iter != device_names.end(); ++iter)
+ {
+ ui.camdevice_combo->addItem(iter->c_str());
+ }
+ ui.camdevice_combo->setCurrentIndex(settings.cam_index);
+
+ ui.f_dspin->setValue(settings.cam_f);
+ ui.res_x_spin->setValue(settings.cam_res_x);
+ ui.res_y_spin->setValue(settings.cam_res_y);
+ ui.fps_spin->setValue(settings.cam_fps);
+
+ ui.camroll_combo->addItem("-90", -1);
+ ui.camroll_combo->addItem("0" , 0);
+ ui.camroll_combo->addItem("90" , 1);
+ int i = ui.camroll_combo->findData(settings.cam_roll);
+ ui.camroll_combo->setCurrentIndex(i>=0 ? i : 0);
+
+ ui.campitch_spin->setValue(settings.cam_pitch);
+ ui.camyaw_spin->setValue(settings.cam_yaw);
+ ui.threshold_slider->setValue(settings.threshold);
+
+ ui.chkEnableRoll->setChecked(settings.bEnableRoll);
+ ui.chkEnablePitch->setChecked(settings.bEnablePitch);
+ ui.chkEnableYaw->setChecked(settings.bEnableYaw);
+ ui.chkEnableX->setChecked(settings.bEnableX);
+ ui.chkEnableY->setChecked(settings.bEnableY);
+ ui.chkEnableZ->setChecked(settings.bEnableZ);
+
+ ui.mindiam_spin->setValue(settings.min_point_size);
+ ui.maxdiam_spin->setValue(settings.max_point_size);
+ ui.model_tabs->setCurrentIndex(dialog_settings.active_model_panel);
+ ui.clip_bheight_spin->setValue(dialog_settings.clip_by);
+ ui.clip_blength_spin->setValue(dialog_settings.clip_bz);
+ ui.clip_theight_spin->setValue(dialog_settings.clip_ty);
+ ui.clip_tlength_spin->setValue(dialog_settings.clip_tz);
+ ui.cap_width_spin->setValue(dialog_settings.cap_x);
+ ui.cap_height_spin->setValue(dialog_settings.cap_y);
+ ui.cap_length_spin->setValue(dialog_settings.cap_z);
+ ui.m1x_spin->setValue(dialog_settings.M01x);
+ ui.m1y_spin->setValue(dialog_settings.M01y);
+ ui.m1z_spin->setValue(dialog_settings.M01z);
+ ui.m2x_spin->setValue(dialog_settings.M02x);
+ ui.m2y_spin->setValue(dialog_settings.M02y);
+ ui.m2z_spin->setValue(dialog_settings.M02z);
+ ui.tx_spin->setValue(settings.t_MH[0]);
+ ui.ty_spin->setValue(settings.t_MH[1]);
+ ui.tz_spin->setValue(settings.t_MH[2]);
+
+ // connect Qt signals and slots
+ connect( ui.videowidget_check,SIGNAL(toggled(bool)), this,SLOT(set_video_widget(bool)) );
+ connect( ui.dynpose_check,SIGNAL(toggled(bool)), this,SLOT(set_dyn_pose_res(bool)) );
+ connect( ui.sleep_spin,SIGNAL(valueChanged(int)), this,SLOT(set_sleep_time(int)) );
+ connect( ui.reset_spin,SIGNAL(valueChanged(int)), this,SLOT(set_reset_time(int)) );
+ connect( ui.camdevice_combo,SIGNAL(currentIndexChanged(int)), this,SLOT(set_cam_index(int)) );
+ connect( ui.f_dspin,SIGNAL(valueChanged(double)), this,SLOT(set_cam_f(double)) );
+ connect( ui.res_x_spin,SIGNAL(valueChanged(int)), this,SLOT(set_cam_res_x(int)) );
+ connect( ui.res_y_spin,SIGNAL(valueChanged(int)), this,SLOT(set_cam_res_y(int)) );
+ connect( ui.fps_spin,SIGNAL(valueChanged(int)), this,SLOT(set_cam_fps(int)) );
+ connect( ui.camroll_combo,SIGNAL(currentIndexChanged(int)), this,SLOT(set_cam_roll(int)) );
+ connect( ui.campitch_spin,SIGNAL(valueChanged(int)), this,SLOT(set_cam_pitch(int)) );
+ connect( ui.camyaw_spin,SIGNAL(valueChanged(int)), this,SLOT(set_cam_yaw(int)) );
+ connect( ui.threshold_slider,SIGNAL(sliderMoved(int)), this,SLOT(set_threshold(int)) );
+
+ connect( ui.chkEnableRoll,SIGNAL(toggled(bool)), this,SLOT(set_ena_roll(bool)) );
+ connect( ui.chkEnablePitch,SIGNAL(toggled(bool)), this,SLOT(set_ena_pitch(bool)) );
+ connect( ui.chkEnableYaw,SIGNAL(toggled(bool)), this,SLOT(set_ena_yaw(bool)) );
+ connect( ui.chkEnableX,SIGNAL(toggled(bool)), this,SLOT(set_ena_x(bool)) );
+ connect( ui.chkEnableY,SIGNAL(toggled(bool)), this,SLOT(set_ena_y(bool)) );
+ connect( ui.chkEnableZ,SIGNAL(toggled(bool)), this,SLOT(set_ena_z(bool)) );
+
+ connect( ui.mindiam_spin,SIGNAL(valueChanged(int)), this,SLOT(set_min_point_size(int)) );
+ connect( ui.maxdiam_spin,SIGNAL(valueChanged(int)), this,SLOT(set_max_point_size(int)) );
+ connect( ui.model_tabs,SIGNAL(currentChanged(int)), this,SLOT(set_model(int)) );
+ connect( ui.clip_theight_spin,SIGNAL(valueChanged(int)), this,SLOT(set_clip_t_height(int)) );
+ connect( ui.clip_tlength_spin,SIGNAL(valueChanged(int)), this,SLOT(set_clip_t_length(int)) );
+ connect( ui.clip_bheight_spin,SIGNAL(valueChanged(int)), this,SLOT(set_clip_b_height(int)) );
+ connect( ui.clip_blength_spin,SIGNAL(valueChanged(int)), this,SLOT(set_clip_b_length(int)) );
+ connect( ui.cap_width_spin,SIGNAL(valueChanged(int)), this,SLOT(set_cap_width(int)) );
+ connect( ui.cap_height_spin,SIGNAL(valueChanged(int)), this,SLOT(set_cap_height(int)) );
+ connect( ui.cap_length_spin,SIGNAL(valueChanged(int)), this,SLOT(set_cap_length(int)) );
+ connect( ui.m1x_spin,SIGNAL(valueChanged(int)), this,SLOT(set_m1x(int)) );
+ connect( ui.m1y_spin,SIGNAL(valueChanged(int)), this,SLOT(set_m1y(int)) );
+ connect( ui.m1z_spin,SIGNAL(valueChanged(int)), this,SLOT(set_m1z(int)) );
+ connect( ui.m2x_spin,SIGNAL(valueChanged(int)), this,SLOT(set_m2x(int)) );
+ connect( ui.m2y_spin,SIGNAL(valueChanged(int)), this,SLOT(set_m2y(int)) );
+ connect( ui.m2z_spin,SIGNAL(valueChanged(int)), this,SLOT(set_m2z(int)) );
+ connect( ui.tx_spin,SIGNAL(valueChanged(int)), this,SLOT(set_tx(int)) );
+ connect( ui.ty_spin,SIGNAL(valueChanged(int)), this,SLOT(set_ty(int)) );
+ connect( ui.tz_spin,SIGNAL(valueChanged(int)), this,SLOT(set_tz(int)) );
+
+ connect( ui.tcalib_button,SIGNAL(toggled(bool)), this,SLOT(startstop_trans_calib(bool)) );
+
+ connect( ui.videowidget_button,SIGNAL(clicked()), this,SLOT(create_video_widget()) );
+
+ connect(ui.reset_button, SIGNAL(clicked()), this, SLOT(doReset()));
+ //connect(ui.center_button, SIGNAL(clicked()), this, SLOT(doCenter()));
+
+ connect(ui.ok_button, SIGNAL(clicked()), this, SLOT(doOK()));
+ connect(ui.cancel_button, SIGNAL(clicked()), this, SLOT(doCancel()));
+
+ connect(&timer,SIGNAL(timeout()), this,SLOT(poll_tracker_info()));
+ timer.start(100);
+}
+
+TrackerDialog::~TrackerDialog()
+{
+ qDebug()<<"TrackerDialog::~TrackerDialog";
+}
+
+void TrackerDialog::set_cam_roll(int idx)
+{
+ settings.cam_roll = ui.camroll_combo->itemData(idx).toInt();
+ settings_changed();
+}
+
+void TrackerDialog::set_model_clip()
+{
+ settings.M01[0] = 0;
+ settings.M01[1] = dialog_settings.clip_ty;
+ settings.M01[2] = -dialog_settings.clip_tz;
+ settings.M02[0] = 0;
+ settings.M02[1] = -dialog_settings.clip_by;
+ settings.M02[2] = -dialog_settings.clip_bz;
+
+ settings_changed();
+}
+
+void TrackerDialog::set_model_cap()
+{
+ settings.M01[0] = -dialog_settings.cap_x;
+ settings.M01[1] = -dialog_settings.cap_y;
+ settings.M01[2] = -dialog_settings.cap_z;
+ settings.M02[0] = dialog_settings.cap_x;
+ settings.M02[1] = -dialog_settings.cap_y;
+ settings.M02[2] = -dialog_settings.cap_z;
+
+ settings_changed();
+}
+
+void TrackerDialog::set_model_custom()
+{
+ settings.M01[0] = dialog_settings.M01x;
+ settings.M01[1] = dialog_settings.M01y;
+ settings.M01[2] = dialog_settings.M01z;
+ settings.M02[0] = dialog_settings.M02x;
+ settings.M02[1] = dialog_settings.M02y;
+ settings.M02[2] = dialog_settings.M02z;
+
+ settings_changed();
+}
+
+void TrackerDialog::set_model(int val)
+{
+ dialog_settings.active_model_panel = val;
+
+ switch (val) {
+
+ case TrackerDialogSettings::MODEL_CLIP:
+ set_model_clip();
+ break;
+
+ case TrackerDialogSettings::MODEL_CAP:
+ set_model_cap();
+ break;
+
+ case TrackerDialogSettings::MODEL_CUSTOM:
+ set_model_custom();
+ break;
+
+ default:
+ break;
+ }
+}
+
+void TrackerDialog::startstop_trans_calib(bool start)
+{
+ if (start)
+ {
+ qDebug()<<"TrackerDialog:: Starting translation calibration";
+ trans_calib.reset();
+ trans_calib_running = true;
+ }
+ else
+ {
+ qDebug()<<"TrackerDialog:: Stoppping translation calibration";
+ trans_calib_running = false;
+ settings.t_MH = trans_calib.get_estimate();
+ settings_changed();
+ }
+}
+
+void TrackerDialog::trans_calib_step()
+{
+ if (tracker)
+ {
+ FrameTrafo X_CM;
+ tracker->get_pose(&X_CM);
+ trans_calib.update(X_CM.R, X_CM.t);
+ cv::Vec3f t_MH = trans_calib.get_estimate();
+ //qDebug()<<"TrackerDialog:: Current translation estimate: "<<t_MH[0]<<t_MH[1]<<t_MH[2];
+ ui.tx_spin->setValue(t_MH[0]);
+ ui.ty_spin->setValue(t_MH[1]);
+ ui.tz_spin->setValue(t_MH[2]);
+ }
+}
+
+void TrackerDialog::settings_changed()
+{
+ settings_dirty = true;
+ if (tracker) tracker->apply(settings);
+}
+
+void TrackerDialog::doCenter()
+{
+ if (tracker) tracker->center();
+}
+
+void TrackerDialog::doReset()
+{
+ if (tracker) tracker->reset();
+}
+
+void TrackerDialog::doOK()
+{
+ settings.save_ini();
+ dialog_settings.save_ini();
+ close();
+}
+
+void TrackerDialog::doCancel()
+{
+ if (settings_dirty) {
+ int ret = QMessageBox::question ( this, "Settings have changed", "Do you want to save the settings?",
+ QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel, QMessageBox::Discard );
+ switch (ret) {
+ case QMessageBox::Save:
+ settings.save_ini();
+ dialog_settings.save_ini();
+ close();
+ break;
+ case QMessageBox::Discard:
+ close();
+ break;
+ case QMessageBox::Cancel:
+ // Cancel was clicked
+ break;
+ default:
+ // should never be reached
+ break;
+ }
+ }
+ else {
+ close();
+ }
+}
+
+void TrackerDialog::widget_destroyed(QObject* obj)
+{
+ if (obj == video_widget_dialog) {
+ // widget was / will be already deleted by Qt
+ destroy_video_widget(false);
+ }
+}
+
+void TrackerDialog::create_video_widget()
+{
+ // this should not happen but better be sure
+ if (video_widget_dialog) destroy_video_widget();
+ if (!tracker) return;
+
+ video_widget_dialog = new VideoWidgetDialog(this, tracker);
+ video_widget_dialog->setAttribute( Qt::WA_DeleteOnClose );
+ connect( video_widget_dialog, SIGNAL(destroyed(QObject*)), this, SLOT(widget_destroyed(QObject*)) );
+ video_widget_dialog->show();
+
+ ui.videowidget_button->setEnabled(false);
+}
+
+void TrackerDialog::destroy_video_widget(bool do_delete /*= true*/)
+{
+ if (video_widget_dialog) {
+ if (do_delete) delete video_widget_dialog;
+ video_widget_dialog = NULL;
+ }
+ if (tracker) ui.videowidget_button->setEnabled(true);
+}
+
+void TrackerDialog::poll_tracker_info()
+{
+ if (tracker)
+ {
+ QString to_print;
+
+ // display caminfo
+ CamInfo info;
+ tracker->get_cam_info(&info);
+ to_print = QString::number(info.res_x)+"x"+QString::number(info.res_y)+" @ "+QString::number(info.fps)+" FPS";
+ ui.caminfo_label->setText(to_print);
+
+ // display pointinfo
+ int n_points = tracker->get_n_points();
+ to_print = QString::number(n_points);
+ if (n_points == 3)
+ to_print += " OK!";
+ else
+ to_print += " BAD!";
+ ui.pointinfo_label->setText(to_print);
+
+ // update calibration
+ if (trans_calib_running) trans_calib_step();
+
+ // update videowidget
+ if (video_widget_dialog) {
+ video_widget_dialog->get_video_widget()->update_frame_and_points();
+ }
+ }
+ else
+ {
+ QString to_print = "Tracker offline";
+ ui.caminfo_label->setText(to_print);
+ ui.pointinfo_label->setText(to_print);
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// ITrackerDialog interface
+void TrackerDialog::Initialize(QWidget *parent)
+{
+ QPoint offsetpos(200, 200);
+ if (parent) {
+ this->move(parent->pos() + offsetpos);
+ }
+ show();
+}
+
+void TrackerDialog::registerTracker(ITracker *t)
+{
+ qDebug()<<"TrackerDialog:: Tracker registered";
+ tracker = static_cast<Tracker*>(t);
+ if (isVisible() && settings_dirty) tracker->apply(settings);
+ ui.videowidget_button->setEnabled(true);
+ ui.tcalib_button->setEnabled(true);
+ //ui.center_button->setEnabled(true);
+ ui.reset_button->setEnabled(true);
+}
+
+void TrackerDialog::unRegisterTracker()
+{
+ qDebug()<<"TrackerDialog:: Tracker un-registered";
+ tracker = NULL;
+ destroy_video_widget();
+ ui.videowidget_button->setEnabled(false);
+ ui.tcalib_button->setEnabled(false);
+ //ui.center_button->setEnabled(false);
+ ui.reset_button->setEnabled(false);
+}
+
+//-----------------------------------------------------------------------------
+#pragma comment(linker, "/export:GetTrackerDialog=_GetTrackerDialog@0")
+
+FTNOIR_TRACKER_BASE_EXPORT ITrackerDialogPtr __stdcall GetTrackerDialog( )
+{
+ return new TrackerDialog;
+}
\ No newline at end of file diff --git a/ftnoir_tracker_pt/ftnoir_tracker_pt_dialog.h b/FTNoIR_Tracker_PT/ftnoir_tracker_pt_dialog.h index f13fe13e..bf0a90f2 100644 --- a/ftnoir_tracker_pt/ftnoir_tracker_pt_dialog.h +++ b/FTNoIR_Tracker_PT/ftnoir_tracker_pt_dialog.h @@ -1,102 +1,116 @@ -/* 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 FTNOIR_TRACKER_PT_DIALOG_H -#define FTNOIR_TRACKER_PT_DIALOG_H - -#include "ftnoir_tracker_base/ftnoir_tracker_base.h" -#include "ftnoir_tracker_pt_settings.h" -#include "ftnoir_tracker_pt.h" -#include "ui_ftnoir_pt_controls.h" -#include "trans_calib.h" - -#include <QTimer> - -//----------------------------------------------------------------------------- -class TrackerDialog : public QWidget, public ITrackerDialog -{ - Q_OBJECT -public: - TrackerDialog(); - ~TrackerDialog(); - - // ITrackerDialog interface - void Initialize(QWidget *parent); - void registerTracker(ITracker *tracker); - void unRegisterTracker(); - - void trans_calib_step(); - -protected slots: - // ugly qt stuff - void set_video_widget(bool val) { settings.video_widget = val; settings_changed(); } - void set_dyn_pose_res(bool val) { settings.dyn_pose_res = val; settings_changed(); } - void set_sleep_time(int val) { settings.sleep_time = val; settings_changed(); } - void set_reset_time(int val) { settings.reset_time = val; settings_changed(); } - void set_cam_index(int val) { settings.cam_index = val; settings_changed(); } - void set_cam_f(double val) { settings.cam_f = val; settings_changed(); } - void set_cam_res_x(int val) { settings.cam_res_x = val; settings_changed(); } - void set_cam_res_y(int val) { settings.cam_res_y = val; settings_changed(); } - void set_cam_fps(int val) { settings.cam_fps = val; settings_changed(); } - void set_cam_pitch(int val) { settings.cam_pitch = val; settings_changed(); } - void set_min_point_size(int val) { settings.min_point_size = val; settings_changed(); } - void set_max_point_size(int val) { settings.max_point_size = val; settings_changed(); } - void set_threshold(int val) { settings.threshold = val; settings_changed(); } - void set_ena_roll(bool val) { settings.bEnableRoll = val; settings_changed(); } - void set_ena_pitch(bool val) { settings.bEnablePitch = val; settings_changed(); } - void set_ena_yaw(bool val) { settings.bEnableYaw = val; settings_changed(); } - void set_ena_x(bool val) { settings.bEnableX = val; settings_changed(); } - void set_ena_y(bool val) { settings.bEnableY = val; settings_changed(); } - void set_ena_z(bool val) { settings.bEnableZ = val; settings_changed(); } - - void set_clip_t_height(int val) { dialog_settings.clip_ty = val; set_clip(); } - void set_clip_t_length(int val) { dialog_settings.clip_tz = val; set_clip(); } - void set_clip_b_height(int val) { dialog_settings.clip_by = val; set_clip(); } - void set_clip_b_length(int val) { dialog_settings.clip_bz = val; set_clip(); } - void set_cap_width(int val) { dialog_settings.cap_x = val; set_cap(); } - void set_cap_height(int val) { dialog_settings.cap_y = val; set_cap(); } - void set_cap_length(int val) { dialog_settings.cap_z = val; set_cap(); } - void set_m1x(int val) { dialog_settings.M01x = val; set_custom(); } - void set_m1y(int val) { dialog_settings.M01y = val; set_custom(); } - void set_m1z(int val) { dialog_settings.M01z = val; set_custom(); } - void set_m2x(int val) { dialog_settings.M02x = val; set_custom(); } - void set_m2y(int val) { dialog_settings.M02y = val; set_custom(); } - void set_m2z(int val) { dialog_settings.M02z = val; set_custom(); } - void set_tx(int val) { settings.t_MH[0] = val; settings_changed(); } - void set_ty(int val) { settings.t_MH[1] = val; settings_changed(); } - void set_tz(int val) { settings.t_MH[2] = val; settings_changed(); } - void set_model(int model_id); - - void doCenter(); - void doReset(); - - void doOK(); - void doCancel(); - - void startstop_trans_calib(bool start); - - void poll_tracker_info(); - -protected: - void set_clip(); - void set_cap(); - void set_custom(); - - void settings_changed(); - - TrackerSettings settings; - TrackerDialogSettings dialog_settings; - bool settings_dirty; - - Tracker* tracker; - TranslationCalibrator trans_calib; - bool trans_calib_running; - QTimer timer; - Ui::UICPTClientControls ui; -}; - -#endif //FTNOIR_TRACKER_PT_DIALOG_H +/* 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 FTNOIR_TRACKER_PT_DIALOG_H
+#define FTNOIR_TRACKER_PT_DIALOG_H
+
+#include "..\ftnoir_tracker_base\ftnoir_tracker_base.h"
+#include "ftnoir_tracker_pt_settings.h"
+#include "ftnoir_tracker_pt.h"
+#include "trans_calib.h"
+#include "video_widget.h"
+#include "ui_FTNoIR_PT_Controls.h"
+
+#include <QTimer>
+
+//-----------------------------------------------------------------------------
+// The dialog that shows up when the user presses "Settings"
+class TrackerDialog : public QWidget, Ui::UICPTClientControls, public ITrackerDialog
+{
+ Q_OBJECT
+public:
+ TrackerDialog();
+ ~TrackerDialog();
+
+ // ITrackerDialog interface
+ void Initialize(QWidget *parent);
+ void registerTracker(ITracker *tracker);
+ void unRegisterTracker();
+
+ void trans_calib_step();
+
+protected slots:
+ // ugly qt stuff
+ void set_video_widget(bool val) { settings.video_widget = val; settings_changed(); }
+ void set_dyn_pose_res(bool val) { settings.dyn_pose_res = val; settings_changed(); }
+ void set_sleep_time(int val) { settings.sleep_time = val; settings_changed(); }
+ void set_reset_time(int val) { settings.reset_time = val; settings_changed(); }
+ void set_cam_index(int idx) { settings.cam_index = idx; settings_changed(); }
+ void set_cam_f(double val) { settings.cam_f = val; settings_changed(); }
+ void set_cam_res_x(int val) { settings.cam_res_x = val; settings_changed(); }
+ void set_cam_res_y(int val) { settings.cam_res_y = val; settings_changed(); }
+ void set_cam_fps(int val) { settings.cam_fps = val; settings_changed(); }
+ void set_cam_roll(int idx);
+ void set_cam_pitch(int val) { settings.cam_pitch = val; settings_changed(); }
+ void set_cam_yaw(int val) { settings.cam_yaw = val; settings_changed(); }
+ void set_min_point_size(int val) { settings.min_point_size = val; settings_changed(); }
+ void set_max_point_size(int val) { settings.max_point_size = val; settings_changed(); }
+ void set_threshold(int val) { settings.threshold = val; settings_changed(); }
+ void set_ena_roll(bool val) { settings.bEnableRoll = val; settings_changed(); }
+ void set_ena_pitch(bool val) { settings.bEnablePitch = val; settings_changed(); }
+ void set_ena_yaw(bool val) { settings.bEnableYaw = val; settings_changed(); }
+ void set_ena_x(bool val) { settings.bEnableX = val; settings_changed(); }
+ void set_ena_y(bool val) { settings.bEnableY = val; settings_changed(); }
+ void set_ena_z(bool val) { settings.bEnableZ = val; settings_changed(); }
+
+ void set_clip_t_height(int val) { dialog_settings.clip_ty = val; set_model_clip(); }
+ void set_clip_t_length(int val) { dialog_settings.clip_tz = val; set_model_clip(); }
+ void set_clip_b_height(int val) { dialog_settings.clip_by = val; set_model_clip(); }
+ void set_clip_b_length(int val) { dialog_settings.clip_bz = val; set_model_clip(); }
+ void set_cap_width(int val) { dialog_settings.cap_x = val; set_model_cap(); }
+ void set_cap_height(int val) { dialog_settings.cap_y = val; set_model_cap(); }
+ void set_cap_length(int val) { dialog_settings.cap_z = val; set_model_cap(); }
+ void set_m1x(int val) { dialog_settings.M01x = val; set_model_custom(); }
+ void set_m1y(int val) { dialog_settings.M01y = val; set_model_custom(); }
+ void set_m1z(int val) { dialog_settings.M01z = val; set_model_custom(); }
+ void set_m2x(int val) { dialog_settings.M02x = val; set_model_custom(); }
+ void set_m2y(int val) { dialog_settings.M02y = val; set_model_custom(); }
+ void set_m2z(int val) { dialog_settings.M02z = val; set_model_custom(); }
+ void set_tx(int val) { settings.t_MH[0] = val; settings_changed(); }
+ void set_ty(int val) { settings.t_MH[1] = val; settings_changed(); }
+ void set_tz(int val) { settings.t_MH[2] = val; settings_changed(); }
+ void set_model(int model_id);
+
+ void doCenter();
+ void doReset();
+
+ void doOK();
+ void doCancel();
+
+ void startstop_trans_calib(bool start);
+
+ void widget_destroyed(QObject* obj);
+
+ void create_video_widget();
+
+ void poll_tracker_info();
+
+protected:
+ void destroy_video_widget(bool do_delete = true);
+
+ void set_model_clip();
+ void set_model_cap();
+ void set_model_custom();
+
+ void settings_changed();
+
+ TrackerSettings settings;
+ TrackerDialogSettings dialog_settings;
+ bool settings_dirty;
+
+ Tracker* tracker;
+ QTimer timer;
+
+ VideoWidgetDialog* video_widget_dialog;
+
+ TranslationCalibrator trans_calib;
+ bool trans_calib_running;
+
+ Ui::UICPTClientControls ui;
+};
+
+#endif //FTNOIR_TRACKER_PT_DIALOG_H
\ No newline at end of file diff --git a/ftnoir_tracker_pt/ftnoir_tracker_pt_dll.cpp b/FTNoIR_Tracker_PT/ftnoir_tracker_pt_dll.cpp index 1c486382..3a73f679 100644 --- a/ftnoir_tracker_pt/ftnoir_tracker_pt_dll.cpp +++ b/FTNoIR_Tracker_PT/ftnoir_tracker_pt_dll.cpp @@ -1,40 +1,40 @@ -/* 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 "ftnoir_tracker_pt_dll.h" -#include <QIcon> -#include "facetracknoir/global-settings.h" - -//----------------------------------------------------------------------------- -void TrackerDll::getFullName(QString *strToBeFilled) -{ - *strToBeFilled = "PointTracker 1.0"; -} - -void TrackerDll::getShortName(QString *strToBeFilled) -{ - *strToBeFilled = "PointTracker"; -} - -void TrackerDll::getDescription(QString *strToBeFilled) -{ - *strToBeFilled = "Tracks a 3-point model with know geometry like Freetrack / TrackIR"; -} - -void TrackerDll::getIcon(QIcon *icon) -{ - *icon = QIcon(":/resources/icon.png"); -} - - -//----------------------------------------------------------------------------- -//#pragma comment(linker, "/export:GetTrackerDll=_GetTrackerDll@0") - -extern "C" FTNOIR_TRACKER_BASE_EXPORT Metadata* CALLING_CONVENTION GetMetadata() -{ - return new TrackerDll; -} +/* 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 "ftnoir_tracker_pt_dll.h"
+
+#include <QIcon>
+
+//-----------------------------------------------------------------------------
+void TrackerDll::getFullName(QString *strToBeFilled)
+{
+ *strToBeFilled = "PointTracker 1.1";
+}
+
+void TrackerDll::getShortName(QString *strToBeFilled)
+{
+ *strToBeFilled = "PointTracker";
+}
+
+void TrackerDll::getDescription(QString *strToBeFilled)
+{
+ *strToBeFilled = "Tracks a 3-point model with know geometry like Freetrack / TrackIR";
+}
+
+void TrackerDll::getIcon(QIcon *icon)
+{
+ *icon = QIcon(":/Resources/icon.ico");
+}
+
+
+//-----------------------------------------------------------------------------
+#pragma comment(linker, "/export:GetTrackerDll=_GetTrackerDll@0")
+
+FTNOIR_TRACKER_BASE_EXPORT ITrackerDllPtr __stdcall GetTrackerDll()
+{
+ return new TrackerDll;
+}
diff --git a/ftnoir_tracker_pt/ftnoir_tracker_pt_dll.h b/FTNoIR_Tracker_PT/ftnoir_tracker_pt_dll.h index 4dc94173..15ad63aa 100644 --- a/ftnoir_tracker_pt/ftnoir_tracker_pt_dll.h +++ b/FTNoIR_Tracker_PT/ftnoir_tracker_pt_dll.h @@ -1,18 +1,19 @@ -/* 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 "ftnoir_tracker_base/ftnoir_tracker_base.h" -#include "facetracknoir/global-settings.h" - -//----------------------------------------------------------------------------- -class TrackerDll : public Metadata -{ - void getFullName(QString *strToBeFilled); - void getShortName(QString *strToBeFilled); - void getDescription(QString *strToBeFilled); - void getIcon(QIcon *icon); -}; +/* 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 "..\ftnoir_tracker_base\ftnoir_tracker_base.h"
+
+//-----------------------------------------------------------------------------
+class TrackerDll : public ITrackerDll
+{
+ // ITrackerDll interface
+ void Initialize() {}
+ void getFullName(QString *strToBeFilled);
+ void getShortName(QString *strToBeFilled);
+ void getDescription(QString *strToBeFilled);
+ void getIcon(QIcon *icon);
+};
\ No newline at end of file diff --git a/ftnoir_tracker_pt/ftnoir_tracker_pt_settings.cpp b/FTNoIR_Tracker_PT/ftnoir_tracker_pt_settings.cpp index 787a5265..13ef49ec 100644 --- a/ftnoir_tracker_pt/ftnoir_tracker_pt_settings.cpp +++ b/FTNoIR_Tracker_PT/ftnoir_tracker_pt_settings.cpp @@ -1,150 +1,154 @@ -/* 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 "ftnoir_tracker_pt.h" -#include <QCoreApplication> -#include <QSettings> - -//----------------------------------------------------------------------------- -void TrackerSettings::load_ini() -{ - qDebug("TrackerSettings::load_ini()"); - - QSettings settings("opentrack"); // Registry settings (in HK_USER) - QString currentFile = settings.value( "SettingsFile", QCoreApplication::applicationDirPath() + "/settings/default.ini" ).toString(); - QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file) - - iniFile.beginGroup( "PointTracker" ); - - cam_index = iniFile.value("CameraId", 0).toInt(); - cam_f = iniFile.value("CameraF", 1).toFloat(); - cam_res_x = iniFile.value("CameraResX", 640).toInt(); - cam_res_y = iniFile.value("CameraResY", 480).toInt(); - cam_fps = iniFile.value("CameraFPS", 30).toInt(); - cam_pitch = iniFile.value("CameraPitch", 0).toInt(); - threshold = iniFile.value("PointExtractThreshold", 128).toInt(); - min_point_size = iniFile.value("PointExtractMinSize", 2).toInt(); - max_point_size = iniFile.value("PointExtractMaxSize", 50).toInt(); - M01[0] = iniFile.value("PointModelM01x", 0).toFloat(); - M01[1] = iniFile.value("PointModelM01y", 40).toFloat(); - M01[2] = iniFile.value("PointModelM01z", -30).toFloat(); - M02[0] = iniFile.value("PointModelM02x", 0).toFloat(); - M02[1] = iniFile.value("PointModelM02y", -70).toFloat(); - M02[2] = iniFile.value("PointModelM02z", -80).toFloat(); - t_MH[0] = iniFile.value("tMHx", 0).toFloat(); - t_MH[1] = iniFile.value("tMHy", 0).toFloat(); - t_MH[2] = iniFile.value("tMHz", 0).toFloat(); - dyn_pose_res = iniFile.value("DynamicPoseResolution", true).toBool(); - video_widget = iniFile.value("VideoWidget", true).toBool(); - sleep_time = iniFile.value("SleepTime", 10).toInt(); - reset_time = iniFile.value("ResetTime", 1000).toInt(); - - bEnableRoll = iniFile.value( "EnableRoll", 1 ).toBool(); - bEnablePitch = iniFile.value( "EnablePitch", 1 ).toBool(); - bEnableYaw = iniFile.value( "EnableYaw", 1 ).toBool(); - bEnableX = iniFile.value( "EnableX", 1 ).toBool(); - bEnableY = iniFile.value( "EnableY", 1 ).toBool(); - bEnableZ = iniFile.value( "EnableZ", 1 ).toBool(); - - iniFile.endGroup(); -} - -void TrackerSettings::save_ini() const -{ - qDebug("TrackerSettings::save_ini()"); - - QSettings settings("opentrack"); // Registry settings (in HK_USER) - QString currentFile = settings.value( "SettingsFile", QCoreApplication::applicationDirPath() + "/settings/default.ini" ).toString(); - QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file) - - iniFile.beginGroup ( "PointTracker" ); - - iniFile.setValue("CameraId", cam_index); - iniFile.setValue("CameraF", cam_f); - iniFile.setValue("CameraResX", cam_res_x); - iniFile.setValue("CameraResY", cam_res_y); - iniFile.setValue("CameraFPS", cam_fps); - iniFile.setValue("CameraPitch", cam_pitch); - iniFile.setValue("PointExtractThreshold", threshold); - iniFile.setValue("PointExtractMinSize", min_point_size); - iniFile.setValue("PointExtractMaxSize", max_point_size); - iniFile.setValue("PointModelM01x", M01[0]); - iniFile.setValue("PointModelM01y", M01[1]); - iniFile.setValue("PointModelM01z", M01[2]); - iniFile.setValue("PointModelM02x", M02[0]); - iniFile.setValue("PointModelM02y", M02[1]); - iniFile.setValue("PointModelM02z", M02[2]); - iniFile.setValue("tMHx", t_MH[0]); - iniFile.setValue("tMHy", t_MH[1]); - iniFile.setValue("tMHz", t_MH[2]); - iniFile.setValue("DynamicPoseResolution", dyn_pose_res); - iniFile.setValue("VideoWidget", video_widget); - iniFile.setValue("SleepTime", sleep_time); - iniFile.setValue("ResetTime", reset_time); - - iniFile.setValue( "EnableRoll", bEnableRoll ); - iniFile.setValue( "EnablePitch", bEnablePitch ); - iniFile.setValue( "EnableYaw", bEnableYaw ); - iniFile.setValue( "EnableX", bEnableX ); - iniFile.setValue( "EnableY", bEnableY ); - iniFile.setValue( "EnableZ", bEnableZ ); - - iniFile.endGroup(); -} - -//----------------------------------------------------------------------------- -void TrackerDialogSettings::load_ini() -{ - qDebug("TrackerDialogSettings::load_ini()"); - - QSettings settings("opentrack"); // Registry settings (in HK_USER) - QString currentFile = settings.value( "SettingsFile", QCoreApplication::applicationDirPath() + "/settings/default.ini" ).toString(); - QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file) - - iniFile.beginGroup( "PointTrackerDialog" ); - - active_model_panel = iniFile.value("ActiveModelPanel", MODEL_CLIP).toInt(); - M01x = iniFile.value("CustomM01x", 0).toInt(); - M01y = iniFile.value("CustomM01y", 40).toInt(); - M01z = iniFile.value("CustomM01z", -30).toInt(); - M02x = iniFile.value("CustomM02x", 0).toInt(); - M02y = iniFile.value("CustomM02y", -70).toInt(); - M02z = iniFile.value("CustomM02z", -80).toInt(); - clip_ty = iniFile.value("ClipTopHeight", 40).toInt(); - clip_tz = iniFile.value("ClipTopLength", 30).toInt(); - clip_by = iniFile.value("ClipBottomHeight", 70).toInt(); - clip_bz = iniFile.value("ClipBottomLength", 80).toInt(); - cap_x = iniFile.value("CapHalfWidth", 40).toInt(); - cap_y = iniFile.value("CapHeight", 60).toInt(); - cap_z = iniFile.value("CapLength", 100).toInt(); -} - -void TrackerDialogSettings::save_ini() const -{ - qDebug("TrackerDialogSettings::save_ini()"); - - QSettings settings("opentrack"); // Registry settings (in HK_USER) - QString currentFile = settings.value( "SettingsFile", QCoreApplication::applicationDirPath() + "/settings/default.ini" ).toString(); - QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file) - - iniFile.beginGroup ( "PointTrackerDialog" ); - - iniFile.setValue("ActiveModelPanel", active_model_panel); - iniFile.setValue("CustomM01x", M01x); - iniFile.setValue("CustomM01y", M01y); - iniFile.setValue("CustomM01z", M01z); - iniFile.setValue("CustomM02x", M02x); - iniFile.setValue("CustomM02y", M02y); - iniFile.setValue("CustomM02z", M02z); - iniFile.setValue("ClipTopHeight", clip_ty); - iniFile.setValue("ClipTopLength", clip_tz); - iniFile.setValue("ClipBottomHeight", clip_by); - iniFile.setValue("ClipBottomLength", clip_bz); - iniFile.setValue("CapHalfWidth", cap_x); - iniFile.setValue("CapHeight", cap_y); - iniFile.setValue("CapLength", cap_z); +/* 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 "ftnoir_tracker_pt.h"
+#include <QCoreApplication>
+#include <QSettings>
+
+//-----------------------------------------------------------------------------
+void TrackerSettings::load_ini()
+{
+ qDebug("TrackerSettings::load_ini()");
+
+ QSettings settings("Abbequerque Inc.", "FaceTrackNoIR"); // Registry settings (in HK_USER)
+ QString currentFile = settings.value( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString();
+ QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file)
+
+ iniFile.beginGroup( "PointTracker" );
+
+ cam_index = iniFile.value("CameraId", 0).toInt();
+ cam_f = iniFile.value("CameraF", 1).toFloat();
+ cam_res_x = iniFile.value("CameraResX", 640).toInt();
+ cam_res_y = iniFile.value("CameraResY", 480).toInt();
+ cam_fps = iniFile.value("CameraFPS", 30).toInt();
+ cam_roll = iniFile.value("CameraRoll", 0).toInt();
+ cam_pitch = iniFile.value("CameraPitch", 0).toInt();
+ cam_yaw = iniFile.value("CameraYaw", 0).toInt();
+ threshold = iniFile.value("PointExtractThreshold", 128).toInt();
+ min_point_size = iniFile.value("PointExtractMinSize", 2).toInt();
+ max_point_size = iniFile.value("PointExtractMaxSize", 50).toInt();
+ M01[0] = iniFile.value("PointModelM01x", 0).toFloat();
+ M01[1] = iniFile.value("PointModelM01y", 40).toFloat();
+ M01[2] = iniFile.value("PointModelM01z", -30).toFloat();
+ M02[0] = iniFile.value("PointModelM02x", 0).toFloat();
+ M02[1] = iniFile.value("PointModelM02y", -70).toFloat();
+ M02[2] = iniFile.value("PointModelM02z", -80).toFloat();
+ t_MH[0] = iniFile.value("tMHx", 0).toFloat();
+ t_MH[1] = iniFile.value("tMHy", 0).toFloat();
+ t_MH[2] = iniFile.value("tMHz", 0).toFloat();
+ dyn_pose_res = iniFile.value("DynamicPoseResolution", true).toBool();
+ video_widget = iniFile.value("VideoWidget", true).toBool();
+ sleep_time = iniFile.value("SleepTime", 10).toInt();
+ reset_time = iniFile.value("ResetTime", 1000).toInt();
+
+ bEnableRoll = iniFile.value("EnableRoll", 1).toBool();
+ bEnablePitch = iniFile.value("EnablePitch", 1).toBool();
+ bEnableYaw = iniFile.value("EnableYaw", 1).toBool();
+ bEnableX = iniFile.value("EnableX", 1).toBool();
+ bEnableY = iniFile.value("EnableY", 1).toBool();
+ bEnableZ = iniFile.value("EnableZ", 1).toBool();
+
+ iniFile.endGroup();
+}
+
+void TrackerSettings::save_ini() const
+{
+ qDebug("TrackerSettings::save_ini()");
+
+ QSettings settings("Abbequerque Inc.", "FaceTrackNoIR"); // Registry settings (in HK_USER)
+ QString currentFile = settings.value( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString();
+ QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file)
+
+ iniFile.beginGroup ( "PointTracker" );
+
+ iniFile.setValue("CameraId", cam_index);
+ iniFile.setValue("CameraF", cam_f);
+ iniFile.setValue("CameraResX", cam_res_x);
+ iniFile.setValue("CameraResY", cam_res_y);
+ iniFile.setValue("CameraFPS", cam_fps);
+ iniFile.setValue("CameraRoll", cam_roll);
+ iniFile.setValue("CameraPitch", cam_pitch);
+ iniFile.setValue("CameraYaw", cam_yaw);
+ iniFile.setValue("PointExtractThreshold", threshold);
+ iniFile.setValue("PointExtractMinSize", min_point_size);
+ iniFile.setValue("PointExtractMaxSize", max_point_size);
+ iniFile.setValue("PointModelM01x", M01[0]);
+ iniFile.setValue("PointModelM01y", M01[1]);
+ iniFile.setValue("PointModelM01z", M01[2]);
+ iniFile.setValue("PointModelM02x", M02[0]);
+ iniFile.setValue("PointModelM02y", M02[1]);
+ iniFile.setValue("PointModelM02z", M02[2]);
+ iniFile.setValue("tMHx", t_MH[0]);
+ iniFile.setValue("tMHy", t_MH[1]);
+ iniFile.setValue("tMHz", t_MH[2]);
+ iniFile.setValue("DynamicPoseResolution", dyn_pose_res);
+ iniFile.setValue("VideoWidget", video_widget);
+ iniFile.setValue("SleepTime", sleep_time);
+ iniFile.setValue("ResetTime", reset_time);
+
+ iniFile.setValue( "EnableRoll", bEnableRoll );
+ iniFile.setValue( "EnablePitch", bEnablePitch );
+ iniFile.setValue( "EnableYaw", bEnableYaw );
+ iniFile.setValue( "EnableX", bEnableX );
+ iniFile.setValue( "EnableY", bEnableY );
+ iniFile.setValue( "EnableZ", bEnableZ );
+
+ iniFile.endGroup();
+}
+
+//-----------------------------------------------------------------------------
+void TrackerDialogSettings::load_ini()
+{
+ qDebug("TrackerDialogSettings::load_ini()");
+
+ QSettings settings("Abbequerque Inc.", "FaceTrackNoIR"); // Registry settings (in HK_USER)
+ QString currentFile = settings.value( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString();
+ QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file)
+
+ iniFile.beginGroup( "PointTrackerDialog" );
+
+ active_model_panel = iniFile.value("ActiveModelPanel", MODEL_CLIP).toInt();
+ M01x = iniFile.value("CustomM01x", 0).toInt();
+ M01y = iniFile.value("CustomM01y", 40).toInt();
+ M01z = iniFile.value("CustomM01z", -30).toInt();
+ M02x = iniFile.value("CustomM02x", 0).toInt();
+ M02y = iniFile.value("CustomM02y", -70).toInt();
+ M02z = iniFile.value("CustomM02z", -80).toInt();
+ clip_ty = iniFile.value("ClipTopHeight", 40).toInt();
+ clip_tz = iniFile.value("ClipTopLength", 30).toInt();
+ clip_by = iniFile.value("ClipBottomHeight", 70).toInt();
+ clip_bz = iniFile.value("ClipBottomLength", 80).toInt();
+ cap_x = iniFile.value("CapHalfWidth", 40).toInt();
+ cap_y = iniFile.value("CapHeight", 60).toInt();
+ cap_z = iniFile.value("CapLength", 100).toInt();
+}
+
+void TrackerDialogSettings::save_ini() const
+{
+ qDebug("TrackerDialogSettings::save_ini()");
+
+ QSettings settings("Abbequerque Inc.", "FaceTrackNoIR"); // Registry settings (in HK_USER)
+ QString currentFile = settings.value( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString();
+ QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file)
+
+ iniFile.beginGroup ( "PointTrackerDialog" );
+
+ iniFile.setValue("ActiveModelPanel", active_model_panel);
+ iniFile.setValue("CustomM01x", M01x);
+ iniFile.setValue("CustomM01y", M01y);
+ iniFile.setValue("CustomM01z", M01z);
+ iniFile.setValue("CustomM02x", M02x);
+ iniFile.setValue("CustomM02y", M02y);
+ iniFile.setValue("CustomM02z", M02z);
+ iniFile.setValue("ClipTopHeight", clip_ty);
+ iniFile.setValue("ClipTopLength", clip_tz);
+ iniFile.setValue("ClipBottomHeight", clip_by);
+ iniFile.setValue("ClipBottomLength", clip_bz);
+ iniFile.setValue("CapHalfWidth", cap_x);
+ iniFile.setValue("CapHeight", cap_y);
+ iniFile.setValue("CapLength", cap_z);
}
\ No newline at end of file diff --git a/ftnoir_tracker_pt/ftnoir_tracker_pt_settings.h b/FTNoIR_Tracker_PT/ftnoir_tracker_pt_settings.h index a1523898..1cf60853 100644 --- a/ftnoir_tracker_pt/ftnoir_tracker_pt_settings.h +++ b/FTNoIR_Tracker_PT/ftnoir_tracker_pt_settings.h @@ -1,84 +1,88 @@ -/* 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 FTNOIR_TRACKER_PT_SETTINGS_H -#define FTNOIR_TRACKER_PT_SETTINGS_H - -#include <opencv2/opencv.hpp> -#include "point_tracker.h" - - -//----------------------------------------------------------------------------- -struct TrackerSettings -{ - // camera - int cam_index; - float cam_f; - int cam_res_x; - int cam_res_y; - int cam_fps; - int cam_pitch; - - // point extraction - int threshold; - int min_point_size; - int max_point_size; - - // point tracking - cv::Vec3f M01; - cv::Vec3f M02; - bool dyn_pose_res; - - // head to model translation - cv::Vec3f t_MH; - - int sleep_time; // in ms - int reset_time; // in ms - bool video_widget; - - bool bEnableRoll; - bool bEnablePitch; - bool bEnableYaw; - bool bEnableX; - bool bEnableY; - bool bEnableZ; - - void load_ini(); - void save_ini() const; -}; - - -//----------------------------------------------------------------------------- -struct TrackerDialogSettings -{ - enum - { - MODEL_CLIP, - MODEL_CAP, - MODEL_CUSTOM - }; - int active_model_panel; - - int M01x; - int M01y; - int M01z; - int M02x; - int M02y; - int M02z; - int clip_ty; - int clip_tz; - int clip_by; - int clip_bz; - int cap_x; - int cap_y; - int cap_z; - - void load_ini(); - void save_ini() const; -}; - +/* 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 FTNOIR_TRACKER_PT_SETTINGS_H
+#define FTNOIR_TRACKER_PT_SETTINGS_H
+
+#include <opencv2/opencv.hpp>
+#include "point_tracker.h"
+
+
+//-----------------------------------------------------------------------------
+// Tracker settings and their ini-IO
+struct TrackerSettings
+{
+ // camera
+ int cam_index;
+ float cam_f;
+ int cam_res_x;
+ int cam_res_y;
+ int cam_fps;
+ int cam_roll;
+ int cam_pitch;
+ int cam_yaw;
+
+ // point extraction
+ int threshold;
+ int min_point_size;
+ int max_point_size;
+
+ // point tracking
+ cv::Vec3f M01;
+ cv::Vec3f M02;
+ bool dyn_pose_res;
+
+ // head to model translation
+ cv::Vec3f t_MH;
+
+ int sleep_time; // in ms
+ int reset_time; // in ms
+ bool video_widget;
+
+ bool bEnableRoll;
+ bool bEnablePitch;
+ bool bEnableYaw;
+ bool bEnableX;
+ bool bEnableY;
+ bool bEnableZ;
+
+ void load_ini();
+ void save_ini() const;
+};
+
+
+//-----------------------------------------------------------------------------
+// Settings specific to the tracker dialog and their ini-IO
+struct TrackerDialogSettings
+{
+ enum
+ {
+ MODEL_CLIP,
+ MODEL_CAP,
+ MODEL_CUSTOM
+ };
+ int active_model_panel;
+
+ int M01x;
+ int M01y;
+ int M01z;
+ int M02x;
+ int M02y;
+ int M02z;
+ int clip_ty;
+ int clip_tz;
+ int clip_by;
+ int clip_bz;
+ int cap_x;
+ int cap_y;
+ int cap_z;
+
+ void load_ini();
+ void save_ini() const;
+};
+
#endif //FTNOIR_TRACKER_PT_SETTINGS_H
\ No newline at end of file diff --git a/ftnoir_tracker_pt/point_extractor.cpp b/FTNoIR_Tracker_PT/point_extractor.cpp index 09be967a..76a152a7 100644 --- a/ftnoir_tracker_pt/point_extractor.cpp +++ b/FTNoIR_Tracker_PT/point_extractor.cpp @@ -1,96 +1,101 @@ -/* 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 "point_extractor.h" -#include <QDebug> - -using namespace cv; -using namespace std; - -// ---------------------------------------------------------------------------- -const vector<Vec2f>& PointExtractor::extract_points(Mat frame, float dt, bool draw_output) -{ - const int W = frame.cols; - const int H = frame.rows; - - // clear old points - points.clear(); - - // convert to grayscale - Mat frame_grey; - cvtColor(frame, frame_grey, COLOR_BGR2GRAY); - - // convert to binary - Mat frame_bin; - threshold(frame_grey, frame_bin, threshold_val, 255, THRESH_BINARY); - - unsigned int region_size_min = 3.14*min_size*min_size; - unsigned int region_size_max = 3.14*max_size*max_size; - - int blob_index = 1; - for (int y=0; y<H; y++) - { - for (int x=0; x<W; x++) - { - // find connected components with floodfill - if (frame_bin.at<unsigned char>(y,x) != 255) continue; - Rect rect; - floodFill(frame_bin, Point(x,y), Scalar(blob_index), &rect, Scalar(0), Scalar(0), FLOODFILL_FIXED_RANGE); - blob_index++; - - // calculate the size of the connected component - unsigned int region_size = 0; - for (int i=rect.y; i < (rect.y+rect.height); i++) - { - for (int j=rect.x; j < (rect.x+rect.width); j++) - { - if (frame_bin.at<unsigned char>(i,j) != blob_index-1) continue; - region_size++; - } - } - - if (region_size < region_size_min || region_size > region_size_max) continue; - - // calculate the center of mass: - // mx = (sum_ij j*f(frame_grey_ij)) / (sum_ij f(frame_grey_ij)) - // my = ... - // f maps from [threshold,256] -> [0, 1], lower values are mapped to 0 - float m = 0; - float mx = 0; - float my = 0; - for (int i=rect.y; i < (rect.y+rect.height); i++) - { - for (int j=rect.x; j < (rect.x+rect.width); j++) - { - if (frame_bin.at<unsigned char>(i,j) != blob_index-1) continue; - float val = frame_grey.at<unsigned char>(i,j); - val = float(val - threshold_val)/(256 - threshold_val); - val = val*val; // makes it more stable (less emphasis on low values, more on the peak) - m += val; - mx += j * val; - my += i * val; - } - } - - // convert to centered camera coordinate system with y axis upwards - Vec2f c; - c[0] = (mx/m - W/2)/W; - c[1] = -(my/m - H/2)/W; - points.push_back(c); - - if (blob_index >= 255) break; - } - if (blob_index >= 255) break; - } - - // draw output image - if (draw_output) { - frame.setTo(Scalar(255,0,0), frame_bin); - } - - return points; -} +/* 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 "point_extractor.h"
+#include <QDebug>
+
+using namespace cv;
+using namespace std;
+
+// ----------------------------------------------------------------------------
+const vector<Vec2f>& PointExtractor::extract_points(Mat frame, float dt, bool draw_output)
+{
+ const int W = frame.cols;
+ const int H = frame.rows;
+
+ // clear old points
+ points.clear();
+
+ // convert to grayscale
+ Mat frame_gray;
+ cvtColor(frame, frame_gray, CV_RGB2GRAY);
+
+ // convert to binary
+ Mat frame_bin;
+ threshold(frame_gray, frame_bin, threshold_val, 255, THRESH_BINARY);
+
+ unsigned int region_size_min = 3.14*min_size*min_size/4.0;
+ unsigned int region_size_max = 3.14*max_size*max_size/4.0;
+
+ int blob_index = 1;
+ for (int y=0; y<H; y++)
+ {
+ if (blob_index >= 255) break;
+ for (int x=0; x<W; x++)
+ {
+ if (blob_index >= 255) break;
+
+ // find connected components with floodfill
+ if (frame_bin.at<unsigned char>(y,x) != 255) continue;
+ Rect rect;
+ floodFill(frame_bin, Point(x,y), Scalar(blob_index), &rect, Scalar(0), Scalar(0), FLOODFILL_FIXED_RANGE);
+ blob_index++;
+
+ // calculate the size of the connected component
+ unsigned int region_size = 0;
+ for (int i=rect.y; i < (rect.y+rect.height); i++)
+ {
+ for (int j=rect.x; j < (rect.x+rect.width); j++)
+ {
+ if (frame_bin.at<unsigned char>(i,j) != blob_index-1) continue;
+ region_size++;
+ }
+ }
+
+ if (region_size < region_size_min || region_size > region_size_max) continue;
+
+ // calculate the center of mass:
+ // mx = (sum_ij j*f(frame_grey_ij)) / (sum_ij f(frame_grey_ij))
+ // my = ...
+ // f maps from [threshold,256] -> [0, 1], lower values are mapped to 0
+ float m = 0;
+ float mx = 0;
+ float my = 0;
+ for (int i=rect.y; i < (rect.y+rect.height); i++)
+ {
+ for (int j=rect.x; j < (rect.x+rect.width); j++)
+ {
+ if (frame_bin.at<unsigned char>(i,j) != blob_index-1) continue;
+ float val = frame_gray.at<unsigned char>(i,j);
+ val = float(val - threshold_val)/(256 - threshold_val);
+ val = val*val; // makes it more stable (less emphasis on low values, more on the peak)
+ m += val;
+ mx += j * val;
+ my += i * val;
+ }
+ }
+
+ // convert to centered camera coordinate system with y axis upwards
+ Vec2f c;
+ c[0] = (mx/m - W/2)/W;
+ c[1] = -(my/m - H/2)/W;
+ points.push_back(c);
+ }
+ }
+
+ // draw output image
+ if (draw_output) {
+ vector<Mat> channels;
+ frame_bin.setTo(170, frame_bin);
+ channels.push_back(frame_gray + frame_bin);
+ channels.push_back(frame_gray - frame_bin);
+ channels.push_back(frame_gray - frame_bin);
+ merge(channels, frame);
+ }
+
+ return points;
+}
diff --git a/ftnoir_tracker_pt/point_extractor.h b/FTNoIR_Tracker_PT/point_extractor.h index 9a6f7f2c..b142d2bb 100644 --- a/ftnoir_tracker_pt/point_extractor.h +++ b/FTNoIR_Tracker_PT/point_extractor.h @@ -1,31 +1,31 @@ -/* 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 POINTEXTRACTOR_H -#define POINTEXTRACTOR_H - -#include <opencv2/opencv.hpp> - -// ---------------------------------------------------------------------------- -// Extracts points from an opencv image -class PointExtractor -{ -public: - // extracts points from frame and draws some processing info into frame, if draw_output is set - // dt: time since last call in seconds - // WARNING: returned reference is valid as long as object - const std::vector<cv::Vec2f>& extract_points(cv::Mat frame, float dt, bool draw_output); - const std::vector<cv::Vec2f>& get_points() { return points; } - - int threshold_val; - int min_size, max_size; - -protected: - std::vector<cv::Vec2f> points; -}; - -#endif //POINTEXTRACTOR_H +/* 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 POINTEXTRACTOR_H
+#define POINTEXTRACTOR_H
+
+#include <opencv2/opencv.hpp>
+
+// ----------------------------------------------------------------------------
+// Extracts points from an opencv image
+class PointExtractor
+{
+public:
+ // extracts points from frame and draws some processing info into frame, if draw_output is set
+ // dt: time since last call in seconds
+ // WARNING: returned reference is valid as long as object
+ const std::vector<cv::Vec2f>& extract_points(cv::Mat frame, float dt, bool draw_output);
+ const std::vector<cv::Vec2f>& get_points() { return points; }
+
+ int threshold_val;
+ int min_size, max_size;
+
+protected:
+ std::vector<cv::Vec2f> points;
+};
+
+#endif //POINTEXTRACTOR_H
diff --git a/ftnoir_tracker_pt/point_tracker.cpp b/FTNoIR_Tracker_PT/point_tracker.cpp index 210ed2eb..acde9154 100644 --- a/ftnoir_tracker_pt/point_tracker.cpp +++ b/FTNoIR_Tracker_PT/point_tracker.cpp @@ -1,352 +1,359 @@ -/* 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 "point_tracker.h" - -#include <vector> -#include <algorithm> -#include <cmath> - -#include <QDebug> - -using namespace cv; -using namespace std; - -const float PI = 3.14159265358979323846f; - -// ---------------------------------------------------------------------------- -static void get_row(const Matx33f& m, int i, Vec3f& v) -{ - v[0] = m(i,0); - v[1] = m(i,1); - v[2] = m(i,2); -} - -static void set_row(Matx33f& m, int i, const Vec3f& v) -{ - m(i,0) = v[0]; - m(i,1) = v[1]; - m(i,2) = v[2]; -} - -// ---------------------------------------------------------------------------- -PointModel::PointModel(Vec3f M01, Vec3f M02) - : M01(M01), M02(M02) -{ - // calculate u - u = M01.cross(M02); - u /= norm(u); - - // calculate projection matrix on M01,M02 plane - float s11 = M01.dot(M01); - float s12 = M01.dot(M02); - float s22 = M02.dot(M02); - P = 1.0/(s11*s22-s12*s12) * Matx22f(s22, -s12, - -s12, s11); - - // calculate d and d_order for simple freetrack-like point correspondence - vector<Vec2f> points; - points.push_back(Vec2f(0,0)); - points.push_back(Vec2f(M01[0], M01[1])); - points.push_back(Vec2f(M02[0], M02[1])); - // fit line to orthographically projected points - // ERROR: yields wrong results with colinear points?! - /* - Vec4f line; - fitLine(points, line, CV_DIST_L2, 0, 0.01, 0.01); - d[0] = line[0]; d[1] = line[1]; - */ - // TODO: fix this - d = Vec2f(M01[0]-M02[0], M01[1]-M02[1]); - - // sort model points - get_d_order(points, d_order); -} - -static bool d_vals_sort(const pair<float,int> a, const pair<float,int> b) -{ - return a.first < b.first; -} - -void PointModel::get_d_order(const std::vector<cv::Vec2f>& points, int d_order[]) const -{ - // get sort indices with respect to d scalar product - vector< pair<float,int> > d_vals; - for (int i = 0; i<(int)points.size(); ++i) - d_vals.push_back(pair<float, int>(d.dot(points[i]), i)); - - sort(d_vals.begin(), d_vals.end(), d_vals_sort); - - for (int i = 0; i<(int)points.size(); ++i) - d_order[i] = d_vals[i].second; -} - - -// ---------------------------------------------------------------------------- -PointTracker::PointTracker() : dynamic_pose_resolution(true), dt_reset(1), init_phase(true), dt_valid(0), v_t(0,0,0), v_r(0,0,0) -{ - X_CM.t[2] = 1000; // default position: 1 m away from cam; -} - -void PointTracker::reset() -{ - // enter init phase and reset velocities - init_phase = true; - dt_valid = 0; - reset_velocities(); -} - -void PointTracker::reset_velocities() -{ - v_t = Vec3f(0,0,0); - v_r = Vec3f(0,0,0); -} - - -bool PointTracker::track(const vector<Vec2f>& points, float f, float dt) -{ - if (!dynamic_pose_resolution) init_phase = true; - - dt_valid += dt; - // if there was no valid tracking result for too long, do a reset - if (dt_valid > dt_reset) - { - //qDebug()<<"dt_valid "<<dt_valid<<" > dt_reset "<<dt_reset; - reset(); - } - - // if there is a pointtracking problem, reset the velocities - if (!point_model.get() || (int) points.size() != PointModel::N_POINTS) - { - //qDebug()<<"Wrong number of points!"; - reset_velocities(); - return false; - } - - X_CM_old = X_CM; // backup old transformation for velocity calculation - - if (!init_phase) - predict(dt_valid); - - // if there is a point correspondence problem something has gone wrong, do a reset - if (!find_correspondences(points, f)) - { - //qDebug()<<"Error in finding point correspondences!"; - X_CM = X_CM_old; // undo prediction - reset(); - return false; - } - - (void) POSIT(f); - //qDebug()<<"Number of POSIT iterations: "<<n_iter; - - if (!init_phase) - update_velocities(dt_valid); - - // we have a valid tracking result, leave init phase and reset time since valid result - init_phase = false; - dt_valid = 0; - return true; -} - -void PointTracker::predict(float dt) -{ - // predict with constant velocity - Matx33f R; - Rodrigues(dt*v_r, R); - X_CM.R = R*X_CM.R; - X_CM.t += dt * v_t; -} - -void PointTracker::update_velocities(float dt) -{ - // update velocities - Rodrigues(X_CM.R*X_CM_old.R.t(), v_r); - v_r /= dt; - v_t = (X_CM.t - X_CM_old.t)/dt; -} - -bool PointTracker::find_correspondences(const vector<Vec2f>& points, float f) -{ - if (init_phase) { - // We do a simple freetrack-like sorting in the init phase... - // sort points - int point_d_order[PointModel::N_POINTS]; - point_model->get_d_order(points, point_d_order); - - // set correspondences - for (int i=0; i<PointModel::N_POINTS; ++i) - { - p[point_model->d_order[i]] = points[point_d_order[i]]; - } - } - else { - // ... otherwise we look at the distance to the projection of the expected model points - // project model points under current pose - p_exp[0] = project(Vec3f(0,0,0), f); - p_exp[1] = project(point_model->M01, f); - p_exp[2] = project(point_model->M02, f); - - // set correspondences by minimum distance to projected model point - bool point_taken[PointModel::N_POINTS]; - for (int i=0; i<PointModel::N_POINTS; ++i) - point_taken[i] = false; - - float min_sdist = 0; - int min_idx = 0; - - for (int i=0; i<PointModel::N_POINTS; ++i) - { - // find closest point to projected model point i - for (int j=0; j<PointModel::N_POINTS; ++j) - { - Vec2f d = p_exp[i]-points[j]; - float sdist = d.dot(d); - if (sdist < min_sdist || j==0) - { - min_idx = j; - min_sdist = sdist; - } - } - // if one point is closest to more than one model point, abort - if (point_taken[min_idx]) return false; - point_taken[min_idx] = true; - p[i] = points[min_idx]; - } - } - return true; -} - - - -int PointTracker::POSIT(float f) -{ - // POSIT algorithm for coplanar points as presented in - // [Denis Oberkampf, Daniel F. DeMenthon, Larry S. Davis: "Iterative Pose Estimation Using Coplanar Feature Points"] - // we use the same notation as in the paper here - - // The expected rotation used for resolving the ambiguity in POSIT: - // In every iteration step the rotation closer to R_expected is taken - Matx33f R_expected; - if (init_phase) - R_expected = Matx33f::eye(); // in the init phase, we want to be close to the default pose = no rotation - else - R_expected = X_CM.R; // later we want to be close to the last (predicted) rotation - - // initial pose = last (predicted) pose - Vec3f k; - get_row(X_CM.R, 2, k); - float Z0 = X_CM.t[2]; - - float old_epsilon_1 = 0; - float old_epsilon_2 = 0; - float epsilon_1 = 1; - float epsilon_2 = 1; - - Vec3f I0, J0; - Vec2f I0_coeff, J0_coeff; - - Vec3f I_1, J_1, I_2, J_2; - Matx33f R_1, R_2; - Matx33f* R_current; - - const int MAX_ITER = 100; - const float EPS_THRESHOLD = 1e-4; - - int i=1; - for (; i<MAX_ITER; ++i) - { - epsilon_1 = k.dot(point_model->M01)/Z0; - epsilon_2 = k.dot(point_model->M02)/Z0; - - // vector of scalar products <I0, M0i> and <J0, M0i> - Vec2f I0_M0i(p[1][0]*(1.0 + epsilon_1) - p[0][0], - p[2][0]*(1.0 + epsilon_2) - p[0][0]); - Vec2f J0_M0i(p[1][1]*(1.0 + epsilon_1) - p[0][1], - p[2][1]*(1.0 + epsilon_2) - p[0][1]); - - // construct projection of I, J onto M0i plane: I0 and J0 - I0_coeff = point_model->P * I0_M0i; - J0_coeff = point_model->P * J0_M0i; - I0 = I0_coeff[0]*point_model->M01 + I0_coeff[1]*point_model->M02; - J0 = J0_coeff[0]*point_model->M01 + J0_coeff[1]*point_model->M02; - - // calculate u component of I, J - float II0 = I0.dot(I0); - float IJ0 = I0.dot(J0); - float JJ0 = J0.dot(J0); - float rho, theta; - if (JJ0 == II0) { - rho = sqrt(abs(2*IJ0)); - theta = -PI/4; - if (IJ0<0) theta *= -1; - } - else { - rho = sqrt(sqrt( (JJ0-II0)*(JJ0-II0) + 4*IJ0*IJ0 )); - theta = atan( -2*IJ0 / (JJ0-II0) ); - if (JJ0 - II0 < 0) theta += PI; - theta /= 2; - } - - // construct the two solutions - I_1 = I0 + rho*cos(theta)*point_model->u; - I_2 = I0 - rho*cos(theta)*point_model->u; - - J_1 = J0 + rho*sin(theta)*point_model->u; - J_2 = J0 - rho*sin(theta)*point_model->u; - - float norm_const = 1.0/norm(I_1); // all have the same norm - - // create rotation matrices - I_1 *= norm_const; J_1 *= norm_const; - I_2 *= norm_const; J_2 *= norm_const; - - set_row(R_1, 0, I_1); - set_row(R_1, 1, J_1); - set_row(R_1, 2, I_1.cross(J_1)); - - set_row(R_2, 0, I_2); - set_row(R_2, 1, J_2); - set_row(R_2, 2, I_2.cross(J_2)); - - // the single translation solution - Z0 = norm_const * f; - - // pick the rotation solution closer to the expected one - // in simple metric d(A,B) = || I - A * B^T || - float R_1_deviation = norm(Matx33f::eye() - R_expected * R_1.t()); - float R_2_deviation = norm(Matx33f::eye() - R_expected * R_2.t()); - - if (R_1_deviation < R_2_deviation) - R_current = &R_1; - else - R_current = &R_2; - - get_row(*R_current, 2, k); - - // check for convergence condition - if (abs(epsilon_1 - old_epsilon_1) + abs(epsilon_2 - old_epsilon_2) < EPS_THRESHOLD) - break; - old_epsilon_1 = epsilon_1; - old_epsilon_2 = epsilon_2; - } - - // apply results - X_CM.R = *R_current; - X_CM.t[0] = p[0][0] * Z0/f; - X_CM.t[1] = p[0][1] * Z0/f; - X_CM.t[2] = Z0; - - return i; - - //Rodrigues(X_CM.R, r); - //qDebug()<<"iter: "<<i; - //qDebug()<<"t: "<<X_CM.t[0]<<' '<<X_CM.t[1]<<' '<<X_CM.t[2]; - //Vec3f r; - // - //qDebug()<<"r: "<<r[0]<<' '<<r[1]<<' '<<r[2]<<'\n'; -} +/* 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 "point_tracker.h"
+
+#include <vector>
+#include <algorithm>
+#include <cmath>
+
+#include <QDebug>
+
+using namespace cv;
+using namespace boost;
+using namespace std;
+
+const float PI = 3.14159265358979323846f;
+
+// ----------------------------------------------------------------------------
+static void get_row(const Matx33f& m, int i, Vec3f& v)
+{
+ v[0] = m(i,0);
+ v[1] = m(i,1);
+ v[2] = m(i,2);
+}
+
+static void set_row(Matx33f& m, int i, const Vec3f& v)
+{
+ m(i,0) = v[0];
+ m(i,1) = v[1];
+ m(i,2) = v[2];
+}
+
+// ----------------------------------------------------------------------------
+PointModel::PointModel(Vec3f M01, Vec3f M02)
+ : M01(M01),
+ M02(M02)
+{
+ // calculate u
+ u = M01.cross(M02);
+ u /= norm(u);
+
+ // calculate projection matrix on M01,M02 plane
+ float s11 = M01.dot(M01);
+ float s12 = M01.dot(M02);
+ float s22 = M02.dot(M02);
+ P = 1.0/(s11*s22-s12*s12) * Matx22f(s22, -s12,
+ -s12, s11);
+
+ // calculate d and d_order for simple freetrack-like point correspondence
+ vector<Vec2f> points;
+ points.push_back(Vec2f(0,0));
+ points.push_back(Vec2f(M01[0], M01[1]));
+ points.push_back(Vec2f(M02[0], M02[1]));
+ // fit line to orthographically projected points
+ // ERROR: yields wrong results with colinear points?!
+ /*
+ Vec4f line;
+ fitLine(points, line, CV_DIST_L2, 0, 0.01, 0.01);
+ d[0] = line[0]; d[1] = line[1];
+ */
+ // TODO: fix this
+ d = Vec2f(M01[0]-M02[0], M01[1]-M02[1]);
+
+ // sort model points
+ get_d_order(points, d_order);
+}
+
+void PointModel::get_d_order(const std::vector<cv::Vec2f>& points, int d_order[]) const
+{
+ // get sort indices with respect to d scalar product
+ vector< pair<float,int> > d_vals;
+ for (int i = 0; i<points.size(); ++i)
+ d_vals.push_back(pair<float, int>(d.dot(points[i]), i));
+
+ struct
+ {
+ bool operator()(const pair<float, int>& a, const pair<float, int>& b) { return a.first < b.first; }
+ } comp;
+ sort(d_vals.begin(), d_vals.end(), comp);
+
+ for (int i = 0; i<points.size(); ++i)
+ d_order[i] = d_vals[i].second;
+}
+
+
+// ----------------------------------------------------------------------------
+PointTracker::PointTracker()
+ : init_phase(true),
+ dt_valid(0),
+ dt_reset(1),
+ v_t(0,0,0),
+ v_r(0,0,0),
+ dynamic_pose_resolution(true)
+{
+ X_CM.t[2] = 1000; // default position: 1 m away from cam;
+}
+
+void PointTracker::reset()
+{
+ // enter init phase and reset velocities
+ init_phase = true;
+ dt_valid = 0;
+ reset_velocities();
+}
+
+void PointTracker::reset_velocities()
+{
+ v_t = Vec3f(0,0,0);
+ v_r = Vec3f(0,0,0);
+}
+
+
+bool PointTracker::track(const vector<Vec2f>& points, float f, float dt)
+{
+ if (!dynamic_pose_resolution) init_phase = true;
+
+ dt_valid += dt;
+ // if there was no valid tracking result for too long, do a reset
+ if (dt_valid > dt_reset)
+ {
+ //qDebug()<<"dt_valid "<<dt_valid<<" > dt_reset "<<dt_reset;
+ reset();
+ }
+
+ // if there is a pointtracking problem, reset the velocities
+ if (!point_model || points.size() != PointModel::N_POINTS)
+ {
+ //qDebug()<<"Wrong number of points!";
+ reset_velocities();
+ return false;
+ }
+
+ X_CM_old = X_CM; // backup old transformation for velocity calculation
+
+ if (!init_phase)
+ predict(dt_valid);
+
+ // if there is a point correspondence problem something has gone wrong, do a reset
+ if (!find_correspondences(points, f))
+ {
+ //qDebug()<<"Error in finding point correspondences!";
+ X_CM = X_CM_old; // undo prediction
+ reset();
+ return false;
+ }
+
+ int n_iter = POSIT(f);
+ //qDebug()<<"Number of POSIT iterations: "<<n_iter;
+
+ if (!init_phase)
+ update_velocities(dt_valid);
+
+ // we have a valid tracking result, leave init phase and reset time since valid result
+ init_phase = false;
+ dt_valid = 0;
+ return true;
+}
+
+void PointTracker::predict(float dt)
+{
+ // predict with constant velocity
+ Matx33f R;
+ Rodrigues(dt*v_r, R);
+ X_CM.R = R*X_CM.R;
+ X_CM.t += dt * v_t;
+}
+
+void PointTracker::update_velocities(float dt)
+{
+ // update velocities
+ Rodrigues(X_CM.R*X_CM_old.R.t(), v_r);
+ v_r /= dt;
+ v_t = (X_CM.t - X_CM_old.t)/dt;
+}
+
+bool PointTracker::find_correspondences(const vector<Vec2f>& points, float f)
+{
+ if (init_phase) {
+ // We do a simple freetrack-like sorting in the init phase...
+ // sort points
+ int point_d_order[PointModel::N_POINTS];
+ point_model->get_d_order(points, point_d_order);
+
+ // set correspondences
+ for (int i=0; i<PointModel::N_POINTS; ++i)
+ {
+ p[point_model->d_order[i]] = points[point_d_order[i]];
+ }
+ }
+ else {
+ // ... otherwise we look at the distance to the projection of the expected model points
+ // project model points under current pose
+ p_exp[0] = project(Vec3f(0,0,0), f);
+ p_exp[1] = project(point_model->M01, f);
+ p_exp[2] = project(point_model->M02, f);
+
+ // set correspondences by minimum distance to projected model point
+ bool point_taken[PointModel::N_POINTS];
+ for (int i=0; i<PointModel::N_POINTS; ++i)
+ point_taken[i] = false;
+
+ float min_sdist = 0;
+ int min_idx = 0;
+
+ for (int i=0; i<PointModel::N_POINTS; ++i)
+ {
+ // find closest point to projected model point i
+ for (int j=0; j<PointModel::N_POINTS; ++j)
+ {
+ Vec2f d = p_exp[i]-points[j];
+ float sdist = d.dot(d);
+ if (sdist < min_sdist || j==0)
+ {
+ min_idx = j;
+ min_sdist = sdist;
+ }
+ }
+ // if one point is closest to more than one model point, abort
+ if (point_taken[min_idx]) return false;
+ point_taken[min_idx] = true;
+ p[i] = points[min_idx];
+ }
+ }
+ return true;
+}
+
+
+
+int PointTracker::POSIT(float f)
+{
+ // POSIT algorithm for coplanar points as presented in
+ // [Denis Oberkampf, Daniel F. DeMenthon, Larry S. Davis: "Iterative Pose Estimation Using Coplanar Feature Points"]
+ // we use the same notation as in the paper here
+
+ // The expected rotation used for resolving the ambiguity in POSIT:
+ // In every iteration step the rotation closer to R_expected is taken
+ Matx33f R_expected;
+ if (init_phase)
+ R_expected = Matx33f::eye(); // in the init phase, we want to be close to the default pose = no rotation
+ else
+ R_expected = X_CM.R; // later we want to be close to the last (predicted) rotation
+
+ // initial pose = last (predicted) pose
+ Vec3f k;
+ get_row(X_CM.R, 2, k);
+ float Z0 = X_CM.t[2];
+
+ float old_epsilon_1 = 0;
+ float old_epsilon_2 = 0;
+ float epsilon_1 = 1;
+ float epsilon_2 = 1;
+
+ Vec3f I0, J0;
+ Vec2f I0_coeff, J0_coeff;
+
+ Vec3f I_1, J_1, I_2, J_2;
+ Matx33f R_1, R_2;
+ Matx33f* R_current;
+
+ const int MAX_ITER = 100;
+ const float EPS_THRESHOLD = 1e-4;
+
+ int i=1;
+ for (; i<MAX_ITER; ++i)
+ {
+ epsilon_1 = k.dot(point_model->M01)/Z0;
+ epsilon_2 = k.dot(point_model->M02)/Z0;
+
+ // vector of scalar products <I0, M0i> and <J0, M0i>
+ Vec2f I0_M0i(p[1][0]*(1.0 + epsilon_1) - p[0][0],
+ p[2][0]*(1.0 + epsilon_2) - p[0][0]);
+ Vec2f J0_M0i(p[1][1]*(1.0 + epsilon_1) - p[0][1],
+ p[2][1]*(1.0 + epsilon_2) - p[0][1]);
+
+ // construct projection of I, J onto M0i plane: I0 and J0
+ I0_coeff = point_model->P * I0_M0i;
+ J0_coeff = point_model->P * J0_M0i;
+ I0 = I0_coeff[0]*point_model->M01 + I0_coeff[1]*point_model->M02;
+ J0 = J0_coeff[0]*point_model->M01 + J0_coeff[1]*point_model->M02;
+
+ // calculate u component of I, J
+ float II0 = I0.dot(I0);
+ float IJ0 = I0.dot(J0);
+ float JJ0 = J0.dot(J0);
+ float rho, theta;
+ if (JJ0 == II0) {
+ rho = sqrt(abs(2*IJ0));
+ theta = -PI/4;
+ if (IJ0<0) theta *= -1;
+ }
+ else {
+ rho = sqrt(sqrt( (JJ0-II0)*(JJ0-II0) + 4*IJ0*IJ0 ));
+ theta = atan( -2*IJ0 / (JJ0-II0) );
+ if (JJ0 - II0 < 0) theta += PI;
+ theta /= 2;
+ }
+
+ // construct the two solutions
+ I_1 = I0 + rho*cos(theta)*point_model->u;
+ I_2 = I0 - rho*cos(theta)*point_model->u;
+
+ J_1 = J0 + rho*sin(theta)*point_model->u;
+ J_2 = J0 - rho*sin(theta)*point_model->u;
+
+ float norm_const = 1.0/norm(I_1); // all have the same norm
+
+ // create rotation matrices
+ I_1 *= norm_const; J_1 *= norm_const;
+ I_2 *= norm_const; J_2 *= norm_const;
+
+ set_row(R_1, 0, I_1);
+ set_row(R_1, 1, J_1);
+ set_row(R_1, 2, I_1.cross(J_1));
+
+ set_row(R_2, 0, I_2);
+ set_row(R_2, 1, J_2);
+ set_row(R_2, 2, I_2.cross(J_2));
+
+ // the single translation solution
+ Z0 = norm_const * f;
+
+ // pick the rotation solution closer to the expected one
+ // in simple metric d(A,B) = || I - A * B^T ||
+ float R_1_deviation = norm(Matx33f::eye() - R_expected * R_1.t());
+ float R_2_deviation = norm(Matx33f::eye() - R_expected * R_2.t());
+
+ if (R_1_deviation < R_2_deviation)
+ R_current = &R_1;
+ else
+ R_current = &R_2;
+
+ get_row(*R_current, 2, k);
+
+ // check for convergence condition
+ if (abs(epsilon_1 - old_epsilon_1) + abs(epsilon_2 - old_epsilon_2) < EPS_THRESHOLD)
+ break;
+ old_epsilon_1 = epsilon_1;
+ old_epsilon_2 = epsilon_2;
+ }
+
+ // apply results
+ X_CM.R = *R_current;
+ X_CM.t[0] = p[0][0] * Z0/f;
+ X_CM.t[1] = p[0][1] * Z0/f;
+ X_CM.t[2] = Z0;
+
+ return i;
+
+ //Rodrigues(X_CM.R, r);
+ //qDebug()<<"iter: "<<i;
+ //qDebug()<<"t: "<<X_CM.t[0]<<' '<<X_CM.t[1]<<' '<<X_CM.t[2];
+ //Vec3f r;
+ //
+ //qDebug()<<"r: "<<r[0]<<' '<<r[1]<<' '<<r[2]<<'\n';
+}
diff --git a/ftnoir_tracker_pt/point_tracker.h b/FTNoIR_Tracker_PT/point_tracker.h index 8967f806..f52e9dd7 100644 --- a/ftnoir_tracker_pt/point_tracker.h +++ b/FTNoIR_Tracker_PT/point_tracker.h @@ -1,114 +1,125 @@ -/* 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 POINTTRACKER_H -#define POINTTRACKER_H - -#include <memory> -#include <opencv2/opencv.hpp> -#include <list> - -// ---------------------------------------------------------------------------- -// Afine frame trafo -class FrameTrafo -{ -public: - FrameTrafo() : R(cv::Matx33f::eye()), t(0,0,0) {} - FrameTrafo(const cv::Matx33f& R, const cv::Vec3f& t) : R(R),t(t) {} - - cv::Matx33f R; - cv::Vec3f t; -}; - -inline FrameTrafo operator*(const FrameTrafo& X, const FrameTrafo& Y) -{ - return FrameTrafo(X.R*Y.R, X.R*Y.t + X.t); -} - -inline cv::Vec3f operator*(const FrameTrafo& X, const cv::Vec3f& v) -{ - return X.R*v + X.t; -} - -// ---------------------------------------------------------------------------- -// Describes a 3-point model -// nomenclature as in -// [Denis Oberkampf, Daniel F. DeMenthon, Larry S. Davis: "Iterative Pose Estimation Using Coplanar Feature Points"] -class PointModel -{ - friend class PointTracker; -public: - static const int N_POINTS = 3; - - PointModel(cv::Vec3f M01, cv::Vec3f M02); - - const cv::Vec3f& get_M01() const { return M01; }; - const cv::Vec3f& get_M02() const { return M02; }; - -protected: - cv::Vec3f M01; // M01 in model frame - cv::Vec3f M02; // M02 in model frame - - cv::Vec3f u; // unit vector perpendicular to M01,M02-plane - - cv::Matx22f P; - - cv::Vec2f d; // discrimant vector for point correspondence - int d_order[3]; // sorting of projected model points with respect to d scalar product - - void get_d_order(const std::vector<cv::Vec2f>& points, int d_order[]) const; -}; - -// ---------------------------------------------------------------------------- -// Tracks a 3-point model -// implementing the POSIT algorithm for coplanar points as presented in -// [Denis Oberkampf, Daniel F. DeMenthon, Larry S. Davis: "Iterative Pose Estimation Using Coplanar Feature Points"] -class PointTracker -{ -public: - PointTracker(); - - // track the pose using the set of normalized point coordinates (x pos in range -0.5:0.5) - // f : (focal length)/(sensor width) - // dt : time since last call - bool track(const std::vector<cv::Vec2f>& points, float f, float dt); - std::auto_ptr<PointModel> point_model; - - bool dynamic_pose_resolution; - float dt_reset; - - FrameTrafo get_pose() const { return X_CM; } - void reset(); - -protected: - inline cv::Vec2f project(const cv::Vec3f& v_M, float f) - { - cv::Vec3f v_C = X_CM * v_M; - return cv::Vec2f(f*v_C[0]/v_C[2], f*v_C[1]/v_C[2]); - } - - bool find_correspondences(const std::vector<cv::Vec2f>& points, float f); - - cv::Vec2f p[PointModel::N_POINTS]; // the points in model order - cv::Vec2f p_exp[PointModel::N_POINTS]; // the expected point positions - - void predict(float dt); - void update_velocities(float dt); - void reset_velocities(); - - - int POSIT(float f); // The POSIT algorithm, returns the number of iterations - - bool init_phase; - float dt_valid; // time since last valid tracking result - cv::Vec3f v_t; // velocities - cv::Vec3f v_r; - FrameTrafo X_CM; // trafo from model to camera - FrameTrafo X_CM_old; -}; - -#endif //POINTTRACKER_H +/* 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 POINTTRACKER_H
+#define POINTTRACKER_H
+
+#include <opencv2/opencv.hpp>
+#include <boost/shared_ptr.hpp>
+#include <list>
+
+// ----------------------------------------------------------------------------
+// Affine frame trafo
+class FrameTrafo
+{
+public:
+ FrameTrafo() : R(cv::Matx33f::eye()), t(0,0,0) {}
+ FrameTrafo(const cv::Matx33f& R, const cv::Vec3f& t) : R(R),t(t) {}
+
+ cv::Matx33f R;
+ cv::Vec3f t;
+};
+
+inline FrameTrafo operator*(const FrameTrafo& X, const FrameTrafo& Y)
+{
+ return FrameTrafo(X.R*Y.R, X.R*Y.t + X.t);
+}
+
+inline FrameTrafo operator*(const cv::Matx33f& X, const FrameTrafo& Y)
+{
+ return FrameTrafo(X*Y.R, X*Y.t);
+}
+
+inline FrameTrafo operator*(const FrameTrafo& X, const cv::Matx33f& Y)
+{
+ return FrameTrafo(X.R*Y, X.t);
+}
+
+inline cv::Vec3f operator*(const FrameTrafo& X, const cv::Vec3f& v)
+{
+ return X.R*v + X.t;
+}
+
+
+// ----------------------------------------------------------------------------
+// Describes a 3-point model
+// nomenclature as in
+// [Denis Oberkampf, Daniel F. DeMenthon, Larry S. Davis: "Iterative Pose Estimation Using Coplanar Feature Points"]
+class PointModel
+{
+ friend class PointTracker;
+public:
+ static const int N_POINTS = 3;
+
+ PointModel(cv::Vec3f M01, cv::Vec3f M02);
+
+ const cv::Vec3f& get_M01() const { return M01; };
+ const cv::Vec3f& get_M02() const { return M02; };
+
+protected:
+ cv::Vec3f M01; // M01 in model frame
+ cv::Vec3f M02; // M02 in model frame
+
+ cv::Vec3f u; // unit vector perpendicular to M01,M02-plane
+
+ cv::Matx22f P;
+
+ cv::Vec2f d; // discriminant vector for point correspondence
+ int d_order[3]; // sorting of projected model points with respect to d scalar product
+
+ void get_d_order(const std::vector<cv::Vec2f>& points, int d_order[]) const;
+};
+
+// ----------------------------------------------------------------------------
+// Tracks a 3-point model
+// implementing the POSIT algorithm for coplanar points as presented in
+// [Denis Oberkampf, Daniel F. DeMenthon, Larry S. Davis: "Iterative Pose Estimation Using Coplanar Feature Points"]
+class PointTracker
+{
+public:
+ PointTracker();
+
+ // track the pose using the set of normalized point coordinates (x pos in range -0.5:0.5)
+ // f : (focal length)/(sensor width)
+ // dt : time since last call
+ bool track(const std::vector<cv::Vec2f>& points, float f, float dt);
+ boost::shared_ptr<PointModel> point_model;
+
+ bool dynamic_pose_resolution;
+ float dt_reset;
+
+ FrameTrafo get_pose() const { return X_CM; }
+ void reset();
+
+protected:
+ inline cv::Vec2f project(const cv::Vec3f& v_M, float f)
+ {
+ cv::Vec3f v_C = X_CM * v_M;
+ return cv::Vec2f(f*v_C[0]/v_C[2], f*v_C[1]/v_C[2]);
+ }
+
+ bool find_correspondences(const std::vector<cv::Vec2f>& points, float f);
+
+ cv::Vec2f p[PointModel::N_POINTS]; // the points in model order
+ cv::Vec2f p_exp[PointModel::N_POINTS]; // the expected point positions
+
+ void predict(float dt);
+ void update_velocities(float dt);
+ void reset_velocities();
+
+
+ int POSIT(float f); // The POSIT algorithm, returns the number of iterations
+
+ bool init_phase;
+ float dt_valid; // time since last valid tracking result
+ cv::Vec3f v_t; // velocities
+ cv::Vec3f v_r;
+ FrameTrafo X_CM; // trafo from model to camera
+ FrameTrafo X_CM_old;
+};
+
+#endif //POINTTRACKER_H
diff --git a/ftnoir_tracker_pt/resource.h b/FTNoIR_Tracker_PT/resource.h index 4ca527a3..c14e94ad 100644 --- a/ftnoir_tracker_pt/resource.h +++ b/FTNoIR_Tracker_PT/resource.h @@ -1,14 +1,14 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Visual C++ generated include file. -// Used by FTNoIR_Tracker_PT.rc - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 101 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1001 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif +//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by FTNoIR_Tracker_PT.rc
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 101
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1001
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/ftnoir_tracker_pt/timer.cpp b/FTNoIR_Tracker_PT/timer.cpp index 07379853..363b5b09 100644 --- a/ftnoir_tracker_pt/timer.cpp +++ b/FTNoIR_Tracker_PT/timer.cpp @@ -1,65 +1,66 @@ -/* 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 "timer.h" - -#include <stdlib.h> - -// ---------------------------------------------------------------------------- -Timer::Timer() -: startTime(0), endTime(0), running(false) -{ -#ifdef WIN32 - QueryPerformanceFrequency(&frequency); - startCount.QuadPart = 0; - endCount.QuadPart = 0; -#else - startCount.tv_sec = startCount.tv_usec = 0; - endCount.tv_sec = endCount.tv_usec = 0; -#endif -} - - -void Timer::start() -{ -#ifdef WIN32 - QueryPerformanceCounter(&startCount); -#else - gettimeofday(&startCount, NULL); -#endif - running = true; -} - - -void Timer::stop() -{ -#ifdef WIN32 - QueryPerformanceCounter(&endCount); -#else - gettimeofday(&endCount, NULL); -#endif - running = false; -} - - -double Timer::elapsed() -{ -#ifdef WIN32 - if (running) - QueryPerformanceCounter(&endCount); - - startTime = startCount.QuadPart * (1e3 / frequency.QuadPart); - endTime = endCount.QuadPart * (1e3 / frequency.QuadPart); -#else - (void) gettimeofday(&endCount, NULL); - - startTime = (startCount.tv_sec * 1e3) + startCount.tv_usec; - endTime = (endCount.tv_sec * 1e3) + endCount.tv_usec; -#endif - - return endTime - startTime; +/* 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 "timer.h"
+
+#include <stdlib.h>
+
+// ----------------------------------------------------------------------------
+Timer::Timer()
+: startTime(0), endTime(0), running(false)
+{
+#ifdef WIN32
+ QueryPerformanceFrequency(&frequency);
+ startCount.QuadPart = 0;
+ endCount.QuadPart = 0;
+#else
+ startCount.tv_sec = startCount.tv_usec = 0;
+ endCount.tv_sec = endCount.tv_usec = 0;
+#endif
+}
+
+
+void Timer::start()
+{
+#ifdef WIN32
+ QueryPerformanceCounter(&startCount);
+#else
+ gettimeofday(&startCount, NULL);
+#endif
+ running = true;
+}
+
+
+void Timer::stop()
+{
+#ifdef WIN32
+ QueryPerformanceCounter(&endCount);
+#else
+ gettimeofday(&endCount, NULL);
+#endif
+ running = false;
+}
+
+
+double Timer::elapsed()
+{
+#ifdef WIN32
+ if (running)
+ QueryPerformanceCounter(&endCount);
+
+ startTime = startCount.QuadPart * (1e3 / frequency.QuadPart);
+ endTime = endCount.QuadPart * (1e3 / frequency.QuadPart);
+#else
+ if(!stopped)
+ gettimeofday(&endCount, NULL);
+
+ startTime = (startCount.tv_sec * 1e3) + startCount.tv_usec;
+ endTime = (endCount.tv_sec * 1e3) + endCount.tv_usec;
+#endif
+
+ return endTime - startTime;
}
\ No newline at end of file diff --git a/ftnoir_tracker_pt/timer.h b/FTNoIR_Tracker_PT/timer.h index 1c2c3559..f189e23c 100644 --- a/ftnoir_tracker_pt/timer.h +++ b/FTNoIR_Tracker_PT/timer.h @@ -1,44 +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. - */ - -#ifndef PT_TIMER_H -#define PT_TIMER_H - -#ifdef WIN32 // Windows system specific -#include <windows.h> -#else // Unix based system specific -#include <sys/time.h> -#endif - -// ---------------------------------------------------------------------------- -// high resolution timer based on http://www.songho.ca/misc/timer/timer.html -class Timer -{ -public: - Timer(); - - void start(); - void stop(); - void restart() { start(); } // for Qt compatibility - double elapsed(); // get elapsed time in ms - -protected: - double startTime; // starting time in ms - double endTime; // ending time in ms - bool running; - -#ifdef WIN32 - LARGE_INTEGER frequency; // ticks per second - LARGE_INTEGER startCount; - LARGE_INTEGER endCount; -#else - timeval startCount; - timeval endCount; -#endif -}; - +/* 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 PT_TIMER_H
+#define PT_TIMER_H
+
+#ifdef WIN32 // Windows system specific
+#include <windows.h>
+#else // Unix based system specific
+#include <sys/time.h>
+#endif
+
+// ----------------------------------------------------------------------------
+// High resolution timer based on http://www.songho.ca/misc/timer/timer.html
+class Timer
+{
+public:
+ Timer();
+
+ void start();
+ void stop();
+ void restart() { start(); } // for Qt compatibility
+ double elapsed(); // get elapsed time in ms
+
+protected:
+ double startTime; // starting time in ms
+ double endTime; // ending time in ms
+ bool running;
+
+#ifdef WIN32
+ LARGE_INTEGER frequency; // ticks per second
+ LARGE_INTEGER startCount;
+ LARGE_INTEGER endCount;
+#else
+ timeval startCount;
+ timeval endCount;
+#endif
+};
+
#endif //PT_TIMER_H
\ No newline at end of file diff --git a/ftnoir_tracker_pt/trans_calib.cpp b/FTNoIR_Tracker_PT/trans_calib.cpp index 729a0b7f..9b75a1b6 100644 --- a/ftnoir_tracker_pt/trans_calib.cpp +++ b/FTNoIR_Tracker_PT/trans_calib.cpp @@ -1,44 +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 "trans_calib.h" - -using namespace cv; - -//----------------------------------------------------------------------------- -TranslationCalibrator::TranslationCalibrator() -{ - reset(); -} - -void TranslationCalibrator::reset() -{ - P = Matx66f::zeros(); - y = Vec6f(0,0,0, 0,0,0); -} - -void TranslationCalibrator::update(const Matx33f& R_CM_k, const Vec3f& t_CM_k) -{ - Matx<float, 6,3> H_k_T = Matx<float, 6,3>::zeros(); - for (int i=0; i<3; ++i) { - for (int j=0; j<3; ++j) { - H_k_T(i,j) = R_CM_k(j,i); - } - } - for (int i=0; i<3; ++i) - { - H_k_T(3+i,i) = 1.0; - } - P += H_k_T * H_k_T.t(); - y += H_k_T * t_CM_k; -} - -Vec3f TranslationCalibrator::get_estimate() -{ - Vec6f x = P.inv() * y; - return Vec3f(-x[0], -x[1], -x[2]); +/* 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 "trans_calib.h"
+
+using namespace cv;
+
+//-----------------------------------------------------------------------------
+TranslationCalibrator::TranslationCalibrator()
+{
+ reset();
+}
+
+void TranslationCalibrator::reset()
+{
+ P = Matx66f::zeros();
+ y = Vec6f(0,0,0, 0,0,0);
+}
+
+void TranslationCalibrator::update(const Matx33f& R_CM_k, const Vec3f& t_CM_k)
+{
+ Matx<float, 6,3> H_k_T = Matx<float, 6,3>::zeros();
+ for (int i=0; i<3; ++i) {
+ for (int j=0; j<3; ++j) {
+ H_k_T(i,j) = R_CM_k(j,i);
+ }
+ }
+ for (int i=0; i<3; ++i)
+ {
+ H_k_T(3+i,i) = 1.0;
+ }
+ P += H_k_T * H_k_T.t();
+ y += H_k_T * t_CM_k;
+}
+
+Vec3f TranslationCalibrator::get_estimate()
+{
+ Vec6f x = P.inv() * y;
+ return Vec3f(-x[0], -x[1], -x[2]);
}
\ No newline at end of file diff --git a/ftnoir_tracker_pt/trans_calib.h b/FTNoIR_Tracker_PT/trans_calib.h index 6288546a..f2521690 100644 --- a/ftnoir_tracker_pt/trans_calib.h +++ b/FTNoIR_Tracker_PT/trans_calib.h @@ -1,39 +1,39 @@ -/* 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 TRANSCALIB_H -#define TRANSCALIB_H - -#include <opencv2/opencv.hpp> - -//----------------------------------------------------------------------------- -// calibrates the translation from head to model = t_MH -// by recursive least squares / -// kalman filter in information form with identity noise covariance -// measurement equation when head position = t_CH is fixed: -// (R_CM_k , Id)*(-t_MH, t_CH) = t_CM_k - -class TranslationCalibrator -{ -public: - TranslationCalibrator(); - - // reset the calibration process - void reset(); - - // update the current estimate - void update(const cv::Matx33f& R_CM_k, const cv::Vec3f& t_CM_k); - - // get the current estimate for t_MH - cv::Vec3f get_estimate(); - -protected: - cv::Matx66f P; // normalized precision matrix = inverse covariance - cv::Vec6f y; // P*(-t_MH, t_CH) -}; - +/* 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 TRANSCALIB_H
+#define TRANSCALIB_H
+
+#include <opencv2/opencv.hpp>
+
+//-----------------------------------------------------------------------------
+// Calibrates the translation from head to model = t_MH
+// by recursive least squares /
+// kalman filter in information form with identity noise covariance
+// measurement equation when head position = t_CH is fixed:
+// (R_CM_k , Id)*(-t_MH, t_CH) = t_CM_k
+
+class TranslationCalibrator
+{
+public:
+ TranslationCalibrator();
+
+ // reset the calibration process
+ void reset();
+
+ // update the current estimate
+ void update(const cv::Matx33f& R_CM_k, const cv::Vec3f& t_CM_k);
+
+ // get the current estimate for t_MH
+ cv::Vec3f get_estimate();
+
+protected:
+ cv::Matx66f P; // normalized precision matrix = inverse covariance
+ cv::Vec6f y; // P*(-t_MH, t_CH)
+};
+
#endif //TRANSCALIB_H
\ No newline at end of file diff --git a/FTNoIR_Tracker_PT/video_widget.cpp b/FTNoIR_Tracker_PT/video_widget.cpp new file mode 100644 index 00000000..236faaf7 --- /dev/null +++ b/FTNoIR_Tracker_PT/video_widget.cpp @@ -0,0 +1,119 @@ +/* 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.
+ *
+ * 20130312, WVR: Add 7 lines to resizeGL after resize_frame. This should lower CPU-load.
+ */
+
+#include "video_widget.h"
+
+#include <QDebug>
+#include <QHBoxLayout>
+
+using namespace cv;
+using namespace std;
+using namespace boost;
+
+// ----------------------------------------------------------------------------
+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();
+ glDisable(GL_DEPTH_TEST);
+ glBegin(GL_QUADS);
+ glVertex2f(0,0);
+ glVertex2f(1,0);
+ glVertex2f(1,1);
+ glVertex2f(0,1);
+ glEnd();
+}
+
+void VideoWidget::paintGL()
+{
+ glClear(GL_COLOR_BUFFER_BIT);
+ if (!resized_qframe.isNull())
+ {
+ glDrawPixels(resized_qframe.width(), resized_qframe.height(), GL_RGBA, GL_UNSIGNED_BYTE, resized_qframe.bits());
+
+ const int crosshair_radius = 10;
+ const int crosshair_thickness = 1;
+
+ if (points)
+ {
+ glColor3f(1.0, 0.0, 0.0);
+ glLineWidth(crosshair_thickness);
+ int x,y;
+ for (vector<Vec2f>::iterator iter = points->begin();
+ iter != points->end();
+ ++iter)
+ {
+ x = (*iter)[0] * resized_qframe.width() + resized_qframe.width()/2.0 + 0.5;
+ y = (*iter)[1] * resized_qframe.width() + resized_qframe.height()/2.0 + 0.5;
+
+ glBegin(GL_LINES);
+ glVertex2i(x-crosshair_radius, y);
+ glVertex2i(x+crosshair_radius, y);
+ glEnd();
+ glBegin(GL_LINES);
+ glVertex2i(x, y-crosshair_radius);
+ glVertex2i(x, y+crosshair_radius);
+ glEnd();
+ }
+ }
+ }
+ glFlush();
+}
+
+
+void VideoWidget::resize_frame()
+{
+ if (!qframe.isNull())
+ resized_qframe = qframe.scaled(this->size(), Qt::KeepAspectRatio);
+}
+
+
+void VideoWidget::update_frame_and_points()
+{
+ if (!get_frame_and_points(frame, points)) return;
+
+ // convert to QImage
+ if (frame.channels() == 3)
+ qframe = QImage((const unsigned char*)(frame.data), frame.cols, frame.rows, frame.step, QImage::Format_RGB888).rgbSwapped();
+ else if (frame.channels() == 1)
+ qframe = QImage((const unsigned char*)(frame.data), frame.cols, frame.rows, frame.step, QImage::Format_Indexed8);
+ qframe = QGLWidget::convertToGLFormat(qframe);
+
+ resize_frame();
+ updateGL();
+}
+
+// ----------------------------------------------------------------------------
+VideoWidgetDialog::VideoWidgetDialog(QWidget *parent, FrameProvider* provider)
+ : QDialog(parent),
+ video_widget(NULL)
+{
+ const int VIDEO_FRAME_WIDTH = 640;
+ const int VIDEO_FRAME_HEIGHT = 480;
+
+ video_widget = new VideoWidget(this, provider);
+
+ QHBoxLayout* layout = new QHBoxLayout();
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->addWidget(video_widget);
+ if (this->layout()) delete this->layout();
+ setLayout(layout);
+ resize(VIDEO_FRAME_WIDTH, VIDEO_FRAME_HEIGHT);
+}
\ No newline at end of file diff --git a/FTNoIR_Tracker_PT/video_widget.h b/FTNoIR_Tracker_PT/video_widget.h new file mode 100644 index 00000000..dd5fb642 --- /dev/null +++ b/FTNoIR_Tracker_PT/video_widget.h @@ -0,0 +1,58 @@ +/* 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 "frame_observer.h"
+
+#include <QGLWidget>
+#include <QTime>
+#include <QDialog>
+#include <opencv2/opencv.hpp>
+#include <boost/shared_ptr.hpp>
+
+// ----------------------------------------------------------------------------
+// OpenGL based widget to display an OpenCV image with some points on top
+class VideoWidget : public QGLWidget, public FrameObserver
+{
+ Q_OBJECT
+
+public:
+ VideoWidget(QWidget *parent, FrameProvider* provider) : QGLWidget(parent), FrameObserver(provider) {}
+
+ virtual void initializeGL();
+ virtual void resizeGL(int w, int h);
+ virtual void paintGL();
+
+ void update_frame_and_points();
+
+private:
+ void resize_frame();
+
+ cv::Mat frame;
+ QImage qframe;
+ QImage resized_qframe;
+
+ boost::shared_ptr< std::vector<cv::Vec2f> > points;
+};
+
+// ----------------------------------------------------------------------------
+// A VideoWidget embedded in a dialog frame
+class VideoWidgetDialog : public QDialog
+{
+public:
+ VideoWidgetDialog(QWidget *parent, FrameProvider* provider);
+ virtual ~VideoWidgetDialog() {}
+
+ VideoWidget* get_video_widget() { return video_widget; }
+
+private:
+ VideoWidget* video_widget;
+};
+
+#endif // VIDEOWIDGET_H
diff --git a/ftnoir_protocol_fg/ftnoir_protocol_fg.cpp.autosave b/ftnoir_protocol_fg/ftnoir_protocol_fg.cpp.autosave new file mode 100644 index 00000000..0b67b0d2 --- /dev/null +++ b/ftnoir_protocol_fg/ftnoir_protocol_fg.cpp.autosave @@ -0,0 +1,222 @@ +/******************************************************************************** +* FaceTrackNoIR This program is a private project of the some enthusiastic * +* gamers from Holland, who don't like to pay much for * +* head-tracking. * +* * +* Copyright (C) 2010 Wim Vriend (Developing) * +* Ron Hendriks (Researching and Testing) * +* * +* Homepage * +* * +* This program is free software; you can redistribute it and/or modify it * +* under the terms of the GNU General Public License as published by the * +* Free Software Foundation; either version 3 of the License, or (at your * +* option) any later version. * +* * +* This program is distributed in the hope that it will be useful, but * +* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * +* more details. * +* * +* You should have received a copy of the GNU General Public License along * +* with this program; if not, see <http://www.gnu.org/licenses/>. * +* * +* FGServer FGServer is the Class, that communicates headpose-data * +* to FlightGear, using UDP. * +* It is based on the (Linux) example made by Melchior FRANZ. * +********************************************************************************/ +#include "ftnoir_protocol_fg.h" +#include <QFile> +#include "facetracknoir/global-settings.h" +#include <ftnoir_tracker_base/ftnoir_tracker_types.h> + +// For Todd and Arda Kutlu +//#define SEND_ASCII_DATA +//#define LOG_OUTPUT + +/** constructor **/ +FTNoIR_Protocol::FTNoIR_Protocol() +{ + blnConnectionActive = false; + loadSettings(); +} + +/** destructor **/ +FTNoIR_Protocol::~FTNoIR_Protocol() +{ + if (inSocket != 0) { + inSocket->close(); + delete inSocket; + } + + if (outSocket != 0) { + outSocket->close(); + delete outSocket; + } +} + +// +// Load the current Settings from the currently 'active' INI-file. +// +void FTNoIR_Protocol::loadSettings() { + QSettings settings("opentrack"); // Registry settings (in HK_USER) + + QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/settings/default.ini" ).toString(); + QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file) + + iniFile.beginGroup ( "FG" ); + + bool blnLocalPC = iniFile.value ( "LocalPCOnly", 1 ).toBool(); + if (blnLocalPC) { + destIP = QHostAddress::LocalHost; + } + else { + QString destAddr = iniFile.value ( "IP-1", 192 ).toString() + "." + iniFile.value ( "IP-2", 168 ).toString() + "." + iniFile.value ( "IP-3", 2 ).toString() + "." + iniFile.value ( "IP-4", 1 ).toString(); + destIP = QHostAddress( destAddr ); + } + destPort = iniFile.value ( "PortNumber", 5550 ).toInt(); + + iniFile.endGroup (); + +} + +// +// Update Headpose in Game. +// +void FTNoIR_Protocol::sendHeadposeToGame( double *headpose, double *rawheadpose ) { +int no_bytes; +QHostAddress sender; +quint16 senderPort; + + // + // Copy the Raw measurements directly to the client. + // + FlightData.x = headpose[TX]; + FlightData.y = headpose[Pitch]; + FlightData.z = headpose[TZ]; + FlightData.p = headpose[TY]; + FlightData.h = headpose[Yaw]; + FlightData.r = headpose[Roll]; + FlightData.status = fg_cmd; + + // + // Try to send an UDP-message to the FlightGear + // + +#ifdef SEND_ASCII_DATA + sprintf_s(data, "%.2f %.2f %.2f %.2f %.2f %.2f\n\0", FlightData.x, FlightData.y, FlightData.z, FlightData.p, FlightData.h, FlightData.r); + + if (outSocket != 0) { + no_bytes = outSocket->writeD atagram((const char *) &data, strlen( data ), destIP, destPort); + if ( no_bytes > 0) { + qDebug() << "FGServer::writePendingDatagrams says: bytes send =" << data; + } + else { + qDebug() << "FGServer::writePendingDatagrams says: nothing sent!"; + } + } + +#endif + + #ifdef LOG_OUTPUT + // Use this for some debug-output to file... + QFile datafile(QCoreApplication::applicationDirPath() + "\\FG_output.txt"); + if (datafile.open(QFile::WriteOnly | QFile::Append)) { + QTextStream out(&datafile); + out << "output:\t" << FlightData.x << "\t" << FlightData.y << "\t" << FlightData.z << "\t" << FlightData.p << "\t" << FlightData.h << "\t" << FlightData.r << '\n'; + } + #endif + + #ifndef SEND_ASCII_DATA + //! [1] +// no_bytes = outSocket->writeDatagram((const char *) &FlightData, sizeof( FlightData ), QHostAddress::LocalHost, 5550); + if (outSocket != 0) { + no_bytes = outSocket->writeDatagram((const char *) &FlightData, sizeof( FlightData ), destIP, destPort); + if ( no_bytes > 0) { + // qDebug() << "FGServer::writePendingDatagrams says: bytes send =" << no_bytes << sizeof( double ); + } + else { + qDebug() << "FGServer::writePendingDatagrams says: nothing sent!"; + } + } + #endif + + // + // FlightGear keeps sending data, so we must read that here. + // + if (inSocket != 0) { + while (inSocket->hasPendingDatagrams()) { + + QByteArray datagram; + datagram.resize(inSocket->pendingDatagramSize()); + + inSocket->readDatagram( (char * ) &cmd, sizeof(cmd), &sender, &senderPort); + + fg_cmd = cmd; // Let's just accept that command for now... + if ( cmd > 0 ) { + qDebug() << "FGServer::sendHeadposeToGame hasPendingDatagrams, cmd = " << cmd; +// headTracker->handleGameCommand ( cmd ); // Send it upstream, for the Tracker to handle + } + + if (!blnConnectionActive) { + blnConnectionActive = true; + } + } + } +} + +// +// Check if the Client DLL exists and load it (to test it), if so. +// Returns 'true' if all seems OK. +// +bool FTNoIR_Protocol::checkServerInstallationOK() +{ + // Init. the data + FlightData.x = 0.0f; + FlightData.y = 0.0f; + FlightData.z = 0.0f; + FlightData.h = 0.0f; + FlightData.p = 0.0f; + FlightData.r = 0.0f; + FlightData.status = 0; + fg_cmd = 1; + + inSocket = 0; + outSocket = 0; + + // + // Create UDP-sockets. + // + if (inSocket == 0) { + qDebug() << "FGServer::sendHeadposeToGame creating insocket"; + inSocket = new QUdpSocket(); + + // Connect the inSocket to the port, to receive messages + if (!inSocket->bind(QHostAddress::Any, destPort+1)) { + QMessageBox::warning(0,"FaceTrackNoIR Error", "Unable to bind UDP-port",QMessageBox::Ok,QMessageBox::NoButton); + delete inSocket; + inSocket = 0; + return false; + } + } + + if (outSocket == 0) { + outSocket = new QUdpSocket(); + } + + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +// Factory function that creates instances if the Protocol object. + +// Export both decorated and undecorated names. +// GetProtocol - Undecorated name, which can be easily used with GetProcAddress +// Win32 API function. +// _GetProtocol@0 - Common name decoration for __stdcall functions in C language. +//#pragma comment(linker, "/export:GetProtocol=_GetProtocol@0") + +extern "C" FTNOIR_PROTOCOL_BASE_EXPORT IProtocol* CALLING_CONVENTION GetConstructor() +{ + return new FTNoIR_Protocol; +} diff --git a/ftnoir_tracker_pt/ftnoir_tracker_pt.cpp b/ftnoir_tracker_pt/ftnoir_tracker_pt.cpp deleted file mode 100644 index 48702d19..00000000 --- a/ftnoir_tracker_pt/ftnoir_tracker_pt.cpp +++ /dev/null @@ -1,261 +0,0 @@ -/* 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 "ftnoir_tracker_pt.h" -#include <QHBoxLayout> -#include <cmath> -#include <QDebug> -#include <QFile> -#include <QCoreApplication> -#include "facetracknoir/global-settings.h" - -using namespace std; -using namespace cv; - -//#define PT_PERF_LOG //log performance - -//----------------------------------------------------------------------------- -Tracker::Tracker() - : tracking_valid(false), frame_count(0), commands(0), video_widget(NULL), fresh(false) -{ - should_quit = false; - qDebug()<<"Tracker::Tracker"; - TrackerSettings settings; - settings.load_ini(); - apply(settings); -} - -Tracker::~Tracker() -{ - qDebug()<<"Tracker::~Tracker"; - set_command(ABORT); - wait(); - if (video_widget) delete video_widget; -} - -void Tracker::set_command(Command command) -{ - //QMutexLocker lock(&mutex); - commands |= command; -} - -void Tracker::reset_command(Command command) -{ - //QMutexLocker lock(&mutex); - commands &= ~command; -} - -void Tracker::run() -{ - qDebug()<<"Tracker:: Thread started"; - -#ifdef PT_PERF_LOG - QFile log_file(QCoreApplication::applicationDirPath() + "/PointTrackerPerformance.txt"); - if (!log_file.open(QIODevice::WriteOnly | QIODevice::Text)) return; - QTextStream log_stream(&log_file); -#endif - - time.start(); - float dt; - bool new_frame; - forever - { - { - QMutexLocker lock(&mutex); - if (should_quit) - break; - - if (commands & ABORT) break; - if (commands & PAUSE) continue; - commands = 0; - - dt = time.elapsed() / 1000.0; - time.restart(); - - new_frame = camera.get_frame(dt, &frame); - if (new_frame && !frame.empty()) - { - const std::vector<cv::Vec2f>& points = point_extractor.extract_points(frame, dt, draw_frame); - tracking_valid = point_tracker.track(points, camera.get_info().f, dt); - frame_count++; - fresh = true; - } -#ifdef PT_PERF_LOG - log_stream<<"dt: "<<dt; - if (!frame.empty()) log_stream<<" fps: "<<camera.get_info().fps; - log_stream<<"\n"; -#endif - refreshVideo(); - } - msleep(sleep_time); - } - - qDebug()<<"Tracker:: Thread stopping"; -} - -void Tracker::apply(const TrackerSettings& settings) -{ - qDebug()<<"Tracker:: Applying settings"; - QMutexLocker lock(&mutex); - camera.set_index(settings.cam_index); - camera.set_res(settings.cam_res_x, settings.cam_res_y); - camera.set_fps(settings.cam_fps); - camera.set_f(settings.cam_f); - point_extractor.threshold_val = settings.threshold; - point_extractor.min_size = settings.min_point_size; - point_extractor.max_size = settings.max_point_size; - point_tracker.point_model = std::auto_ptr<PointModel>(new PointModel(settings.M01, settings.M02)); - point_tracker.dynamic_pose_resolution = settings.dyn_pose_res; - sleep_time = settings.sleep_time; - point_tracker.dt_reset = settings.reset_time / 1000.0; - draw_frame = settings.video_widget; - cam_pitch = settings.cam_pitch; - - bEnableRoll = settings.bEnableRoll; - bEnablePitch = settings.bEnablePitch; - bEnableYaw = settings.bEnableYaw; - bEnableX = settings.bEnableX; - bEnableY = settings.bEnableY; - bEnableZ = settings.bEnableZ; - - t_MH = settings.t_MH; - qDebug()<<"Tracker::apply ends"; -} - -void Tracker::reset() -{ - QMutexLocker lock(&mutex); - point_tracker.reset(); -} - -void Tracker::center() -{ - point_tracker.reset(); // we also do a reset here since there is no reset shortkey yet - QMutexLocker lock(&mutex); - FrameTrafo X_CM_0 = point_tracker.get_pose(); - FrameTrafo X_MH(Matx33f::eye(), t_MH); - X_CH_0 = X_CM_0 * X_MH; -} - -void Tracker::refreshVideo() -{ - if (video_widget && fresh) - { - Mat frame_copy; - std::auto_ptr< vector<Vec2f> > points; - { - //QMutexLocker lock(&mutex); - if (!draw_frame || frame.empty()) return; - - // copy the frame and points from the tracker thread - frame_copy = frame.clone(); - points = std::auto_ptr< vector<Vec2f> >(new vector<Vec2f>(point_extractor.get_points())); - } - //QMutexLocker lck(&mutex); - video_widget->update_image(frame_copy, points); - } -} - -void Tracker::StartTracker(QFrame* videoframe) -{ - const int VIDEO_FRAME_WIDTH = videoframe->width(); - const int VIDEO_FRAME_HEIGHT = videoframe->height(); - TrackerSettings settings; - settings.load_ini(); - apply(settings); - qDebug("Tracker::Initialize"); - // setup video frame - video_widget = new VideoWidget(videoframe); - QHBoxLayout* layout = new QHBoxLayout(); - layout->setContentsMargins(0, 0, 0, 0); - layout->addWidget(video_widget); - if (videoframe->layout()) delete videoframe->layout(); - videoframe->setLayout(layout); - video_widget->resize(VIDEO_FRAME_WIDTH, VIDEO_FRAME_HEIGHT); - videoframe->show(); - connect(&timer, SIGNAL(timeout()), this, SLOT(paint_widget())); - timer.start(40); - camera.start(); - start(); - reset_command(PAUSE); -} - -void Tracker::paint_widget() { - if (fresh) { - fresh = false; - video_widget->update(); - } -} - -bool Tracker::GiveHeadPoseData(double *data) -{ - const double rad2deg = 180.0/3.14159265; - const double deg2rad = 1.0/rad2deg; - { - QMutexLocker lock(&mutex); - - if (!tracking_valid) return false; - - FrameTrafo X_CM = point_tracker.get_pose(); - FrameTrafo X_MH(Matx33f::eye(), t_MH); - FrameTrafo X_CH = X_CM * X_MH; - - Matx33f R = X_CH.R * X_CH_0.R.t(); - Vec3f t = X_CH.t - X_CH_0.t; - - // correct for camera pitch - Matx33f R_CP( 1, 0, 0, - 0, cos(deg2rad*cam_pitch), sin(deg2rad*cam_pitch), - 0, -sin(deg2rad*cam_pitch), cos(deg2rad*cam_pitch)); - R = R_CP * R * R_CP.t(); - t = R_CP * t; - - // get translation(s) - if (bEnableX) { - data[TX] = t[0] / 10.0; // convert to cm - } - if (bEnableY) { - data[TY] = t[1] / 10.0; - } - if (bEnableZ) { - data[TZ] = t[2] / 10.0; - } - - // translate rotation matrix from opengl (G) to roll-pitch-yaw (R) frame - // -z -> x, y -> z, x -> -y - Matx33f R_RG( 0, 0,-1, - -1, 0, 0, - 0, 1, 0); - R = R_RG * R * R_RG.t(); - - // extract rotation angles - double alpha, beta, gamma; - //beta = atan2( -R(2,0), sqrt(R(0,0)*R(0,0) + R(1,0)*R(1,0)) ); - beta = atan2( -R(2,0), sqrt(R(2,1)*R(2,1) + R(2,2)*R(2,2)) ); - alpha = atan2( R(1,0), R(0,0)); - gamma = atan2( R(2,1), R(2,2)); - - if (bEnableYaw) { - data[Yaw] = rad2deg * alpha; - } - if (bEnablePitch) { - data[Pitch] = rad2deg * beta; - } - if (bEnableRoll) { - data[Roll] = rad2deg * gamma; - } - } - return true; -} - -//----------------------------------------------------------------------------- -//#pragma comment(linker, "/export:GetTracker=_GetTracker@0") - -extern "C" FTNOIR_TRACKER_BASE_EXPORT ITracker* CALLING_CONVENTION GetConstructor() -{ - return new Tracker; -} diff --git a/ftnoir_tracker_pt/ftnoir_tracker_pt.qrc b/ftnoir_tracker_pt/ftnoir_tracker_pt.qrc deleted file mode 100644 index 5734917f..00000000 --- a/ftnoir_tracker_pt/ftnoir_tracker_pt.qrc +++ /dev/null @@ -1,10 +0,0 @@ -<RCC> - <qresource prefix="/"> - <file>resources/icon.png</file> - <file>resources/cap_front.png</file> - <file>resources/cap_side.png</file> - <file>resources/clip_front.png</file> - <file>resources/clip_side.png</file> - <file>resources/logo_ir.png</file> - </qresource> -</RCC> diff --git a/ftnoir_tracker_pt/resources/icon.png b/ftnoir_tracker_pt/resources/icon.png Binary files differdeleted file mode 100644 index 49af20e4..00000000 --- a/ftnoir_tracker_pt/resources/icon.png +++ /dev/null diff --git a/ftnoir_tracker_pt/video_widget.cpp b/ftnoir_tracker_pt/video_widget.cpp deleted file mode 100644 index 2b554aba..00000000 --- a/ftnoir_tracker_pt/video_widget.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/* 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 cv; -using namespace std; - -void VideoWidget::update_image(Mat frame, std::auto_ptr< vector<Vec2f> >) -{ - QMutexLocker foo(&mtx); - - if (frame.channels() != 3 && frame.channels() != 1) - return; - - int width = frame.cols, height = frame.rows; - unsigned char* src = frame.data; - - QImage qframe(width, height, QImage::Format_RGB888); - if (frame.channels() == 3) - { - uchar* data = qframe.bits(); - const int pitch = qframe.bytesPerLine(); - for (int y = 0; y < height; y++) - for (int x = 0; x < width; x++) - { - const int pos = 3 * (y*width + x); - data[y * pitch + x * 3 + 0] = src[pos + 2]; - data[y * pitch + x * 3 + 1] = src[pos + 1]; - data[y * pitch + x * 3 + 2] = src[pos + 0]; - } - } else { - uchar* data = qframe.bits(); - const int pitch = qframe.bytesPerLine(); - for (int y = 0; y < height; y++) - for (int x = 0; x < width; x++) - { - const int pos = (y*width + x); - data[y * pitch + x * 3 + 0] = src[pos]; - data[y * pitch + x * 3 + 1] = src[pos]; - data[y * pitch + x * 3 + 2] = src[pos]; - } - } - qframe = qframe.scaled(size(), Qt::IgnoreAspectRatio, Qt::FastTransformation); - pixmap = QPixmap::fromImage(qframe); -} diff --git a/ftnoir_tracker_pt/video_widget.h b/ftnoir_tracker_pt/video_widget.h deleted file mode 100644 index 3051919b..00000000 --- a/ftnoir_tracker_pt/video_widget.h +++ /dev/null @@ -1,42 +0,0 @@ -/* 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 <opencv2/opencv.hpp> -#include <memory> -#include <QWidget> -#include <QMutex> -#include <QMutexLocker> -#include <QLabel> -#include <QPainter> -#include <QPaintEvent> - -// ---------------------------------------------------------------------------- -class VideoWidget : public QWidget -{ - Q_OBJECT - -public: - VideoWidget(QWidget *parent) : QWidget(parent), mtx() { - } - void update_image(cv::Mat frame, std::auto_ptr< std::vector<cv::Vec2f> >); -protected slots: - void paintEvent( QPaintEvent* e ) { - QMutexLocker foo(&mtx); - QPainter painter(this); - painter.drawPixmap(e->rect(), pixmap, e->rect()); - } - -private: - QMutex mtx; - QPixmap pixmap; -}; - -#endif // VIDEOWIDGET_H diff --git a/ftnoir_tracker_pt/videoinput/videoinput.h b/ftnoir_tracker_pt/videoinput/videoinput.h deleted file mode 100644 index 02841418..00000000 --- a/ftnoir_tracker_pt/videoinput/videoinput.h +++ /dev/null @@ -1,385 +0,0 @@ -#ifndef _VIDEOINPUT -#define _VIDEOINPUT - -//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -//THE SOFTWARE. - -////////////////////////////////////////////////////////// -//Written by Theodore Watson - theo.watson@gmail.com // -//Do whatever you want with this code but if you find // -//a bug or make an improvement I would love to know! // -// // -//Warning This code is experimental // -//use at your own risk :) // -////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////// -/* Shoutouts - -Thanks to: - - Dillip Kumar Kara for crossbar code. - Zachary Lieberman for getting me into this stuff - and for being so generous with time and code. - The guys at Potion Design for helping me with VC++ - Josh Fisher for being a serious C++ nerd :) - Golan Levin for helping me debug the strangest - and slowest bug in the world! - - And all the people using this library who send in - bugs, suggestions and improvements who keep me working on - the next version - yeah thanks a lot ;) - -*/ -///////////////////////////////////////////////////////// - - - -#include <stdlib.h> -#include <stdio.h> -#include <math.h> -#include <string.h> -#include <wchar.h> - -//this is for TryEnterCriticalSection -#ifndef _WIN32_WINNT - # define _WIN32_WINNT 0x400 -#endif -#include <windows.h> - - -//Example Usage -/* - //create a videoInput object - videoInput VI; - - //Prints out a list of available devices and returns num of devices found - int numDevices = VI.listDevices(); - - int device1 = 0; //this could be any deviceID that shows up in listDevices - int device2 = 1; //this could be any deviceID that shows up in listDevices - - //if you want to capture at a different frame rate (default is 30) - //specify it here, you are not guaranteed to get this fps though. - //VI.setIdealFramerate(dev, 60); - - //setup the first device - there are a number of options: - - VI.setupDevice(device1); //setup the first device with the default settings - //VI.setupDevice(device1, VI_COMPOSITE); //or setup device with specific connection type - //VI.setupDevice(device1, 320, 240); //or setup device with specified video size - //VI.setupDevice(device1, 320, 240, VI_COMPOSITE); //or setup device with video size and connection type - - //VI.setFormat(device1, VI_NTSC_M); //if your card doesn't remember what format it should be - //call this with the appropriate format listed above - //NOTE: must be called after setupDevice! - - //optionally setup a second (or third, fourth ...) device - same options as above - VI.setupDevice(device2); - - //As requested width and height can not always be accomodated - //make sure to check the size once the device is setup - - int width = VI.getWidth(device1); - int height = VI.getHeight(device1); - int size = VI.getSize(device1); - - unsigned char * yourBuffer1 = new unsigned char[size]; - unsigned char * yourBuffer2 = new unsigned char[size]; - - //to get the data from the device first check if the data is new - if(VI.isFrameNew(device1)){ - VI.getPixels(device1, yourBuffer1, false, false); //fills pixels as a BGR (for openCV) unsigned char array - no flipping - VI.getPixels(device1, yourBuffer2, true, true); //fills pixels as a RGB (for openGL) unsigned char array - flipping! - } - - //same applies to device2 etc - - //to get a settings dialog for the device - VI.showSettingsWindow(device1); - - - //Shut down devices properly - VI.stopDevice(device1); - VI.stopDevice(device2); -*/ - - -////////////////////////////////////// VARS AND DEFS ////////////////////////////////// - - -//STUFF YOU CAN CHANGE - -//change for verbose debug info -static bool verbose = true; - -//if you need VI to use multi threaded com -//#define VI_COM_MULTI_THREADED - -//STUFF YOU DON'T CHANGE - -//videoInput defines -#define VI_VERSION 0.1995 -#define VI_MAX_CAMERAS 20 -#define VI_NUM_TYPES 18 //DON'T TOUCH -#define VI_NUM_FORMATS 18 //DON'T TOUCH - -//defines for setPhyCon - tuner is not as well supported as composite and s-video -#define VI_COMPOSITE 0 -#define VI_S_VIDEO 1 -#define VI_TUNER 2 -#define VI_USB 3 -#define VI_1394 4 - -//defines for formats -#define VI_NTSC_M 0 -#define VI_PAL_B 1 -#define VI_PAL_D 2 -#define VI_PAL_G 3 -#define VI_PAL_H 4 -#define VI_PAL_I 5 -#define VI_PAL_M 6 -#define VI_PAL_N 7 -#define VI_PAL_NC 8 -#define VI_SECAM_B 9 -#define VI_SECAM_D 10 -#define VI_SECAM_G 11 -#define VI_SECAM_H 12 -#define VI_SECAM_K 13 -#define VI_SECAM_K1 14 -#define VI_SECAM_L 15 -#define VI_NTSC_M_J 16 -#define VI_NTSC_433 17 - - -//allows us to directShow classes here with the includes in the cpp -struct ICaptureGraphBuilder2; -struct IGraphBuilder; -struct IBaseFilter; -struct IAMCrossbar; -struct IMediaControl; -struct ISampleGrabber; -struct IMediaEventEx; -struct IAMStreamConfig; -struct _AMMediaType; -class SampleGrabberCallback; -typedef _AMMediaType AM_MEDIA_TYPE; - -//keeps track of how many instances of VI are being used -//don't touch -static int comInitCount = 0; - - -//////////////////////////////////////// VIDEO DEVICE /////////////////////////////////// - -class videoDevice{ - - - public: - - videoDevice(); - void setSize(int w, int h); - void NukeDownstream(IBaseFilter *pBF); - void destroyGraph(); - ~videoDevice(); - - int videoSize; - int width; - int height; - int tryWidth; - int tryHeight; - - ICaptureGraphBuilder2 *pCaptureGraph; // Capture graph builder object - IGraphBuilder *pGraph; // Graph builder object - IMediaControl *pControl; // Media control object - IBaseFilter *pVideoInputFilter; // Video Capture filter - IBaseFilter *pGrabberF; - IBaseFilter * pDestFilter; - IAMStreamConfig *streamConf; - ISampleGrabber * pGrabber; // Grabs frame - AM_MEDIA_TYPE * pAmMediaType; - - IMediaEventEx * pMediaEvent; - - GUID videoType; - long formatType; - - SampleGrabberCallback * sgCallback; - - bool tryDiffSize; - bool useCrossbar; - bool readyToCapture; - bool sizeSet; - bool setupStarted; - bool specificFormat; - bool autoReconnect; - int nFramesForReconnect; - unsigned long nFramesRunning; - int connection; - int storeConn; - int myID; - long requestedFrameTime; //ie fps - - char nDeviceName[255]; - WCHAR wDeviceName[255]; - - unsigned char * pixels; - char * pBuffer; - -}; - - - - -////////////////////////////////////// VIDEO INPUT ///////////////////////////////////// - - - -class videoInput{ - - public: - videoInput(); - ~videoInput(); - - //turns off console messages - default is to print messages - static void setVerbose(bool _verbose); - - //Functions in rough order they should be used. - static int listDevices(bool silent = false); - - //needs to be called after listDevices - otherwise returns NULL - static char * getDeviceName(int deviceID); - - //choose to use callback based capture - or single threaded - void setUseCallback(bool useCallback); - - //call before setupDevice - //directshow will try and get the closest possible framerate to what is requested - void setIdealFramerate(int deviceID, int idealFramerate); - - //some devices will stop delivering frames after a while - this method gives you the option to try and reconnect - //to a device if videoInput detects that a device has stopped delivering frames. - //you MUST CALL isFrameNew every app loop for this to have any effect - void setAutoReconnectOnFreeze(int deviceNumber, bool doReconnect, int numMissedFramesBeforeReconnect); - - //Choose one of these four to setup your device - bool setupDevice(int deviceID); - bool setupDevice(int deviceID, int w, int h); - - //These two are only for capture cards - //USB and Firewire cameras souldn't specify connection - bool setupDevice(int deviceID, int connection); - bool setupDevice(int deviceID, int w, int h, int connection); - - //If you need to you can set your NTSC/PAL/SECAM - //preference here. if it is available it will be used. - //see #defines above for available formats - eg VI_NTSC_M or VI_PAL_B - //should be called after setupDevice - //can be called multiple times - bool setFormat(int deviceNumber, int format); - - //Tells you when a new frame has arrived - you should call this if you have specified setAutoReconnectOnFreeze to true - bool isFrameNew(int deviceID); - - bool isDeviceSetup(int deviceID); - - //Returns the pixels - flipRedAndBlue toggles RGB/BGR flipping - and you can flip the image too - unsigned char * getPixels(int deviceID, bool flipRedAndBlue = true, bool flipImage = false); - - //Or pass in a buffer for getPixels to fill returns true if successful. - bool getPixels(int id, unsigned char * pixels, bool flipRedAndBlue = true, bool flipImage = false); - - //Launches a pop up settings window - //For some reason in GLUT you have to call it twice each time. - void showSettingsWindow(int deviceID); - - //Manual control over settings thanks..... - //These are experimental for now. - bool setVideoSettingFilter(int deviceID, long Property, long lValue, long Flags = NULL, bool useDefaultValue = false); - bool setVideoSettingFilterPct(int deviceID, long Property, float pctValue, long Flags = NULL); - bool getVideoSettingFilter(int deviceID, long Property, long &min, long &max, long &SteppingDelta, long ¤tValue, long &flags, long &defaultValue); - - bool setVideoSettingCamera(int deviceID, long Property, long lValue, long Flags = NULL, bool useDefaultValue = false); - bool setVideoSettingCameraPct(int deviceID, long Property, float pctValue, long Flags = NULL); - bool getVideoSettingCamera(int deviceID, long Property, long &min, long &max, long &SteppingDelta, long ¤tValue, long &flags, long &defaultValue); - - //bool setVideoSettingCam(int deviceID, long Property, long lValue, long Flags = NULL, bool useDefaultValue = false); - - //get width, height and number of pixels - int getWidth(int deviceID); - int getHeight(int deviceID); - int getSize(int deviceID); - - //completely stops and frees a device - void stopDevice(int deviceID); - - //as above but then sets it up with same settings - bool restartDevice(int deviceID); - - //number of devices available - int devicesFound; - - long propBrightness; - long propContrast; - long propHue; - long propSaturation; - long propSharpness; - long propGamma; - long propColorEnable; - long propWhiteBalance; - long propBacklightCompensation; - long propGain; - - long propPan; - long propTilt; - long propRoll; - long propZoom; - long propExposure; - long propIris; - long propFocus; - - - private: - void setPhyCon(int deviceID, int conn); - void setAttemptCaptureSize(int deviceID, int w, int h); - bool setup(int deviceID); - void processPixels(unsigned char * src, unsigned char * dst, int width, int height, bool bRGB, bool bFlip); - int start(int deviceID, videoDevice * VD); - int getDeviceCount(); - void getMediaSubtypeAsString(GUID type, char * typeAsString); - - HRESULT getDevice(IBaseFilter **pSrcFilter, int deviceID, WCHAR * wDeviceName, char * nDeviceName); - static HRESULT ShowFilterPropertyPages(IBaseFilter *pFilter); - HRESULT SaveGraphFile(IGraphBuilder *pGraph, WCHAR *wszPath); - HRESULT routeCrossbar(ICaptureGraphBuilder2 **ppBuild, IBaseFilter **pVidInFilter, int conType, GUID captureMode); - - //don't touch - static bool comInit(); - static bool comUnInit(); - - int connection; - int callbackSetCount; - bool bCallback; - - GUID CAPTURE_MODE; - - //Extra video subtypes - GUID MEDIASUBTYPE_Y800; - GUID MEDIASUBTYPE_Y8; - GUID MEDIASUBTYPE_GREY; - - videoDevice * VDList[VI_MAX_CAMERAS]; - GUID mediaSubtypes[VI_NUM_TYPES]; - long formatTypes[VI_NUM_FORMATS]; - - static void __cdecl basicThread(void * objPtr); - - static char deviceNames[VI_MAX_CAMERAS][255]; - -}; - - #endif diff --git a/ftnoir_tracker_pt/videoinput/videoinput_vc8.lib b/ftnoir_tracker_pt/videoinput/videoinput_vc8.lib Binary files differdeleted file mode 100644 index 15ca9cf3..00000000 --- a/ftnoir_tracker_pt/videoinput/videoinput_vc8.lib +++ /dev/null diff --git a/ftnoir_tracker_pt/videoinput/videoinput_vc9.lib b/ftnoir_tracker_pt/videoinput/videoinput_vc9.lib Binary files differdeleted file mode 100644 index 32637cc9..00000000 --- a/ftnoir_tracker_pt/videoinput/videoinput_vc9.lib +++ /dev/null |