From e1ae4a738c011fbbe44e5203cc304dacb6489768 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 29 Nov 2015 18:42:28 +0100 Subject: aruco: rework timeout logic - cycle otsu twice before selecting new box size don't cycle otsu each frame. - slower backoff from timeout value before new box size on occasional detections need at least 5 successes for each failure to not exceed. - select more sensible timeout per box size of .35 seconds. this is enough also with 30 Hz webcams, but too little for 15 Hz modes. --- tracker-aruco/ftnoir_tracker_aruco.cpp | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) (limited to 'tracker-aruco/ftnoir_tracker_aruco.cpp') diff --git a/tracker-aruco/ftnoir_tracker_aruco.cpp b/tracker-aruco/ftnoir_tracker_aruco.cpp index 570c2e0d..2d364a86 100644 --- a/tracker-aruco/ftnoir_tracker_aruco.cpp +++ b/tracker-aruco/ftnoir_tracker_aruco.cpp @@ -124,13 +124,14 @@ void Tracker::run() cv::Rect last_roi(65535, 65535, 0, 0); + // XXX change to timer.hpp auto freq = cv::getTickFrequency(); auto last_time = cv::getTickCount(); double cur_fps = 0; std::vector box_sizes { 5, 7, 9, 11 }; int box_idx = 0; - double failed = 0; - const double max_failed = 1.25; + double failed_otsu = 0; + const double max_failed_otsu = .35; cv::Vec3d rvec, tvec; cv::Mat intrinsics = cv::Mat::eye(3, 3, CV_32FC1); cv::Mat dist_coeffs = cv::Mat::zeros(5, 1, CV_32FC1); @@ -188,7 +189,7 @@ void Tracker::run() if (detector.detect(grayscale_, markers, cv::Mat(), cv::Mat(), -1, false), markers.size() == 1 && markers[0].size() == 4) { - failed = std::max(0., failed - dt); + failed_otsu = std::max(0., failed_otsu - dt*.2); auto& m = markers.at(0); for (int i = 0; i < 4; i++) { @@ -202,15 +203,19 @@ void Tracker::run() if (!roi_valid) { - otsu = !otsu; detector._thresMethod = otsu ? aruco::MarkerDetector::FIXED_THRES : aruco::MarkerDetector::ADPT_THRES; - failed += dt; - if (failed > max_failed) + failed_otsu += dt; + if (failed_otsu > max_failed_otsu) { - box_idx++; - box_idx %= box_sizes.size(); - qDebug() << "aruco: box size now" << box_sizes[box_idx]; - failed = 0; + if (otsu == true) + { + box_idx++; + box_idx %= box_sizes.size(); + qDebug() << "aruco: box size now" << box_sizes[box_idx]; + } + qDebug() << "aruco: otsu now" << !otsu; + failed_otsu = 0; + otsu = !otsu; } detector.setThresholdParams(box_sizes[box_idx], thres_param2); detector.setMinMaxSize(size_min, size_max); -- cgit v1.2.3 From e98880adc20988fadacc72f2a520bf0a674f135e Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Thu, 3 Dec 2015 22:58:58 +0100 Subject: aruco: use only Otsu thresholding, never adaptive Detection rate stays as good, likely better as before. @mursey reports in #274 that non-Otsu case eats way more CPU. --- tracker-aruco/ftnoir_tracker_aruco.cpp | 29 +++++++++++------------------ 1 file changed, 11 insertions(+), 18 deletions(-) (limited to 'tracker-aruco/ftnoir_tracker_aruco.cpp') diff --git a/tracker-aruco/ftnoir_tracker_aruco.cpp b/tracker-aruco/ftnoir_tracker_aruco.cpp index 2d364a86..32c81694 100644 --- a/tracker-aruco/ftnoir_tracker_aruco.cpp +++ b/tracker-aruco/ftnoir_tracker_aruco.cpp @@ -121,6 +121,7 @@ void Tracker::run() aruco::MarkerDetector detector; detector.setDesiredSpeed(3); + detector._thresMethod = aruco::MarkerDetector::FIXED_THRES; cv::Rect last_roi(65535, 65535, 0, 0); @@ -128,14 +129,13 @@ void Tracker::run() auto freq = cv::getTickFrequency(); auto last_time = cv::getTickCount(); double cur_fps = 0; - std::vector box_sizes { 5, 7, 9, 11 }; + std::vector box_sizes { 5, 9, 13 }; int box_idx = 0; - double failed_otsu = 0; - const double max_failed_otsu = .35; + double failed = 0; + const double max_failed = .8; cv::Vec3d rvec, tvec; cv::Mat intrinsics = cv::Mat::eye(3, 3, CV_32FC1); cv::Mat dist_coeffs = cv::Mat::zeros(5, 1, CV_32FC1); - bool otsu = false; while (!stop) { @@ -181,7 +181,6 @@ void Tracker::run() if (last_roi.width > 0 && last_roi.height) { - detector.setThresholdParams(box_sizes[box_idx], thres_param2); detector.setMinMaxSize(std::max(0.01, size_min * grayscale.cols / last_roi.width), std::min(1.0, size_max * grayscale.cols / last_roi.width)); @@ -189,7 +188,7 @@ void Tracker::run() if (detector.detect(grayscale_, markers, cv::Mat(), cv::Mat(), -1, false), markers.size() == 1 && markers[0].size() == 4) { - failed_otsu = std::max(0., failed_otsu - dt*.2); + failed = std::max(0., failed - dt*.25); auto& m = markers.at(0); for (int i = 0; i < 4; i++) { @@ -203,19 +202,13 @@ void Tracker::run() if (!roi_valid) { - detector._thresMethod = otsu ? aruco::MarkerDetector::FIXED_THRES : aruco::MarkerDetector::ADPT_THRES; - failed_otsu += dt; - if (failed_otsu > max_failed_otsu) + failed += dt; + if (failed > max_failed) { - if (otsu == true) - { - box_idx++; - box_idx %= box_sizes.size(); - qDebug() << "aruco: box size now" << box_sizes[box_idx]; - } - qDebug() << "aruco: otsu now" << !otsu; - failed_otsu = 0; - otsu = !otsu; + box_idx++; + box_idx %= box_sizes.size(); + qDebug() << "aruco: box size now" << box_sizes[box_idx]; + failed = 0; } detector.setThresholdParams(box_sizes[box_idx], thres_param2); detector.setMinMaxSize(size_min, size_max); -- cgit v1.2.3 From e6b5a7a710890520ab56691e41f080cf97010e5c Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Thu, 3 Dec 2015 23:48:43 +0100 Subject: aruco: use a single standard box size Higher box sizes use more CPU due to the need to convolve a lot. It looks fine with both high and low exposure on both Logitech C525 and PS3 Eye webcams. Issue: #273 --- tracker-aruco/ftnoir_tracker_aruco.cpp | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) (limited to 'tracker-aruco/ftnoir_tracker_aruco.cpp') diff --git a/tracker-aruco/ftnoir_tracker_aruco.cpp b/tracker-aruco/ftnoir_tracker_aruco.cpp index 32c81694..2b38bb2f 100644 --- a/tracker-aruco/ftnoir_tracker_aruco.cpp +++ b/tracker-aruco/ftnoir_tracker_aruco.cpp @@ -129,10 +129,6 @@ void Tracker::run() auto freq = cv::getTickFrequency(); auto last_time = cv::getTickCount(); double cur_fps = 0; - std::vector box_sizes { 5, 9, 13 }; - int box_idx = 0; - double failed = 0; - const double max_failed = .8; cv::Vec3d rvec, tvec; cv::Mat intrinsics = cv::Mat::eye(3, 3, CV_32FC1); cv::Mat dist_coeffs = cv::Mat::zeros(5, 1, CV_32FC1); @@ -146,12 +142,12 @@ void Tracker::run() if (!camera.read(color)) continue; } - static constexpr int thres_param2 = 5; cv::Mat grayscale; cv::cvtColor(color, grayscale, cv::COLOR_RGB2GRAY); const int scale = grayscale.cols > 480 ? 2 : 1; - detector.setThresholdParams(box_sizes[box_idx], thres_param2); + // param 2 ignored for Otsu thresholding. it's required to use our fork of Aruco. + detector.setThresholdParams(5, -1); static constexpr double pi = 3.1415926f; const int w = grayscale.cols, h = grayscale.rows; @@ -188,7 +184,6 @@ void Tracker::run() if (detector.detect(grayscale_, markers, cv::Mat(), cv::Mat(), -1, false), markers.size() == 1 && markers[0].size() == 4) { - failed = std::max(0., failed - dt*.25); auto& m = markers.at(0); for (int i = 0; i < 4; i++) { @@ -202,15 +197,6 @@ void Tracker::run() if (!roi_valid) { - failed += dt; - if (failed > max_failed) - { - box_idx++; - box_idx %= box_sizes.size(); - qDebug() << "aruco: box size now" << box_sizes[box_idx]; - failed = 0; - } - detector.setThresholdParams(box_sizes[box_idx], thres_param2); detector.setMinMaxSize(size_min, size_max); detector.detect(grayscale, markers, cv::Mat(), cv::Mat(), -1, false); } -- cgit v1.2.3 From 0f577dbe8adb8f7e210241c6bee0be73349f8d45 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 6 Dec 2015 00:41:59 +0100 Subject: tracker/aruco, tracker/pt: sleep before releasing camera Really fast toggling tracking crashed with my PS3 Eye. --- tracker-aruco/ftnoir_tracker_aruco.cpp | 2 ++ tracker-pt/ftnoir_tracker_pt.cpp | 3 +++ 2 files changed, 5 insertions(+) (limited to 'tracker-aruco/ftnoir_tracker_aruco.cpp') diff --git a/tracker-aruco/ftnoir_tracker_aruco.cpp b/tracker-aruco/ftnoir_tracker_aruco.cpp index 2b38bb2f..1da5b8df 100644 --- a/tracker-aruco/ftnoir_tracker_aruco.cpp +++ b/tracker-aruco/ftnoir_tracker_aruco.cpp @@ -43,6 +43,8 @@ Tracker::~Tracker() delete videoWidget; if(layout) delete layout; + // fast start/stop causes breakage + portable::sleep(1000); camera.release(); } diff --git a/tracker-pt/ftnoir_tracker_pt.cpp b/tracker-pt/ftnoir_tracker_pt.cpp index 15a60962..2dbf9068 100644 --- a/tracker-pt/ftnoir_tracker_pt.cpp +++ b/tracker-pt/ftnoir_tracker_pt.cpp @@ -13,6 +13,7 @@ #include #include #include "opentrack/camera-names.hpp" +#include "opentrack-compat/sleep.hpp" //#define PT_PERF_LOG //log performance @@ -34,6 +35,8 @@ Tracker_PT::~Tracker_PT() delete video_widget; video_widget = NULL; if (video_frame->layout()) delete video_frame->layout(); + // fast start/stop causes breakage + portable::sleep(1000); camera.stop(); } -- cgit v1.2.3 From 211a17996e3ffc0d84c985c43c612da32923b42d Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 6 Dec 2015 02:24:44 +0100 Subject: api/camera-names: move to compat/ --- opentrack-compat/CMakeLists.txt | 1 + opentrack-compat/camera-names.cpp | 113 ++++++++++++++++++++++++++++++++ opentrack-compat/camera-names.hpp | 22 +++++++ opentrack/CMakeLists.txt | 1 - opentrack/camera-names.cpp | 113 -------------------------------- opentrack/camera-names.hpp | 16 ----- opentrack/opencv-camera-dialog.hpp | 2 +- tracker-aruco/ftnoir_tracker_aruco.cpp | 2 +- tracker-pt/ftnoir_tracker_pt.cpp | 2 +- tracker-pt/ftnoir_tracker_pt_dialog.cpp | 2 +- 10 files changed, 140 insertions(+), 134 deletions(-) create mode 100644 opentrack-compat/camera-names.cpp create mode 100644 opentrack-compat/camera-names.hpp delete mode 100644 opentrack/camera-names.cpp delete mode 100644 opentrack/camera-names.hpp (limited to 'tracker-aruco/ftnoir_tracker_aruco.cpp') diff --git a/opentrack-compat/CMakeLists.txt b/opentrack-compat/CMakeLists.txt index 37d53e6c..8dba67e2 100644 --- a/opentrack-compat/CMakeLists.txt +++ b/opentrack-compat/CMakeLists.txt @@ -2,3 +2,4 @@ opentrack_boilerplate(opentrack-compat NO-COMPAT NO-LINKER-SCRIPT LINKAGE) if(NOT WIN32 AND NOT APPLE) target_link_libraries(opentrack-compat rt) endif() +link_with_dinput8(opentrack-compat) diff --git a/opentrack-compat/camera-names.cpp b/opentrack-compat/camera-names.cpp new file mode 100644 index 00000000..72bcf41a --- /dev/null +++ b/opentrack-compat/camera-names.cpp @@ -0,0 +1,113 @@ +#include "camera-names.hpp" + +#if defined(OPENTRACK_API) && defined(_WIN32) +# define NO_DSHOW_STRSAFE +# include +# include +#endif + +#if defined(OPENTRACK_API) && (defined(__unix) || defined(__linux) || defined(__APPLE__)) +# include +#endif + +#ifdef __linux +#include +#include +#include +#include +#endif + +#include + +OPENTRACK_COMPAT_EXPORT int camera_name_to_index(const QString &name) +{ + auto list = get_camera_names(); + int ret = list.indexOf(name); + if (ret < 0) + ret = 0; + return ret; +} + +OPENTRACK_COMPAT_EXPORT QList get_camera_names() { + QList ret; +#if defined(_WIN32) + // Create the System Device Enumerator. + HRESULT hr; + hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); + if (FAILED(hr)) + qDebug() << "failed CoInitializeEx" << hr; + ICreateDevEnum *pSysDevEnum = NULL; + hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (void **)&pSysDevEnum); + if (FAILED(hr)) + { + qDebug() << "failed CLSID_SystemDeviceEnum" << hr; + return ret; + } + // Obtain a class enumerator for the video compressor category. + IEnumMoniker *pEnumCat = NULL; + hr = pSysDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnumCat, 0); + + if (hr == S_OK) { + // Enumerate the monikers. + IMoniker *pMoniker = NULL; + ULONG cFetched; + while (pEnumCat->Next(1, &pMoniker, &cFetched) == S_OK) { + IPropertyBag *pPropBag; + hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pPropBag); + if (SUCCEEDED(hr)) { + // To retrieve the filter's friendly name, do the following: + VARIANT varName; + VariantInit(&varName); + hr = pPropBag->Read(L"FriendlyName", &varName, 0); + if (SUCCEEDED(hr)) + { + // Display the name in your UI somehow. + QString str((QChar*)varName.bstrVal, wcslen(varName.bstrVal)); + ret.append(str); + } + VariantClear(&varName); + + ////// To create an instance of the filter, do the following: + ////IBaseFilter *pFilter; + ////hr = pMoniker->BindToObject(NULL, NULL, IID_IBaseFilter, + //// (void**)&pFilter); + // Now add the filter to the graph. + //Remember to release pFilter later. + pPropBag->Release(); + } + pMoniker->Release(); + } + pEnumCat->Release(); + } + else + qDebug() << "failed CLSID_VideoInputDeviceCategory" << hr; + + pSysDevEnum->Release(); +#endif +#ifdef __linux + for (int i = 0; i < 16; i++) { + char buf[128]; + sprintf(buf, "/dev/video%d", i); + if (access(buf, F_OK) == 0) + ret.append(buf); + else + continue; + + if (access(buf, R_OK | W_OK) == 0) { + int fd = open(buf, O_RDONLY); + if (fd == -1) + continue; + struct v4l2_capability video_cap; + if(ioctl(fd, VIDIOC_QUERYCAP, &video_cap) == -1) + { + qDebug() << "VIDIOC_QUERYCAP" << errno; + close(fd); + continue; + } + ret[ret.size()-1] = reinterpret_cast(video_cap.card); + close(fd); + } + } +#endif + return ret; +} \ No newline at end of file diff --git a/opentrack-compat/camera-names.hpp b/opentrack-compat/camera-names.hpp new file mode 100644 index 00000000..c2879000 --- /dev/null +++ b/opentrack-compat/camera-names.hpp @@ -0,0 +1,22 @@ +/* Copyright (c) 2014-2015, Stanislaw Halik + + * 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. + */ + +#pragma once + +#include +#include + +#ifdef BUILD_compat +# include "compat-export.hpp" +#else +# include "compat-import.hpp" +#endif + +OPENTRACK_COMPAT_EXPORT QList get_camera_names(); +OPENTRACK_COMPAT_EXPORT int camera_name_to_index(const QString &name); + diff --git a/opentrack/CMakeLists.txt b/opentrack/CMakeLists.txt index de5975e2..08003a5c 100644 --- a/opentrack/CMakeLists.txt +++ b/opentrack/CMakeLists.txt @@ -4,5 +4,4 @@ if(NOT WIN32) else() target_link_libraries(opentrack-api winmm) endif() -link_with_dinput8(opentrack-api) target_link_libraries(opentrack-api opentrack-spline-widget) diff --git a/opentrack/camera-names.cpp b/opentrack/camera-names.cpp deleted file mode 100644 index 74e998ca..00000000 --- a/opentrack/camera-names.cpp +++ /dev/null @@ -1,113 +0,0 @@ -#include "camera-names.hpp" - -#if defined(OPENTRACK_API) && defined(_WIN32) -# define NO_DSHOW_STRSAFE -# include -# include -#endif - -#if defined(OPENTRACK_API) && (defined(__unix) || defined(__linux) || defined(__APPLE__)) -# include -#endif - -#ifdef __linux -#include -#include -#include -#include -#endif - -#include - -int camera_name_to_index(const QString &name) -{ - auto list = get_camera_names(); - int ret = list.indexOf(name); - if (ret < 0) - ret = 0; - return ret; -} - -QList get_camera_names() { - QList ret; -#if defined(_WIN32) - // Create the System Device Enumerator. - HRESULT hr; - hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); - if (FAILED(hr)) - qDebug() << "failed CoInitializeEx" << hr; - ICreateDevEnum *pSysDevEnum = NULL; - hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (void **)&pSysDevEnum); - if (FAILED(hr)) - { - qDebug() << "failed CLSID_SystemDeviceEnum" << hr; - return ret; - } - // Obtain a class enumerator for the video compressor category. - IEnumMoniker *pEnumCat = NULL; - hr = pSysDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnumCat, 0); - - if (hr == S_OK) { - // Enumerate the monikers. - IMoniker *pMoniker = NULL; - ULONG cFetched; - while (pEnumCat->Next(1, &pMoniker, &cFetched) == S_OK) { - IPropertyBag *pPropBag; - hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pPropBag); - if (SUCCEEDED(hr)) { - // To retrieve the filter's friendly name, do the following: - VARIANT varName; - VariantInit(&varName); - hr = pPropBag->Read(L"FriendlyName", &varName, 0); - if (SUCCEEDED(hr)) - { - // Display the name in your UI somehow. - QString str((QChar*)varName.bstrVal, wcslen(varName.bstrVal)); - ret.append(str); - } - VariantClear(&varName); - - ////// To create an instance of the filter, do the following: - ////IBaseFilter *pFilter; - ////hr = pMoniker->BindToObject(NULL, NULL, IID_IBaseFilter, - //// (void**)&pFilter); - // Now add the filter to the graph. - //Remember to release pFilter later. - pPropBag->Release(); - } - pMoniker->Release(); - } - pEnumCat->Release(); - } - else - qDebug() << "failed CLSID_VideoInputDeviceCategory" << hr; - - pSysDevEnum->Release(); -#endif -#ifdef __linux - for (int i = 0; i < 16; i++) { - char buf[128]; - sprintf(buf, "/dev/video%d", i); - if (access(buf, F_OK) == 0) - ret.append(buf); - else - continue; - - if (access(buf, R_OK | W_OK) == 0) { - int fd = open(buf, O_RDONLY); - if (fd == -1) - continue; - struct v4l2_capability video_cap; - if(ioctl(fd, VIDIOC_QUERYCAP, &video_cap) == -1) - { - qDebug() << "VIDIOC_QUERYCAP" << errno; - close(fd); - continue; - } - ret[ret.size()-1] = reinterpret_cast(video_cap.card); - close(fd); - } - } -#endif - return ret; -} \ No newline at end of file diff --git a/opentrack/camera-names.hpp b/opentrack/camera-names.hpp deleted file mode 100644 index ef914458..00000000 --- a/opentrack/camera-names.hpp +++ /dev/null @@ -1,16 +0,0 @@ -/* Copyright (c) 2014-2015, Stanislaw Halik - - * 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. - */ - -#pragma once - -#include -#include - -QList get_camera_names(); -int camera_name_to_index(const QString &name); - diff --git a/opentrack/opencv-camera-dialog.hpp b/opentrack/opencv-camera-dialog.hpp index 0d4a51af..96c7a643 100644 --- a/opentrack/opencv-camera-dialog.hpp +++ b/opentrack/opencv-camera-dialog.hpp @@ -12,7 +12,7 @@ #include #include #include -#include "opentrack/camera-names.hpp" +#include "opentrack-compat/camera-names.hpp" #ifdef __linux #include diff --git a/tracker-aruco/ftnoir_tracker_aruco.cpp b/tracker-aruco/ftnoir_tracker_aruco.cpp index 1da5b8df..316c7e13 100644 --- a/tracker-aruco/ftnoir_tracker_aruco.cpp +++ b/tracker-aruco/ftnoir_tracker_aruco.cpp @@ -16,7 +16,7 @@ #include #include #include -#include "opentrack/camera-names.hpp" +#include "opentrack-compat/camera-names.hpp" #include "opentrack-compat/sleep.hpp" typedef struct { diff --git a/tracker-pt/ftnoir_tracker_pt.cpp b/tracker-pt/ftnoir_tracker_pt.cpp index 2dbf9068..3dd91a45 100644 --- a/tracker-pt/ftnoir_tracker_pt.cpp +++ b/tracker-pt/ftnoir_tracker_pt.cpp @@ -12,7 +12,7 @@ #include #include #include -#include "opentrack/camera-names.hpp" +#include "opentrack-compat/camera-names.hpp" #include "opentrack-compat/sleep.hpp" //#define PT_PERF_LOG //log performance diff --git a/tracker-pt/ftnoir_tracker_pt_dialog.cpp b/tracker-pt/ftnoir_tracker_pt_dialog.cpp index b1ae2238..551910f7 100644 --- a/tracker-pt/ftnoir_tracker_pt_dialog.cpp +++ b/tracker-pt/ftnoir_tracker_pt_dialog.cpp @@ -12,7 +12,7 @@ #include #include #include -#include "opentrack/camera-names.hpp" +#include "opentrack-compat/camera-names.hpp" #include //----------------------------------------------------------------------------- -- cgit v1.2.3