diff options
Diffstat (limited to 'tracker-pt')
-rw-r--r-- | tracker-pt/camera.cpp | 128 | ||||
-rw-r--r-- | tracker-pt/camera.h | 85 | ||||
-rw-r--r-- | tracker-pt/ftnoir_tracker_pt.cpp | 56 | ||||
-rw-r--r-- | tracker-pt/ftnoir_tracker_pt.h | 8 | ||||
-rw-r--r-- | tracker-pt/ftnoir_tracker_pt_dialog.cpp | 10 | ||||
-rw-r--r-- | tracker-pt/lang/ru_RU.ts | 294 |
6 files changed, 405 insertions, 176 deletions
diff --git a/tracker-pt/camera.cpp b/tracker-pt/camera.cpp index 82f4a6fe..60eb4bb8 100644 --- a/tracker-pt/camera.cpp +++ b/tracker-pt/camera.cpp @@ -6,60 +6,23 @@ */ #include "camera.h" -#include "compat/camera-names.hpp" #include <string> #include <QDebug> -Camera::~Camera() {} - -void Camera::set_device(const QString& name) -{ - const int index = camera_name_to_index(name); - - desired_name = name; - - if (desired_index != index) - { - desired_index = index; - _set_device_index(); - - // reset fps - dt_valid = 0; - dt_mean = 0; - active_index = index; - } -} - QString Camera::get_desired_name() const { return desired_name; } -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) +QString Camera::get_active_name() const { - 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(); - } + return active_name; } DEFUN_WARN_UNUSED bool Camera::get_info(CamInfo& ret) { if (cam_info.res_x == 0 || cam_info.res_y == 0) - { return false; - } ret = cam_info; return true; } @@ -68,7 +31,7 @@ bool Camera::get_frame(double dt, cv::Mat* frame) { bool new_frame = _get_frame(frame); // measure fps of valid frames - static constexpr double RC = 1; // second + static constexpr double RC = .1; // seconds const double alpha = dt/(dt + RC); dt_valid += dt; if (new_frame) @@ -76,8 +39,8 @@ bool Camera::get_frame(double dt, cv::Mat* frame) if (dt_mean < 2e-3) dt_mean = dt; else - dt_mean = alpha * dt_mean + (1 - alpha) * dt_valid; - cam_info.fps = int(std::round(dt_mean > 2e-3 ? 1 / dt_mean : 0)); + dt_mean = (1-alpha) * dt_mean + alpha * dt_valid; + cam_info.fps = dt_mean > 2e-3 ? int(1 / dt_mean + .65) : 0; dt_valid = 0; } else @@ -85,40 +48,52 @@ bool Camera::get_frame(double dt, cv::Mat* frame) return new_frame; } -void CVCamera::start() +DEFUN_WARN_UNUSED bool Camera::start(int idx, int fps, int res_x, int res_y) { - stop(); - cap = new cv::VideoCapture(desired_index); - _set_res(); - _set_fps(); - // extract camera info - if (cap->isOpened()) + if (idx >= 0 && fps >= 0 && res_x > 0 && res_y > 0) { - active_index = desired_index; - cam_info.res_x = 0; - cam_info.res_y = 0; - } else { - stop(); + if (!cap || cap->isOpened() || + cam_desired.idx != idx || + cam_desired.fps != fps || + cam_desired.res_x != res_x || + cam_desired.res_y != res_y) + { + cam_desired.idx = idx; + cam_desired.fps = fps; + cam_desired.res_x = res_x; + cam_desired.res_y = res_y; + + cap = camera_ptr(new cv::VideoCapture(cam_desired.idx)); + + cap->set(cv::CAP_PROP_FRAME_WIDTH, cam_desired.res_x); + cap->set(cv::CAP_PROP_FRAME_HEIGHT, cam_desired.res_y); + cap->set(cv::CAP_PROP_FPS, cam_desired.fps); + + if (cap->isOpened()) + { + cam_info.idx = cam_desired.idx; + cam_info.res_x = 0; + cam_info.res_y = 0; + active_name = desired_name; + + return true; + } + } } + + return stop(), false; } -void CVCamera::stop() +void Camera::stop() { - if (cap) - { - const bool opened = cap->isOpened(); - if (opened) - { - qDebug() << "pt: freeing camera"; - cap->release(); - } - delete cap; - cap = nullptr; - qDebug() << "pt camera: stopped"; - } + cap = nullptr; + desired_name = QString(); + active_name = QString(); + cam_info = CamInfo(); + cam_desired = CamInfo(); } -bool CVCamera::_get_frame(cv::Mat* frame) +bool Camera::_get_frame(cv::Mat* frame) { if (cap && cap->isOpened()) { @@ -135,21 +110,12 @@ bool CVCamera::_get_frame(cv::Mat* frame) return false; } -void CVCamera::_set_fps() -{ - if (cap) cap->set(cv::CAP_PROP_FPS, cam_desired.fps); -} - -void CVCamera::_set_res() +void Camera::camera_deleter::operator()(cv::VideoCapture* cap) { if (cap) { - cap->set(cv::CAP_PROP_FRAME_WIDTH, cam_desired.res_x); - cap->set(cv::CAP_PROP_FRAME_HEIGHT, cam_desired.res_y); + if (cap->isOpened()) + cap->release(); + std::default_delete<cv::VideoCapture>()(cap); } } -void CVCamera::_set_device_index() -{ - if (desired_index != active_index) - stop(); -} diff --git a/tracker-pt/camera.h b/tracker-pt/camera.h index be7d35c4..3f5a8f43 100644 --- a/tracker-pt/camera.h +++ b/tracker-pt/camera.h @@ -7,6 +7,9 @@ #pragma once +#undef NDEBUG +#include <cassert> + #include "compat/util.hpp" #include <opencv2/core/core.hpp> @@ -17,81 +20,51 @@ struct CamInfo { - CamInfo() : res_x(0), res_y(0), fps(0) {} + CamInfo() : res_x(0), res_y(0), fps(-1), idx(-1) {} int res_x; int res_y; int fps; + int idx; }; -// ---------------------------------------------------------------------------- -// Base class for cameras, calculates the frame rate -class Camera +class Camera final { public: - Camera() : dt_valid(0), dt_mean(0), desired_index(0), active_index(-1) {} - virtual ~Camera() = 0; - - // start/stop capturing - virtual void start() = 0; - virtual void stop() = 0; - void restart() { stop(); start(); } + Camera() : dt_valid(0), dt_mean(0) {} - // calls corresponding template methods and reinitializes frame rate calculation - void set_device(const QString& name); - void set_fps(int fps); - void set_res(int x_res, int y_res); + DEFUN_WARN_UNUSED bool start(int idx, int fps, int res_x, int res_y); + void stop(); - // gets a frame from the camera, dt: time since last call in seconds DEFUN_WARN_UNUSED bool get_frame(double dt, cv::Mat* frame); - - // WARNING: returned references are valid as long as object DEFUN_WARN_UNUSED bool get_info(CamInfo &ret); + CamInfo get_desired() const { return cam_desired; } QString get_desired_name() const; -protected: - // get a frame from the camera - DEFUN_WARN_UNUSED 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_fps() = 0; - virtual void _set_res() = 0; + QString get_active_name() const; + + cv::VideoCapture& operator*() { assert(cap); return *cap; } + const cv::VideoCapture& operator*() const { assert(cap); return *cap; } + cv::VideoCapture* operator->() { assert(cap); return cap.get(); } + const cv::VideoCapture* operator->() const { return cap.get(); } + operator bool() const { return cap && cap->isOpened(); } + private: + DEFUN_WARN_UNUSED bool _get_frame(cv::Mat* frame); + double dt_valid; double dt_mean; -protected: + CamInfo cam_info; CamInfo cam_desired; - QString desired_name; - int desired_index; - int active_index; -}; + QString desired_name, active_name; -// ---------------------------------------------------------------------------- -// camera based on OpenCV's videoCapture -class CVCamera final : public Camera -{ -public: - CVCamera() : cap(NULL) {} - ~CVCamera() { stop(); } - - void start() override; - void stop() override; - - operator cv::VideoCapture*() { return cap; } -protected: - bool _get_frame(cv::Mat* frame) override; - void _set_fps() override; - void _set_res() override; - void _set_device_index() override; -private: - cv::VideoCapture* cap; -}; + struct camera_deleter final + { + void operator()(cv::VideoCapture* cap); + }; -enum RotationType -{ - CLOCKWISE = 0, - ZERO = 1, - COUNTER_CLOCKWISE = 2 + using camera_ptr = std::unique_ptr<cv::VideoCapture, camera_deleter>; + + camera_ptr cap; }; diff --git a/tracker-pt/ftnoir_tracker_pt.cpp b/tracker-pt/ftnoir_tracker_pt.cpp index d13c5545..40293f56 100644 --- a/tracker-pt/ftnoir_tracker_pt.cpp +++ b/tracker-pt/ftnoir_tracker_pt.cpp @@ -19,8 +19,6 @@ //----------------------------------------------------------------------------- Tracker_PT::Tracker_PT() : - video_widget(nullptr), - video_frame(nullptr), point_count(0), commands(0), ever_success(false) @@ -32,13 +30,7 @@ Tracker_PT::~Tracker_PT() { set_command(ABORT); wait(); - if (video_widget) - delete video_widget; - video_widget = NULL; - if (video_frame) - { - if (video_frame->layout()) delete video_frame->layout(); - } + // fast start/stop causes breakage camera.stop(); } @@ -65,12 +57,21 @@ bool Tracker_PT::get_focal_length(f& ret) using std::tan; using std::atan; using std::sqrt; - +#if 1 const double w = info.res_x, h = info.res_y; const double diag = sqrt(w/h*w/h + h/w*h/w); const double diag_fov = static_cast<int>(s.fov) * M_PI / 180.; const double fov = 2.*atan(tan(diag_fov/2.)/diag); ret = .5 / tan(.5 * fov); +#else + // the formula looks correct but doesn't work right regardless + + const double diag_fov = s.fov * M_PI/180; + const double aspect = w / sqrt(w*w + h*h); + const double fov = 2*atan(tan(diag_fov*.5) * aspect); + ret = .5 / tan(fov * .5); + static bool once = false; if (!once) { once = true; qDebug() << "f" << ret << "fov" << (fov * 180/M_PI); } +#endif return true; } return false; @@ -171,7 +172,7 @@ void Tracker_PT::run() video_widget->update_image(frame_); } } - qDebug() << "pt: Thread stopping"; + qDebug() << "pt: thread stopped"; } void Tracker_PT::apply_settings() @@ -180,37 +181,26 @@ void Tracker_PT::apply_settings() QMutexLocker l(&camera_mtx); - CamInfo info = camera.get_desired(); - const QString name = camera.get_desired_name(); + CamInfo info; - if (s.cam_fps != info.fps || - s.cam_res_x != info.res_x || - s.cam_res_y != info.res_y || - s.camera_name != name) - { - qDebug() << "pt: starting camera"; - camera.stop(); - camera.set_device(s.camera_name); - camera.set_res(s.cam_res_x, s.cam_res_y); - camera.set_fps(s.cam_fps); + if (!camera.get_info(info) || frame.rows != info.res_y || frame.cols != info.res_x) frame = cv::Mat(); - camera.start(); - } + + camera.start(camera_name_to_index(s.camera_name), s.cam_fps, s.cam_res_x, s.cam_res_y); qDebug() << "pt: done applying settings"; } -void Tracker_PT::start_tracker(QFrame *parent_window) +void Tracker_PT::start_tracker(QFrame* video_frame) { - video_frame = parent_window; video_frame->setAttribute(Qt::WA_NativeWindow); - video_frame->show(); - video_widget = new cv_video_widget(video_frame); - QHBoxLayout* video_layout = new QHBoxLayout(parent_window); - video_layout->setContentsMargins(0, 0, 0, 0); - video_layout->addWidget(video_widget); - video_frame->setLayout(video_layout); + video_widget = qptr<cv_video_widget>(video_frame); + layout = qptr<QHBoxLayout>(video_frame); + layout->setContentsMargins(0, 0, 0, 0); + layout->addWidget(video_widget.data()); + video_frame->setLayout(layout.data()); video_widget->resize(video_frame->width(), video_frame->height()); + video_frame->show(); start(); } diff --git a/tracker-pt/ftnoir_tracker_pt.h b/tracker-pt/ftnoir_tracker_pt.h index 020694ae..66928655 100644 --- a/tracker-pt/ftnoir_tracker_pt.h +++ b/tracker-pt/ftnoir_tracker_pt.h @@ -18,12 +18,14 @@ #include "point_tracker.h" #include "compat/timer.hpp" #include "cv/video-widget.hpp" +#include "compat/util.hpp" #include <QCoreApplication> #include <QThread> #include <QMutex> #include <QMutexLocker> #include <QTime> +#include <QLayout> #include <atomic> #include <memory> #include <vector> @@ -65,12 +67,12 @@ private: QMutex camera_mtx; QMutex data_mtx; - CVCamera camera; + Camera camera; PointExtractor point_extractor; PointTracker point_tracker; - cv_video_widget* video_widget; - QFrame* video_frame; + qshared<cv_video_widget> video_widget; + qshared<QLayout> layout; settings_pt s; Timer time; diff --git a/tracker-pt/ftnoir_tracker_pt_dialog.cpp b/tracker-pt/ftnoir_tracker_pt_dialog.cpp index 749ea1ff..d3951bd9 100644 --- a/tracker-pt/ftnoir_tracker_pt_dialog.cpp +++ b/tracker-pt/ftnoir_tracker_pt_dialog.cpp @@ -142,12 +142,16 @@ void TrackerDialog_PT::set_camera_settings_available(const QString& camera_name) void TrackerDialog_PT::show_camera_settings() { const int idx = ui.camdevice_combo->currentIndex(); + if (tracker) { - cv::VideoCapture* cap = tracker->camera; - if (cap && cap->isOpened()) + if (tracker->camera) { - video_property_page::show_from_capture(*cap, idx); + cv::VideoCapture& cap = *tracker->camera; + + CamInfo info; + if (tracker->camera.get_info(info)) + video_property_page::show_from_capture(cap, info.idx); } } else diff --git a/tracker-pt/lang/ru_RU.ts b/tracker-pt/lang/ru_RU.ts new file mode 100644 index 00000000..f6094d27 --- /dev/null +++ b/tracker-pt/lang/ru_RU.ts @@ -0,0 +1,294 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE TS> +<TS version="2.1" language="ru_RU"> +<context> + <name>PT_metadata</name> + <message> + <location filename="../ftnoir_tracker_pt.h" line="+92"/> + <source>PointTracker 1.1</source> + <translation></translation> + </message> +</context> +<context> + <name>UICPTClientControls</name> + <message> + <location filename="../FTNoIR_PT_Controls.ui" line="+23"/> + <source>PointTracker Settings</source> + <translation>Настройки PointTracker</translation> + </message> + <message> + <location line="+38"/> + <source>Camera</source> + <translation>Камера</translation> + </message> + <message> + <location line="+6"/> + <source>Camera settings</source> + <translation>Настройка камеры</translation> + </message> + <message> + <location line="+19"/> + <source>°</source> + <translation></translation> + </message> + <message> + <location line="+22"/> + <source>Diagonal field of view</source> + <translation>Угол обзора камеры</translation> + </message> + <message> + <location line="+13"/> + <source>Width</source> + <translation>Ширина</translation> + </message> + <message> + <location line="+13"/> + <source>FPS</source> + <translation>FPS (Кадров в секунду)</translation> + </message> + <message> + <location line="+16"/> + <source>Desired capture height</source> + <translation></translation> + </message> + <message> + <location line="+3"/> + <location line="+55"/> + <location line="+175"/> + <location line="+16"/> + <source> px</source> + <translation></translation> + </message> + <message> + <location line="-233"/> + <source>Dynamic pose timeout</source> + <translation>Динамическая поза (время ожидания)</translation> + </message> + <message> + <location line="+13"/> + <source>Desired capture framerate</source> + <translation>Желаемая частота кадров</translation> + </message> + <message> + <location line="+3"/> + <source> Hz</source> + <translation> Гц</translation> + </message> + <message> + <location line="+23"/> + <source>Desired capture width</source> + <translation>Желаемая ширина захвата</translation> + </message> + <message> + <location line="+22"/> + <source>Height</source> + <translation>Высота</translation> + </message> + <message> + <location line="+7"/> + <source> ms</source> + <translation> мс</translation> + </message> + <message> + <location line="+19"/> + <source>Dynamic pose resolution</source> + <translation>Динамическая поза (активация) </translation> + </message> + <message> + <location line="+13"/> + <source>Device</source> + <translation>Устройство</translation> + </message> + <message> + <location line="+16"/> + <source>Open</source> + <translation>Открыть</translation> + </message> + <message> + <location line="+7"/> + <source>Camera settings (when available)</source> + <translation>Параметры камеры (если доступно)</translation> + </message> + <message> + <location line="+10"/> + <source>Point extraction</source> + <translation>Извлечение точек</translation> + </message> + <message> + <location line="+6"/> + <source>Max size</source> + <translation>Макс.размер</translation> + </message> + <message> + <location line="+10"/> + <source>Threshold</source> + <translation>Порог</translation> + </message> + <message> + <location line="+10"/> + <source>Min size</source> + <translation>Мин.размер</translation> + </message> + <message> + <location line="+16"/> + <source>Intensity threshold for point extraction</source> + <translation>Порог интенсивности для извлечения точки</translation> + </message> + <message> + <location line="+25"/> + <source>Automatic threshold</source> + <translation>Автоматич. порог</translation> + </message> + <message> + <location line="+7"/> + <source>Enable, slider sets point size</source> + <translation>Полузнок устанавливает размер точек</translation> + </message> + <message> + <location line="+7"/> + <source>Maximum point diameter</source> + <translation></translation> + </message> + <message> + <location line="+16"/> + <source>Minimum point diameter</source> + <translation></translation> + </message> + <message> + <location line="+20"/> + <source>Model</source> + <translation>Модель</translation> + </message> + <message> + <location line="+28"/> + <source>Clip</source> + <translation>Клипса</translation> + </message> + <message> + <location line="+18"/> + <location line="+154"/> + <location line="+129"/> + <source>Model Dimensions</source> + <translation>Размеры модели</translation> + </message> + <message> + <location line="-271"/> + <location line="+19"/> + <location line="+48"/> + <location line="+19"/> + <location line="+97"/> + <location line="+35"/> + <location line="+32"/> + <location line="+40"/> + <location line="+26"/> + <location line="+13"/> + <location line="+13"/> + <location line="+13"/> + <location line="+26"/> + <location line="+132"/> + <location line="+26"/> + <location line="+26"/> + <source> mm</source> + <translation> мм</translation> + </message> + <message> + <location line="-511"/> + <location line="+116"/> + <source>Side</source> + <translation>Сбоку</translation> + </message> + <message> + <location line="-65"/> + <location line="+132"/> + <source>Front</source> + <translation>Спереди</translation> + </message> + <message> + <location line="-107"/> + <source>Cap</source> + <translation>Кепка</translation> + </message> + <message> + <location line="+135"/> + <source>Custom</source> + <translation>Свой</translation> + </message> + <message> + <location line="+18"/> + <location line="+169"/> + <location line="+106"/> + <source>z:</source> + <translation></translation> + </message> + <message> + <location line="-249"/> + <location line="+104"/> + <location line="+93"/> + <source>x:</source> + <translation></translation> + </message> + <message> + <location line="-132"/> + <source><html><head/><body><p>Location of the two remaining model points<br/>with respect to the reference point in default pose</p><p>Use any units you want, not necessarily centimeters.</p></body></html></source> + <translatorcomment>Расположение двух оставшихся точек модели относительно опорной точки в стандартной позе. Возможно исп-ть любые единицы измерения, не обязательно сантиметры.</translatorcomment> + <translation><html><head/><body><p> Расположение двух оставшихся точек модели<br/>относительно опорной точки в стандартной позе. </p><p>Возможно использовать любые единицы измерения.</p></body></html</translation> + </message> + <message> + <location line="+26"/> + <location line="+65"/> + <location line="+67"/> + <source>y:</source> + <translation></translation> + </message> + <message> + <location line="-106"/> + <source><html><head/><body><p><span style=" font-size:16pt;">P</span><span style=" font-size:16pt; vertical-align:sub;">3</span></p></body></html></source> + <translation></translation> + </message> + <message> + <location line="+13"/> + <source><html><head/><body><p><span style=" font-size:16pt;">P</span><span style=" font-size:16pt; vertical-align:sub;">2</span></p></body></html></source> + <translation></translation> + </message> + <message> + <location line="+46"/> + <source>Model position</source> + <translation>Положение модели</translation> + </message> + <message> + <location line="+105"/> + <source><html><head/><body><p><a href="https://github.com/opentrack/opentrack/wiki/model-calibration-for-PT-and-Aruco-trackers"><span style=" text-decoration: underline; color:#0000ff;">Instructions on the opentrack wiki</span></a></p></body></html></source> + <translation><html><head/><body><p><a href="https://github.com/opentrack/opentrack/wiki/model-calibration-for-PT-and-Aruco-trackers"><span style=" text-decoration: underline; color:#0000ff;">Инструкция на opentrack-вики</span></a></p></body></html></translation> + </message> + <message> + <location line="+13"/> + <source>Start calibration</source> + <translation>Начать калибровку</translation> + </message> + <message> + <location line="+17"/> + <source>About</source> + <translation>О программе</translation> + </message> + <message> + <location line="+6"/> + <source><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></source> + <translation><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;">Руководство (PointTracker)</span></a></p></body></html></translation> + </message> + <message> + <location line="+36"/> + <source>Status</source> + <translation>Статус</translation> + </message> + <message> + <location line="+6"/> + <source>Extracted Points:</source> + <translation>Извлечено точек:</translation> + </message> + <message> + <location line="+7"/> + <source>Camera Info:</source> + <translation>Параметры камеры:</translation> + </message> +</context> +</TS> |