summaryrefslogtreecommitdiffhomepage
path: root/ftnoir_tracker_aruco
diff options
context:
space:
mode:
Diffstat (limited to 'ftnoir_tracker_aruco')
-rw-r--r--ftnoir_tracker_aruco/ar_video_widget.cpp42
-rw-r--r--ftnoir_tracker_aruco/ar_video_widget.h (renamed from ftnoir_tracker_aruco/video_widget.h)20
-rw-r--r--ftnoir_tracker_aruco/aruco-trackercontrols.ui782
-rw-r--r--ftnoir_tracker_aruco/ftnoir_tracker_aruco.cpp530
-rw-r--r--ftnoir_tracker_aruco/ftnoir_tracker_aruco.h90
-rw-r--r--ftnoir_tracker_aruco/ftnoir_tracker_aruco_dll.h3
-rw-r--r--ftnoir_tracker_aruco/include/boarddetector.h2
-rw-r--r--ftnoir_tracker_aruco/include/cvdrawingutils.h2
-rw-r--r--ftnoir_tracker_aruco/include/markerdetector.h11
-rw-r--r--ftnoir_tracker_aruco/video_widget.cpp30
10 files changed, 701 insertions, 811 deletions
diff --git a/ftnoir_tracker_aruco/ar_video_widget.cpp b/ftnoir_tracker_aruco/ar_video_widget.cpp
new file mode 100644
index 00000000..9a089213
--- /dev/null
+++ b/ftnoir_tracker_aruco/ar_video_widget.cpp
@@ -0,0 +1,42 @@
+/* Copyright (c) 2012 Patrick Ruoff
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ */
+
+#include "ar_video_widget.h"
+
+#include <QDebug>
+
+using namespace std;
+
+void ArucoVideoWidget::update_image(const cv::Mat& frame)
+{
+ QMutexLocker foo(&mtx);
+ _frame = frame.clone();
+}
+
+void ArucoVideoWidget::update_and_repaint()
+{
+ QMutexLocker foo(&mtx);
+ if (_frame.cols*_frame.rows <= 0)
+ return;
+ QImage qframe = QImage(_frame.cols, _frame.rows, QImage::Format_RGB888);
+ uchar* data = qframe.bits();
+ const int pitch = qframe.bytesPerLine();
+ for (int y = 0; y < _frame.rows; y++)
+ {
+ for (int x = 0; x < _frame.cols; x++)
+ {
+ const auto& elt = _frame.at<cv::Vec3b>(y, x);
+ const cv::Scalar elt2 = static_cast<cv::Scalar>(elt);
+ data[y * pitch + x * 3 + 0] = elt2.val[2];
+ data[y * pitch + x * 3 + 1] = elt2.val[1];
+ data[y * pitch + x * 3 + 2] = elt2.val[0];
+ }
+ }
+ auto qframe2 = qframe.scaled(size(), Qt::IgnoreAspectRatio, Qt::FastTransformation);
+ texture = qframe2;
+ update();
+}
diff --git a/ftnoir_tracker_aruco/video_widget.h b/ftnoir_tracker_aruco/ar_video_widget.h
index 87b6278a..e2cf4d9f 100644
--- a/ftnoir_tracker_aruco/video_widget.h
+++ b/ftnoir_tracker_aruco/ar_video_widget.h
@@ -8,32 +8,40 @@
#ifndef VIDEOWIDGET_H
#define VIDEOWIDGET_H
-#include <QTime>
+#include <QTimer>
#include <QWidget>
#include <QMutex>
#include <QMutexLocker>
#include <QLabel>
#include <QPainter>
#include <QPaintEvent>
+#include <QTimer>
+#include <opencv/cv.hpp>
// ----------------------------------------------------------------------------
-class VideoWidget : public QWidget
+class ArucoVideoWidget : public QWidget
{
Q_OBJECT
public:
- VideoWidget(QWidget *parent) : QWidget(parent), mtx() {
+ ArucoVideoWidget(QWidget *parent) : QWidget(parent) {
+ connect(&timer, SIGNAL(timeout()), this, SLOT(update_and_repaint()));
+ timer.start(60);
}
- void update_image(unsigned char* frame, int width, int height);
+ void update_image(const cv::Mat& frame);
protected slots:
void paintEvent( QPaintEvent* e ) {
QMutexLocker foo(&mtx);
QPainter painter(this);
- painter.drawPixmap(e->rect(), pixmap, e->rect());
+ painter.drawImage(e->rect(), texture);
}
+ void update_and_repaint();
+
private:
QMutex mtx;
- QPixmap pixmap;
+ QImage texture;
+ QTimer timer;
+ cv::Mat _frame;
};
#endif // VIDEOWIDGET_H
diff --git a/ftnoir_tracker_aruco/aruco-trackercontrols.ui b/ftnoir_tracker_aruco/aruco-trackercontrols.ui
index 3ad9fa40..1d5a4241 100644
--- a/ftnoir_tracker_aruco/aruco-trackercontrols.ui
+++ b/ftnoir_tracker_aruco/aruco-trackercontrols.ui
@@ -9,475 +9,365 @@
<rect>
<x>0</x>
<y>0</y>
- <width>593</width>
- <height>280</height>
+ <width>615</width>
+ <height>326</height>
</rect>
</property>
<property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+ <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
- <width>750</width>
- <height>280</height>
+ <width>6666</width>
+ <height>6666</height>
</size>
</property>
<property name="windowTitle">
<string>HT tracker settings</string>
</property>
- <widget class="QLabel" name="label">
- <property name="geometry">
- <rect>
- <x>10</x>
- <y>10</y>
- <width>141</width>
- <height>16</height>
- </rect>
- </property>
- <property name="text">
- <string>Horizontal FOV</string>
- </property>
- </widget>
- <widget class="QDoubleSpinBox" name="cameraFOV">
- <property name="geometry">
- <rect>
- <x>130</x>
- <y>10</y>
- <width>251</width>
- <height>22</height>
- </rect>
- </property>
- <property name="locale">
- <locale language="English" country="UnitedStates"/>
- </property>
- <property name="minimum">
- <double>35.000000000000000</double>
- </property>
- <property name="maximum">
- <double>180.000000000000000</double>
- </property>
- <property name="value">
- <double>52.000000000000000</double>
- </property>
- </widget>
- <widget class="QLabel" name="label_2">
- <property name="geometry">
- <rect>
- <x>10</x>
- <y>40</y>
- <width>137</width>
- <height>16</height>
- </rect>
- </property>
- <property name="text">
- <string>Frames per second</string>
- </property>
- </widget>
- <widget class="QComboBox" name="cameraFPS">
- <property name="geometry">
- <rect>
- <x>130</x>
- <y>40</y>
- <width>251</width>
- <height>22</height>
- </rect>
- </property>
- <item>
- <property name="text">
- <string notr="true">Default</string>
- </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <property name="spacing">
+ <number>7</number>
+ </property>
+ <item row="9" column="1" rowspan="3">
+ <widget class="QGroupBox" name="groupBox_2">
+ <property name="title">
+ <string>Head position</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_2">
+ <item row="2" column="0">
+ <widget class="QLabel" name="label_7">
+ <property name="text">
+ <string>TY</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_5">
+ <property name="text">
+ <string>TX</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QDoubleSpinBox" name="cx">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimum">
+ <double>-10000.000000000000000</double>
+ </property>
+ <property name="maximum">
+ <double>10000.000000000000000</double>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0">
+ <widget class="QLabel" name="label_8">
+ <property name="text">
+ <string>TZ</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1">
+ <widget class="QDoubleSpinBox" name="cz">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimum">
+ <double>-10000.000000000000000</double>
+ </property>
+ <property name="maximum">
+ <double>10000.000000000000000</double>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QDoubleSpinBox" name="cy">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimum">
+ <double>-10000.000000000000000</double>
+ </property>
+ <property name="maximum">
+ <double>10000.000000000000000</double>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
</item>
- <item>
- <property name="text">
- <string>30</string>
- </property>
+ <item row="0" column="3" rowspan="3" colspan="2">
+ <widget class="QGroupBox" name="groupBox">
+ <property name="title">
+ <string>Enable axes</string>
+ </property>
+ <layout class="QFormLayout" name="formLayout">
+ <property name="horizontalSpacing">
+ <number>7</number>
+ </property>
+ <property name="leftMargin">
+ <number>6</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>6</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item row="0" column="0">
+ <widget class="QCheckBox" name="rx">
+ <property name="text">
+ <string>RX</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QCheckBox" name="tx">
+ <property name="text">
+ <string>TX</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QCheckBox" name="ry">
+ <property name="text">
+ <string>RY</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QCheckBox" name="ty">
+ <property name="text">
+ <string>TY</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QCheckBox" name="rz">
+ <property name="text">
+ <string>RZ</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QCheckBox" name="tz">
+ <property name="text">
+ <string>TZ</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
</item>
- <item>
- <property name="text">
- <string>60</string>
- </property>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Frames per second</string>
+ </property>
+ </widget>
</item>
- <item>
- <property name="text">
- <string>120</string>
- </property>
+ <item row="2" column="1" colspan="2">
+ <widget class="QComboBox" name="cameraName"/>
</item>
- </widget>
- <widget class="QLabel" name="label_3">
- <property name="geometry">
- <rect>
- <x>10</x>
- <y>70</y>
- <width>133</width>
- <height>16</height>
- </rect>
- </property>
- <property name="text">
- <string>Camera name</string>
- </property>
- </widget>
- <widget class="QPushButton" name="buttonOK">
- <property name="geometry">
- <rect>
- <x>430</x>
- <y>250</y>
- <width>75</width>
- <height>23</height>
- </rect>
- </property>
- <property name="text">
- <string>OK</string>
- </property>
- </widget>
- <widget class="QPushButton" name="buttonCancel">
- <property name="geometry">
- <rect>
- <x>510</x>
- <y>250</y>
- <width>75</width>
- <height>23</height>
- </rect>
- </property>
- <property name="text">
- <string>Cancel</string>
- </property>
- </widget>
- <widget class="QGroupBox" name="groupBox">
- <property name="geometry">
- <rect>
- <x>390</x>
- <y>10</y>
- <width>101</width>
- <height>81</height>
- </rect>
- </property>
- <property name="title">
- <string>Enable axes</string>
- </property>
- <widget class="QCheckBox" name="rx">
- <property name="geometry">
- <rect>
- <x>10</x>
- <y>20</y>
- <width>70</width>
- <height>17</height>
- </rect>
- </property>
- <property name="text">
- <string>RX</string>
- </property>
- </widget>
- <widget class="QCheckBox" name="ry">
- <property name="geometry">
- <rect>
- <x>10</x>
- <y>40</y>
- <width>70</width>
- <height>17</height>
- </rect>
- </property>
- <property name="text">
- <string>RY</string>
- </property>
- </widget>
- <widget class="QCheckBox" name="rz">
- <property name="geometry">
- <rect>
- <x>10</x>
- <y>60</y>
- <width>70</width>
- <height>17</height>
- </rect>
- </property>
- <property name="text">
- <string>RZ</string>
- </property>
- </widget>
- <widget class="QCheckBox" name="tx">
- <property name="geometry">
- <rect>
- <x>60</x>
- <y>20</y>
- <width>70</width>
- <height>17</height>
- </rect>
- </property>
- <property name="text">
- <string>TX</string>
- </property>
- </widget>
- <widget class="QCheckBox" name="ty">
- <property name="geometry">
- <rect>
- <x>60</x>
- <y>40</y>
- <width>70</width>
- <height>17</height>
- </rect>
- </property>
- <property name="text">
- <string>TY</string>
- </property>
- </widget>
- <widget class="QCheckBox" name="tz">
- <property name="geometry">
- <rect>
- <x>60</x>
- <y>60</y>
- <width>70</width>
- <height>17</height>
- </rect>
- </property>
- <property name="text">
- <string>TZ</string>
- </property>
- </widget>
- </widget>
- <widget class="QComboBox" name="cameraName">
- <property name="geometry">
- <rect>
- <x>130</x>
- <y>70</y>
- <width>251</width>
- <height>22</height>
- </rect>
- </property>
- </widget>
- <widget class="QLabel" name="label_4">
- <property name="geometry">
- <rect>
- <x>10</x>
- <y>100</y>
- <width>128</width>
- <height>16</height>
- </rect>
- </property>
- <property name="text">
- <string>Resolution</string>
- </property>
- </widget>
- <widget class="QComboBox" name="resolution">
- <property name="geometry">
- <rect>
- <x>130</x>
- <y>100</y>
- <width>251</width>
- <height>22</height>
- </rect>
- </property>
- <item>
- <property name="text">
- <string>640x480</string>
- </property>
+ <item row="1" column="1" colspan="2">
+ <widget class="QComboBox" name="cameraFPS">
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>30</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>60</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>120</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>180</string>
+ </property>
+ </item>
+ </widget>
</item>
- <item>
- <property name="text">
- <string>320x240</string>
- </property>
+ <item row="7" column="1">
+ <widget class="QCheckBox" name="red_only">
+ <property name="text">
+ <string>Recommended!</string>
+ </property>
+ </widget>
</item>
- <item>
- <property name="text">
- <string>320x200</string>
- </property>
+ <item row="2" column="0">
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>Camera name</string>
+ </property>
+ </widget>
</item>
- <item>
- <property name="text">
- <string>Default (not recommended!)</string>
- </property>
+ <item row="0" column="1" colspan="2">
+ <widget class="QDoubleSpinBox" name="cameraFOV">
+ <property name="locale">
+ <locale language="English" country="UnitedStates"/>
+ </property>
+ <property name="minimum">
+ <double>35.000000000000000</double>
+ </property>
+ <property name="maximum">
+ <double>180.000000000000000</double>
+ </property>
+ <property name="value">
+ <double>52.000000000000000</double>
+ </property>
+ </widget>
</item>
- </widget>
- <widget class="QDoubleSpinBox" name="doubleSpinBox">
- <property name="geometry">
- <rect>
- <x>130</x>
- <y>130</y>
- <width>171</width>
- <height>22</height>
- </rect>
- </property>
- <property name="frame">
- <bool>true</bool>
- </property>
- <property name="buttonSymbols">
- <enum>QAbstractSpinBox::NoButtons</enum>
- </property>
- <property name="decimals">
- <number>24</number>
- </property>
- <property name="minimum">
- <double>-1000.000000000000000</double>
- </property>
- <property name="maximum">
- <double>1000.000000000000000</double>
- </property>
- <property name="singleStep">
- <double>0.000000000000000</double>
- </property>
- </widget>
- <widget class="QLabel" name="label_5">
- <property name="geometry">
- <rect>
- <x>10</x>
- <y>130</y>
- <width>111</width>
- <height>16</height>
- </rect>
- </property>
- <property name="text">
- <string>Distortion coefficients</string>
- </property>
- </widget>
- <widget class="QDoubleSpinBox" name="doubleSpinBox_2">
- <property name="geometry">
- <rect>
- <x>130</x>
- <y>160</y>
- <width>171</width>
- <height>22</height>
- </rect>
- </property>
- <property name="frame">
- <bool>true</bool>
- </property>
- <property name="buttonSymbols">
- <enum>QAbstractSpinBox::NoButtons</enum>
- </property>
- <property name="decimals">
- <number>24</number>
- </property>
- <property name="minimum">
- <double>-1000.000000000000000</double>
- </property>
- <property name="maximum">
- <double>1000.000000000000000</double>
- </property>
- <property name="singleStep">
- <double>0.000000000000000</double>
- </property>
- </widget>
- <widget class="QDoubleSpinBox" name="doubleSpinBox_3">
- <property name="geometry">
- <rect>
- <x>130</x>
- <y>190</y>
- <width>171</width>
- <height>22</height>
- </rect>
- </property>
- <property name="frame">
- <bool>true</bool>
- </property>
- <property name="buttonSymbols">
- <enum>QAbstractSpinBox::NoButtons</enum>
- </property>
- <property name="decimals">
- <number>24</number>
- </property>
- <property name="minimum">
- <double>-1000.000000000000000</double>
- </property>
- <property name="maximum">
- <double>1000.000000000000000</double>
- </property>
- <property name="singleStep">
- <double>0.000000000000000</double>
- </property>
- </widget>
- <widget class="QDoubleSpinBox" name="doubleSpinBox_4">
- <property name="geometry">
- <rect>
- <x>130</x>
- <y>220</y>
- <width>171</width>
- <height>22</height>
- </rect>
- </property>
- <property name="frame">
- <bool>true</bool>
- </property>
- <property name="buttonSymbols">
- <enum>QAbstractSpinBox::NoButtons</enum>
- </property>
- <property name="decimals">
- <number>24</number>
- </property>
- <property name="minimum">
- <double>-1000.000000000000000</double>
- </property>
- <property name="maximum">
- <double>1000.000000000000000</double>
- </property>
- <property name="singleStep">
- <double>0.000000000000000</double>
- </property>
- </widget>
- <widget class="QDoubleSpinBox" name="doubleSpinBox_5">
- <property name="geometry">
- <rect>
- <x>130</x>
- <y>250</y>
- <width>171</width>
- <height>22</height>
- </rect>
- </property>
- <property name="frame">
- <bool>true</bool>
- </property>
- <property name="buttonSymbols">
- <enum>QAbstractSpinBox::NoButtons</enum>
- </property>
- <property name="decimals">
- <number>24</number>
- </property>
- <property name="minimum">
- <double>-1000.000000000000000</double>
- </property>
- <property name="maximum">
- <double>1000.000000000000000</double>
- </property>
- <property name="singleStep">
- <double>0.000000000000000</double>
- </property>
- </widget>
- <widget class="QLabel" name="label_6">
- <property name="geometry">
- <rect>
- <x>325</x>
- <y>133</y>
- <width>253</width>
- <height>60</height>
- </rect>
- </property>
- <property name="text">
- <string>The ARUCO Library has been developed by
-the Ava group of the Univeristy of Cordoba(Spain)
-Contact to
-Rafael Muñoz Salinas &lt;rmsalinas@uco.es&gt;</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
- </property>
- </widget>
- <widget class="QLineEdit" name="lineEdit">
- <property name="geometry">
- <rect>
- <x>370</x>
- <y>200</y>
- <width>181</width>
- <height>20</height>
- </rect>
- </property>
- <property name="text">
- <string>https://github.com/rmsalinas/aruco</string>
- </property>
- <property name="readOnly">
- <bool>true</bool>
- </property>
- </widget>
+ <item row="6" column="2" rowspan="5" colspan="3">
+ <widget class="QLabel" name="label_6">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The ARUCO Library has been developed by the Ava group of the Univeristy of Cordoba, Spain&lt;/p&gt;&lt;p&gt;Rafael Muñoz Salinas &amp;lt;&lt;a href=&quot;mailto:rmsalinas@uco.es&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0057ae;&quot;&gt;rmsalinas@uco.es&lt;/span&gt;&lt;/a&gt;&amp;gt;&lt;/p&gt;&lt;p&gt;&amp;lt;&lt;a href=&quot;https://github.com/rmsalinas/aruco&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0057ae;&quot;&gt;https://github.com/rmsalinas/aruco&lt;/span&gt;&lt;/a&gt;&amp;gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::RichText</enum>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ <property name="margin">
+ <number>4</number>
+ </property>
+ <property name="openExternalLinks">
+ <bool>true</bool>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
+ </widget>
+ </item>
+ <item row="7" column="0">
+ <widget class="QLabel" name="label_10">
+ <property name="text">
+ <string>Red channel only</string>
+ </property>
+ </widget>
+ </item>
+ <item row="6" column="1">
+ <widget class="QComboBox" name="resolution">
+ <item>
+ <property name="text">
+ <string>640x480</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>320x240</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>320x200</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Default (not recommended!)</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="0" column="0">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Horizontal FOV</string>
+ </property>
+ </widget>
+ </item>
+ <item row="11" column="4">
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ <item row="8" column="1">
+ <widget class="QDoubleSpinBox" name="marker_pitch">
+ <property name="minimum">
+ <double>-180.000000000000000</double>
+ </property>
+ <property name="maximum">
+ <double>180.000000000000000</double>
+ </property>
+ </widget>
+ </item>
+ <item row="6" column="0">
+ <widget class="QLabel" name="label_4">
+ <property name="text">
+ <string>Resolution</string>
+ </property>
+ </widget>
+ </item>
+ <item row="8" column="0">
+ <widget class="QLabel" name="label_9">
+ <property name="text">
+ <string>Marker pitch</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
</widget>
+ <tabstops>
+ <tabstop>cameraFOV</tabstop>
+ <tabstop>cameraFPS</tabstop>
+ <tabstop>cameraName</tabstop>
+ <tabstop>resolution</tabstop>
+ <tabstop>red_only</tabstop>
+ <tabstop>marker_pitch</tabstop>
+ <tabstop>cx</tabstop>
+ <tabstop>cy</tabstop>
+ <tabstop>cz</tabstop>
+ <tabstop>rx</tabstop>
+ <tabstop>ry</tabstop>
+ <tabstop>rz</tabstop>
+ <tabstop>tx</tabstop>
+ <tabstop>ty</tabstop>
+ <tabstop>tz</tabstop>
+ <tabstop>buttonBox</tabstop>
+ </tabstops>
<resources/>
<connections/>
<designerdata>
diff --git a/ftnoir_tracker_aruco/ftnoir_tracker_aruco.cpp b/ftnoir_tracker_aruco/ftnoir_tracker_aruco.cpp
index 152c1e32..ae7ca0b5 100644
--- a/ftnoir_tracker_aruco/ftnoir_tracker_aruco.cpp
+++ b/ftnoir_tracker_aruco/ftnoir_tracker_aruco.cpp
@@ -15,17 +15,21 @@
#include <opencv2/opencv.hpp>
#include <opencv/highgui.h>
#include <vector>
+#include <cstdio>
-#if defined(_WIN32) || defined(__WIN32)
-#include <dshow.h>
+#if defined(_WIN32)
+# undef NOMINMAX
+# define NOMINMAX
+# define NO_DSHOW_STRSAFE
+# include <dshow.h>
#else
-#include <unistd.h>
+# include <unistd.h>
#endif
// delicious copypasta
static QList<QString> get_camera_names(void) {
QList<QString> ret;
-#if defined(_WIN32) || defined(__WIN32)
+#if defined(_WIN32)
// Create the System Device Enumerator.
HRESULT hr;
ICreateDevEnum *pSysDevEnum = NULL;
@@ -78,7 +82,7 @@ static QList<QString> get_camera_names(void) {
if (access(buf, R_OK | W_OK) == 0) {
ret.append(buf);
} else {
- break;
+ continue;
}
}
#endif
@@ -97,55 +101,27 @@ static resolution_tuple resolution_choices[] = {
{ 0, 0 }
};
-void Tracker::load_settings()
+Tracker::Tracker() : stop(false), layout(nullptr), videoWidget(nullptr)
{
- QSettings settings("opentrack");
- QString currentFile = settings.value( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString();
- QSettings iniFile( currentFile, QSettings::IniFormat );
-
- iniFile.beginGroup( "aruco-Tracker" );
- fov = iniFile.value("fov", 56).toFloat();
- force_fps = iniFile.value("fps", 0).toInt();
- camera_index = iniFile.value("camera-index", -1).toInt();
- int res = iniFile.value("resolution", 0).toInt();
- if (res < 0 || res >= (int)(sizeof(resolution_choices) / sizeof(resolution_tuple)))
- res = 0;
- resolution_tuple r = resolution_choices[res];
- force_width = r.width;
- force_height = r.height;
- enableRX = iniFile.value("enable-rx", true).toBool();
- enableRY = iniFile.value("enable-ry", true).toBool();
- enableRZ = iniFile.value("enable-rz", true).toBool();
- enableTX = iniFile.value("enable-tx", true).toBool();
- enableTY = iniFile.value("enable-ty", true).toBool();
- enableTZ = iniFile.value("enable-tz", true).toBool();
- for (int i = 0; i < 5; i++)
- dc[i] = iniFile.value(QString("dc%1").arg(i), 0).toFloat();
- iniFile.endGroup();
-}
-
-Tracker::Tracker()
-{
- fresh = false;
- stop = false;
- videoWidget = NULL;
- layout = NULL;
- enableRX = enableRY = enableRZ = enableTX = enableTY = enableTZ = true;
- load_settings();
}
Tracker::~Tracker()
{
- if (layout)
- delete layout;
+ stop = true;
+ wait();
if (videoWidget)
delete videoWidget;
+ if(layout)
+ delete layout;
+ qDebug() << "releasing camera, brace for impact";
+ camera.release();
+ qDebug() << "all done!";
}
void Tracker::StartTracker(QFrame* videoframe)
{
videoframe->show();
- videoWidget = new VideoWidget(videoframe);
+ videoWidget = new ArucoVideoWidget(videoframe);
QHBoxLayout* layout = new QHBoxLayout();
layout->setContentsMargins(0, 0, 0, 0);
layout->addWidget(videoWidget);
@@ -153,143 +129,263 @@ void Tracker::StartTracker(QFrame* videoframe)
delete videoframe->layout();
videoframe->setLayout(layout);
videoWidget->show();
- this->layout = layout;
- load_settings();
- connect(&timer, SIGNAL(timeout()), this, SLOT(paint_widget()));
- timer.start(50);
start();
for (int i = 0; i < 6; i++)
pose[i] = 0;
-}
-
-void Tracker::paint_widget() {
- if (fresh) {
- fresh = false;
- videoWidget->update();
- }
+ this->layout = layout;
}
#define HT_PI 3.1415926535
void Tracker::run()
{
- cv::VideoCapture camera(camera_index);
-
- if (force_width)
- camera.set(CV_CAP_PROP_FRAME_WIDTH, force_width);
- if (force_height)
- camera.set(CV_CAP_PROP_FRAME_HEIGHT, force_height);
- if (force_fps)
- camera.set(CV_CAP_PROP_FPS, force_fps);
+ int res = s.resolution;
+ if (res < 0 || res >= (int)(sizeof(resolution_choices) / sizeof(resolution_tuple)))
+ res = 0;
+ resolution_tuple r = resolution_choices[res];
+ int fps;
+ switch (static_cast<int>(s.force_fps))
+ {
+ default:
+ case 0:
+ fps = 0;
+ break;
+ case 1:
+ fps = 30;
+ break;
+ case 2:
+ fps = 60;
+ break;
+ case 3:
+ fps = 120;
+ break;
+ case 4:
+ fps = 180;
+ break;
+ }
+ camera = cv::VideoCapture(s.camera_index);
+ if (r.width)
+ {
+ camera.set(CV_CAP_PROP_FRAME_WIDTH, r.width);
+ camera.set(CV_CAP_PROP_FRAME_HEIGHT, r.height);
+ }
+ if (fps)
+ camera.set(CV_CAP_PROP_FPS, fps);
aruco::MarkerDetector detector;
detector.setDesiredSpeed(3);
- detector.setThresholdParams(11, 5);
- cv::Mat color, grayscale, rvec, tvec;
-
+
+ cv::Rect last_roi(65535, 65535, 0, 0);
+
+ cv::Mat color, color_, grayscale, rvec, tvec;
+
+ const double stateful_coeff = 0.88;
+
+ if (!camera.isOpened())
+ {
+ fprintf(stderr, "aruco tracker: can't open camera\n");
+ return;
+ }
+
+ auto freq = cv::getTickFrequency();
+ auto last_time = cv::getTickCount();
+ int cur_fps = 0;
+ int last_fps = 0;
+ cv::Point2f last_centroid;
+ bool first = true;
+
while (!stop)
{
- if (!camera.read(color))
- break;
- cv::cvtColor(color, grayscale, cv::COLOR_BGR2GRAY);
- const float focal_length_w = 0.5 * grayscale.cols / tan(0.5 * fov * HT_PI / 180);
- const float focal_length_h = 0.5 * grayscale.rows / tan(0.5 * fov * grayscale.rows / grayscale.cols * HT_PI / 180.0);
+ if (!camera.read(color_))
+ continue;
+ auto tm = cv::getTickCount();
+ color_.copyTo(color);
+ if (s.red_only)
+ {
+ cv::Mat channel[3];
+ cv::split(color, channel);
+ grayscale = channel[2];
+ } else
+ cv::cvtColor(color, grayscale, cv::COLOR_BGR2GRAY);
+
+ const int scale = frame.cols > 480 ? 2 : 1;
+ detector.setThresholdParams(scale > 1 ? 11 : 7, 4);
+
+ const float focal_length_w = 0.5 * grayscale.cols / tan(0.5 * s.fov * HT_PI / 180);
+ const float focal_length_h = 0.5 * grayscale.rows / tan(0.5 * s.fov * grayscale.rows / grayscale.cols * HT_PI / 180.0);
cv::Mat intrinsics = cv::Mat::eye(3, 3, CV_32FC1);
intrinsics.at<float> (0, 0) = focal_length_w;
intrinsics.at<float> (1, 1) = focal_length_h;
intrinsics.at<float> (0, 2) = grayscale.cols/2;
intrinsics.at<float> (1, 2) = grayscale.rows/2;
-
+
cv::Mat dist_coeffs = cv::Mat::zeros(5, 1, CV_32FC1);
-
- for (int i = 0; i < 5; i++)
- dist_coeffs.at<float>(i) = dc[i];
-
+
std::vector< aruco::Marker > markers;
-
- detector.detect(grayscale, markers, cv::Mat(), cv::Mat(), -1, false);
-
+
+ const double size_min = 0.04;
+ const double size_max = 0.38;
+
+ if (last_roi.width > 0 &&
+ (detector.detect(grayscale(last_roi), markers, cv::Mat(), cv::Mat(), -1, false),
+ markers.size() == 1 && markers[0].size() == 4))
+ {
+ detector.setMinMaxSize(std::max(0.01, size_min * grayscale.cols / last_roi.width),
+ std::min(1.0, size_max * grayscale.cols / last_roi.width));
+ auto& m = markers.at(0);
+ for (int i = 0; i < 4; i++)
+ {
+ auto& p = m.at(i);
+ p.x += last_roi.x;
+ p.y += last_roi.y;
+ }
+ }
+ else
+ {
+ detector.setMinMaxSize(size_min, size_max);
+ detector.detect(grayscale, markers, cv::Mat(), cv::Mat(), -1, false);
+ }
+
if (markers.size() == 1 && markers[0].size() == 4) {
- const aruco::Marker& m = markers.at(0);
+ const auto& m = markers.at(0);
for (int i = 0; i < 4; i++)
- cv::line(color, m[i], m[(i+1)%4], cv::Scalar(0, 0, 255), 4);
+ cv::line(color, m[i], m[(i+1)%4], cv::Scalar(0, 0, 255), scale, 8);
}
-
- frame = color;
-
- if (frame.rows > 0 && !fresh)
+
+ auto time = cv::getTickCount();
+
+ if ((long) (time / freq) != (long) (last_time / freq))
{
- videoWidget->update_image(frame.data, frame.cols, frame.rows);
- fresh = true;
+ last_fps = cur_fps;
+ cur_fps = 0;
+ last_time = time;
}
+
+ cur_fps++;
+
+ char buf[128];
+
+ frame = color.clone();
+
+ ::sprintf(buf, "Hz: %d", last_fps);
+ cv::putText(frame, buf, cv::Point(10, 32), cv::FONT_HERSHEY_PLAIN, scale, cv::Scalar(0, 255, 0), scale);
+ ::sprintf(buf, "Jiffies: %ld", (long) (10000 * (time - tm) / freq));
+ cv::putText(frame, buf, cv::Point(10, 54), cv::FONT_HERSHEY_PLAIN, scale, cv::Scalar(80, 255, 0), scale);
if (markers.size() == 1 && markers[0].size() == 4) {
- const aruco::Marker& m = markers.at(0);
- const float size = 7;
+ const auto& m = markers.at(0);
+ const float size = 40;
+ const double p = s.marker_pitch;
+ const double sq = sin(p * HT_PI / 180);
+ const double cq = cos(p * HT_PI / 180);
+
cv::Mat obj_points(4,3,CV_32FC1);
- obj_points.at<float>(1,0)=-size;
- obj_points.at<float>(1,1)=-size;
- obj_points.at<float>(1,2)=0;
- obj_points.at<float>(2,0)=size;
- obj_points.at<float>(2,1)=-size;
- obj_points.at<float>(2,2)=0;
- obj_points.at<float>(3,0)=size;
- obj_points.at<float>(3,1)=size;
- obj_points.at<float>(3,2)=0;
- obj_points.at<float>(0,0)=-size;
- obj_points.at<float>(0,1)=size;
- obj_points.at<float>(0,2)=0;
-
- cv::solvePnP(obj_points, m, intrinsics, dist_coeffs, rvec, tvec, false, cv::ITERATIVE);
-
+ obj_points.at<float>(1,0)=-size + s.headpos_x;
+ obj_points.at<float>(1,1)=-size * cq + s.headpos_y;
+ obj_points.at<float>(1,2)=-size * sq + s.headpos_z;
+ obj_points.at<float>(2,0)=size + s.headpos_x;
+ obj_points.at<float>(2,1)=-size * cq + s.headpos_y;
+ obj_points.at<float>(2,2)=-size * sq + s.headpos_z;
+ obj_points.at<float>(3,0)=size + s.headpos_x;
+ obj_points.at<float>(3,1)=size * cq + s.headpos_y;
+ obj_points.at<float>(3,2)=size * sq + s.headpos_z;
+ obj_points.at<float>(0,0)=-size + s.headpos_x;
+ obj_points.at<float>(0,1)=size * cq + s.headpos_y;
+ obj_points.at<float>(0,2)=size * sq + s.headpos_z;
+
+ last_roi = cv::Rect(65535, 65535, 0, 0);
+
+ for (int i = 0; i < 4; i++)
+ {
+ auto foo = m.at(i);
+ last_roi.x = std::min<int>(foo.x, last_roi.x);
+ last_roi.y = std::min<int>(foo.y, last_roi.y);
+ last_roi.width = std::max<int>(foo.x, last_roi.width);
+ last_roi.height = std::max<int>(foo.y, last_roi.height);
+ }
+ {
+ last_roi.width -= last_roi.x;
+ last_roi.height -= last_roi.y;
+ last_roi.x -= last_roi.width * stateful_coeff;
+ last_roi.y -= last_roi.height * stateful_coeff;
+ last_roi.width *= stateful_coeff * 3;
+ last_roi.height *= stateful_coeff * 3;
+ last_roi.x = std::max<int>(0, last_roi.x);
+ last_roi.y = std::max<int>(0, last_roi.y);
+ last_roi.width = std::min<int>(grayscale.cols - last_roi.x, last_roi.width);
+ last_roi.height = std::min<int>(grayscale.rows - last_roi.y, last_roi.height);
+ }
+
+ cv::solvePnP(obj_points, m, intrinsics, dist_coeffs, rvec, tvec, !first, cv::ITERATIVE);
+ first = false;
cv::Mat rotation_matrix = cv::Mat::zeros(3, 3, CV_64FC1);
-
cv::Mat junk1(3, 3, CV_64FC1), junk2(3, 3, CV_64FC1);
-
cv::Rodrigues(rvec, rotation_matrix);
-
- cv::Vec3d foo = cv::RQDecomp3x3(rotation_matrix, junk1, junk2);
-
- QMutexLocker lck(&mtx);
-
- for (int i = 0; i < 3; i++)
- pose[i] = tvec.at<double>(i);
-
- pose[Yaw] = foo[1];
- pose[Pitch] = -foo[0];
- pose[Roll] = foo[2];
-
- pose[Yaw] -= atan(pose[TX] / pose[TZ]) * 180 / HT_PI;
- pose[Pitch] -= atan(pose[TY] / pose[TZ]) * 180 / HT_PI;
+
+ {
+ cv::Vec3d euler = cv::RQDecomp3x3(rotation_matrix, junk1, junk2);
+
+ if (fabs(euler[0]) + fabs(s.marker_pitch) > 60)
+ {
+ first = true;
+ qDebug() << "reset levmarq due to pitch breakage";
+ }
+
+ QMutexLocker lck(&mtx);
+
+ for (int i = 0; i < 3; i++)
+ pose[i] = tvec.at<double>(i);
+
+ pose[Yaw] = euler[1];
+ pose[Pitch] = -euler[0];
+ pose[Roll] = euler[2];
+ }
+
+ std::vector<cv::Point2f> repr2;
+ std::vector<cv::Point3f> centroid;
+ centroid.push_back(cv::Point3f(0, 0, 0));
+ cv::projectPoints(centroid, rvec, tvec, intrinsics, dist_coeffs, repr2);
+
+ {
+ auto s = cv::Scalar(255, 0, 255);
+ cv::circle(frame, repr2.at(0), 4, s, -1);
+ }
+
+ last_centroid = repr2[0];
+ }
+ else
+ {
+ last_roi = cv::Rect(65535, 65535, 0, 0);
+ first = true;
}
+
+ if (frame.rows > 0)
+ videoWidget->update_image(frame);
}
}
-bool Tracker::GiveHeadPoseData(double *data)
+void Tracker::GetHeadPoseData(double *data)
{
QMutexLocker lck(&mtx);
- if (enableRX)
+ if (s.eyaw)
data[Yaw] = pose[Yaw];
- if (enableRY)
+ if (s.epitch)
data[Pitch] = pose[Pitch];
- if (enableRZ)
+ if (s.eroll)
data[Roll] = pose[Roll];
- if (enableTX)
- data[TX] = pose[TX];
- if (enableTY)
- data[TY] = pose[TY];
- if (enableTZ)
- data[TZ] = pose[TZ];
-
- return true;
+ if (s.ex)
+ data[TX] = pose[TX] * .1;
+ if (s.ey)
+ data[TY] = pose[TY] * .1;
+ if (s.ez)
+ data[TZ] = pose[TZ] * .1;
}
class TrackerDll : public Metadata
{
// ITrackerDll interface
- void Initialize() {}
void getFullName(QString *strToBeFilled);
void getShortName(QString *strToBeFilled);
void getDescription(QString *strToBeFilled);
@@ -349,163 +445,39 @@ extern "C" FTNOIR_TRACKER_BASE_EXPORT ITrackerDialog* CALLING_CONVENTION GetDial
TrackerControls::TrackerControls()
{
+ tracker = nullptr;
ui.setupUi(this);
setAttribute(Qt::WA_NativeWindow, true);
- connect(ui.cameraName, SIGNAL(currentIndexChanged(int)), this, SLOT(settingChanged(int)));
- connect(ui.cameraFPS, SIGNAL(currentIndexChanged(int)), this, SLOT(settingChanged(int)));
- connect(ui.cameraFOV, SIGNAL(valueChanged(double)), this, SLOT(settingChanged(double)));
- connect(ui.rx, SIGNAL(stateChanged(int)), this, SLOT(settingChanged(int)));
- connect(ui.ry, SIGNAL(stateChanged(int)), this, SLOT(settingChanged(int)));
- connect(ui.rz, SIGNAL(stateChanged(int)), this, SLOT(settingChanged(int)));
- connect(ui.tx, SIGNAL(stateChanged(int)), this, SLOT(settingChanged(int)));
- connect(ui.ty, SIGNAL(stateChanged(int)), this, SLOT(settingChanged(int)));
- connect(ui.tz, SIGNAL(stateChanged(int)), this, SLOT(settingChanged(int)));
- connect(ui.buttonCancel, SIGNAL(clicked()), this, SLOT(doCancel()));
- connect(ui.buttonOK, SIGNAL(clicked()), this, SLOT(doOK()));
- //connect(ui.buttonSettings, SIGNAL(clicked()), this, SLOT(cameraSettings()));
- loadSettings();
- settingsDirty = false;
-}
-
-TrackerControls::~TrackerControls()
-{
-}
-
-void TrackerControls::showEvent(QShowEvent *event)
-{
-}
-
-void TrackerControls::Initialize(QWidget* parent)
-{
- loadSettings();
- show();
-}
-
-void TrackerControls::loadSettings()
-{
- ui.cameraName->clear();
- QList<QString> names = get_camera_names();
- names.prepend("Any available");
- ui.cameraName->addItems(names);
- QSettings settings("opentrack");
- QString currentFile = settings.value( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString();
- QSettings iniFile( currentFile, QSettings::IniFormat );
- iniFile.beginGroup( "aruco-Tracker" );
- ui.cameraName->setCurrentIndex(iniFile.value("camera-index", -1).toInt() + 1);
- ui.cameraFOV->setValue(iniFile.value("fov", 56).toFloat());
- int fps;
- switch (iniFile.value("fps", 0).toInt())
- {
- default:
- case 0:
- fps = 0;
- break;
- case 30:
- fps = 1;
- break;
- case 60:
- fps = 2;
- break;
- case 120:
- fps = 3;
- break;
- }
- ui.cameraFPS->setCurrentIndex(fps);
- ui.rx->setCheckState(iniFile.value("enable-rx", true).toBool() ? Qt::Checked : Qt::Unchecked);
- ui.ry->setCheckState(iniFile.value("enable-ry", true).toBool() ? Qt::Checked : Qt::Unchecked);
- ui.rz->setCheckState(iniFile.value("enable-rz", true).toBool() ? Qt::Checked : Qt::Unchecked);
- ui.tx->setCheckState(iniFile.value("enable-tx", true).toBool() ? Qt::Checked : Qt::Unchecked);
- ui.ty->setCheckState(iniFile.value("enable-ty", true).toBool() ? Qt::Checked : Qt::Unchecked);
- ui.tz->setCheckState(iniFile.value("enable-tz", true).toBool() ? Qt::Checked : Qt::Unchecked);
- ui.resolution->setCurrentIndex(iniFile.value("resolution", 0).toInt());
-
- ui.doubleSpinBox->setValue(iniFile.value("dc0").toDouble());
- ui.doubleSpinBox_2->setValue(iniFile.value("dc1").toDouble());
- ui.doubleSpinBox_3->setValue(iniFile.value("dc2").toDouble());
- ui.doubleSpinBox_4->setValue(iniFile.value("dc3").toDouble());
- ui.doubleSpinBox_5->setValue(iniFile.value("dc4").toDouble());
-
- iniFile.endGroup();
- settingsDirty = false;
-}
-
-void TrackerControls::save()
-{
- QSettings settings("opentrack");
- QString currentFile = settings.value( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString();
- QSettings iniFile( currentFile, QSettings::IniFormat );
-
- iniFile.beginGroup( "aruco-Tracker" );
- iniFile.setValue("fov", ui.cameraFOV->value());
- int fps;
- switch (ui.cameraFPS->currentIndex())
- {
- case 0:
- default:
- fps = 0;
- break;
- case 1:
- fps = 30;
- break;
- case 2:
- fps = 60;
- break;
- case 3:
- fps = 120;
- break;
- }
- iniFile.setValue("fps", fps);
- iniFile.setValue("camera-index", ui.cameraName->currentIndex() - 1);
- iniFile.setValue("enable-rx", ui.rx->checkState() != Qt::Unchecked ? true : false);
- iniFile.setValue("enable-ry", ui.ry->checkState() != Qt::Unchecked ? true : false);
- iniFile.setValue("enable-rz", ui.rz->checkState() != Qt::Unchecked ? true : false);
- iniFile.setValue("enable-tx", ui.tx->checkState() != Qt::Unchecked ? true : false);
- iniFile.setValue("enable-ty", ui.ty->checkState() != Qt::Unchecked ? true : false);
- iniFile.setValue("enable-tz", ui.tz->checkState() != Qt::Unchecked ? true : false);
- iniFile.setValue("resolution", ui.resolution->currentIndex());
-
- iniFile.setValue("dc0", ui.doubleSpinBox->value());
- iniFile.setValue("dc1", ui.doubleSpinBox_2->value());
- iniFile.setValue("dc2", ui.doubleSpinBox_3->value());
- iniFile.setValue("dc3", ui.doubleSpinBox_4->value());
- iniFile.setValue("dc4", ui.doubleSpinBox_5->value());
-
- iniFile.endGroup();
- settingsDirty = false;
+ tie_setting(s.camera_index, ui.cameraName);
+ tie_setting(s.resolution, ui.resolution);
+ tie_setting(s.force_fps, ui.cameraFPS);
+ tie_setting(s.fov, ui.cameraFOV);
+ tie_setting(s.eyaw, ui.rx);
+ tie_setting(s.epitch, ui.ry);
+ tie_setting(s.eroll, ui.rz);
+ tie_setting(s.ex, ui.tx);
+ tie_setting(s.ey, ui.ty);
+ tie_setting(s.ez, ui.tz);
+ tie_setting(s.headpos_x, ui.cx);
+ tie_setting(s.headpos_y, ui.cy);
+ tie_setting(s.headpos_z, ui.cz);
+ tie_setting(s.red_only, ui.red_only);
+ tie_setting(s.marker_pitch, ui.marker_pitch);
+ connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK()));
+ connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel()));
+ ui.cameraName->addItems(get_camera_names());
}
void TrackerControls::doOK()
{
- save();
+ s.b->save();
+ if (tracker)
+ tracker->reload();
this->close();
}
void TrackerControls::doCancel()
{
- if (settingsDirty) {
- 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:
- save();
- this->close();
- break;
- case QMessageBox::Discard:
- this->close();
- break;
- case QMessageBox::Cancel:
- // Cancel was clicked
- break;
- default:
- // should never be reached
- break;
- }
- }
- else {
- this->close();
- }
+ s.b->revert();
+ this->close();
}
diff --git a/ftnoir_tracker_aruco/ftnoir_tracker_aruco.h b/ftnoir_tracker_aruco/ftnoir_tracker_aruco.h
index 7f21f020..4cab84b5 100644
--- a/ftnoir_tracker_aruco/ftnoir_tracker_aruco.h
+++ b/ftnoir_tracker_aruco/ftnoir_tracker_aruco.h
@@ -10,46 +10,63 @@
#include "ftnoir_tracker_base/ftnoir_tracker_base.h"
#include "ui_aruco-trackercontrols.h"
-#include "video_widget.h"
+#include "ar_video_widget.h"
#include <QObject>
-#include <QTimer>
#include <QThread>
#include <QMutex>
#include <QHBoxLayout>
+#include <QDialog>
#include <opencv2/opencv.hpp>
+#include <opencv/highgui.h>
+#include "facetracknoir/options.h"
+using namespace options;
-class Tracker : public QThread, public ITracker
+struct settings {
+ pbundle b;
+ value<double> fov, headpos_x, headpos_y, headpos_z;
+ value<int> camera_index, force_fps, resolution;
+ value<bool> red_only;
+ value<bool> eyaw, epitch, eroll, ex, ey, ez;
+ value<double> marker_pitch;
+ settings() :
+ b(bundle("aruco-tracker")),
+ fov(b, "field-of-view", 56),
+ headpos_x(b, "headpos-x", 0),
+ headpos_y(b, "headpos-y", 0),
+ headpos_z(b, "headpos-z", 0),
+ camera_index(b, "camera-index", 0),
+ force_fps(b, "force-fps", 0),
+ resolution(b, "force-resolution", 0),
+ red_only(b, "red-only", false),
+ eyaw(b, "enable-y", true),
+ epitch(b, "enable-p", true),
+ eroll(b, "enable-r", true),
+ ex(b, "enable-x", true),
+ ey(b, "enable-y", true),
+ ez(b, "enable-z", true),
+ marker_pitch(b, "marker-pitch", 0)
+ {}
+};
+
+class Tracker : protected QThread, public ITracker
{
Q_OBJECT
public:
Tracker();
- ~Tracker();
+ virtual ~Tracker();
void StartTracker(QFrame* frame);
- bool GiveHeadPoseData(double *data);
- bool enableTX, enableTY, enableTZ, enableRX, enableRY, enableRZ;
- bool NeedsTimeToFinish() {
- return true;
- }
- void WaitForExit() {
- stop = true;
- wait();
- }
+ void GetHeadPoseData(double *data);
void run();
+ void reload() { s.b->reload(); }
private:
QMutex mtx;
- QTimer timer;
- VideoWidget* videoWidget;
- QHBoxLayout* layout;
- volatile bool fresh, stop;
- float fov;
- int camera_index;
- float dc[5];
- int force_fps, force_width, force_height;
- void load_settings();
+ volatile bool stop;
+ QHBoxLayout* layout;
+ ArucoVideoWidget* videoWidget;
+ settings s;
double pose[6];
cv::Mat frame;
-private slots:
- void paint_widget();
+ cv::VideoCapture camera;
};
// Widget that has controls for FTNoIR protocol client-settings.
@@ -57,27 +74,20 @@ class TrackerControls : public QWidget, public ITrackerDialog
{
Q_OBJECT
public:
-
- explicit TrackerControls();
- virtual ~TrackerControls();
- void showEvent ( QShowEvent * event );
-
- void Initialize(QWidget *parent);
- void registerTracker(ITracker *tracker) {}
- void unRegisterTracker() {}
-
+ TrackerControls();
+ void registerTracker(ITracker * x) {
+ tracker = dynamic_cast<Tracker*>(x);
+ }
+ void unRegisterTracker() {
+ tracker = nullptr;
+ }
private:
Ui::Form ui;
- void loadSettings();
- void save();
- bool settingsDirty;
-
+ Tracker* tracker;
+ settings s;
private slots:
void doOK();
void doCancel();
- void settingChanged() { settingsDirty = true; }
- void settingChanged(int) { settingsDirty = true; }
- void settingChanged(double) { settingsDirty = true; }
};
#endif
diff --git a/ftnoir_tracker_aruco/ftnoir_tracker_aruco_dll.h b/ftnoir_tracker_aruco/ftnoir_tracker_aruco_dll.h
index 1e53f802..ffdc5262 100644
--- a/ftnoir_tracker_aruco/ftnoir_tracker_aruco_dll.h
+++ b/ftnoir_tracker_aruco/ftnoir_tracker_aruco_dll.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013 Stanis³aw Halik <sthalik@misaki.pl>
+/* Copyright (c) 2013 Stanisław Halik <sthalik@misaki.pl>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -12,7 +12,6 @@
class TrackerDll : public Metadata
{
// ITrackerDll interface
- void Initialize() {}
void getFullName(QString *strToBeFilled);
void getShortName(QString *strToBeFilled);
void getDescription(QString *strToBeFilled);
diff --git a/ftnoir_tracker_aruco/include/boarddetector.h b/ftnoir_tracker_aruco/include/boarddetector.h
index a0ee2361..4770b5c9 100644
--- a/ftnoir_tracker_aruco/include/boarddetector.h
+++ b/ftnoir_tracker_aruco/include/boarddetector.h
@@ -134,6 +134,6 @@ private:
};
-};
+}
#endif
diff --git a/ftnoir_tracker_aruco/include/cvdrawingutils.h b/ftnoir_tracker_aruco/include/cvdrawingutils.h
index ff67242f..38e9986e 100644
--- a/ftnoir_tracker_aruco/include/cvdrawingutils.h
+++ b/ftnoir_tracker_aruco/include/cvdrawingutils.h
@@ -46,7 +46,7 @@ namespace aruco
static void draw3dCube(cv::Mat &Image,Board &m,const CameraParameters &CP);
};
-};
+}
#endif
diff --git a/ftnoir_tracker_aruco/include/markerdetector.h b/ftnoir_tracker_aruco/include/markerdetector.h
index 35369cea..4d6e7b90 100644
--- a/ftnoir_tracker_aruco/include/markerdetector.h
+++ b/ftnoir_tracker_aruco/include/markerdetector.h
@@ -52,10 +52,13 @@ class ARUCO_EXPORTS MarkerDetector
contour=M.contour;
idx=M.idx;
}
- MarkerCandidate & operator=(const MarkerCandidate &M){
+ MarkerCandidate operator=(const MarkerCandidate &M){
+ if (this == &M)
+ return *this;
(*(Marker*)this)=(*(Marker*)&M);
contour=M.contour;
idx=M.idx;
+ return M;
}
vector<cv::Point> contour;//all the points of its contour
@@ -350,9 +353,5 @@ private:
void draw(cv::Mat out,const std::vector<Marker> &markers );
};
-
-
-
-
-};
+}
#endif
diff --git a/ftnoir_tracker_aruco/video_widget.cpp b/ftnoir_tracker_aruco/video_widget.cpp
deleted file mode 100644
index 84cba6a3..00000000
--- a/ftnoir_tracker_aruco/video_widget.cpp
+++ /dev/null
@@ -1,30 +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 std;
-
-void VideoWidget::update_image(unsigned char *frame, int width, int height)
-{
- QMutexLocker foo(&mtx);
- QImage qframe = QImage(width, height, QImage::Format_RGB888);
- 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] = frame[pos + 2];
- data[y * pitch + x * 3 + 1] = frame[pos + 1];
- data[y * pitch + x * 3 + 2] = frame[pos + 0];
- }
- qframe = qframe.scaled(size(), Qt::IgnoreAspectRatio, Qt::FastTransformation);
- pixmap = QPixmap::fromImage(qframe);
-}