From 51fb14715d8e30b1b4ca8ed18f596526be4066df Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Thu, 18 Jun 2015 10:59:55 +0200 Subject: nix stderr spam --- ftnoir_filter_accela/ftnoir_accela_filtercontrols.ui | 4 ---- 1 file changed, 4 deletions(-) diff --git a/ftnoir_filter_accela/ftnoir_accela_filtercontrols.ui b/ftnoir_filter_accela/ftnoir_accela_filtercontrols.ui index c16fbe0a..2387723a 100644 --- a/ftnoir_filter_accela/ftnoir_accela_filtercontrols.ui +++ b/ftnoir_filter_accela/ftnoir_accela_filtercontrols.ui @@ -57,10 +57,6 @@ 0 - - color:#0; -background:none; - Rotation sensitivity -- cgit v1.2.3 From 551c73068f43da1dece0feae8d8a795f0f3726b7 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Fri, 19 Jun 2015 10:02:23 +0200 Subject: pt: remove hysteresis No one used it, and we have a better solution for stable extraction, pending commit. --- ftnoir_tracker_pt/FTNoIR_PT_Controls.ui | 96 ++++++++------------------ ftnoir_tracker_pt/ftnoir_tracker_pt_dialog.cpp | 1 - ftnoir_tracker_pt/ftnoir_tracker_pt_settings.h | 2 - ftnoir_tracker_pt/point_extractor.cpp | 40 +---------- ftnoir_tracker_pt/point_extractor.h | 1 - 5 files changed, 31 insertions(+), 109 deletions(-) diff --git a/ftnoir_tracker_pt/FTNoIR_PT_Controls.ui b/ftnoir_tracker_pt/FTNoIR_PT_Controls.ui index 0e6048c3..39fb0686 100644 --- a/ftnoir_tracker_pt/FTNoIR_PT_Controls.ui +++ b/ftnoir_tracker_pt/FTNoIR_PT_Controls.ui @@ -259,19 +259,6 @@ Point extraction - - - - Minimum point diameter - - - px - - - 1024 - - - @@ -297,81 +284,59 @@ - - - - Maximum point diameter - - - px + + + + Min size - - 1024 + + mindiam_spin - - + + - Max size + Threshold - maxdiam_spin + threshold_slider - - + + - Per pixel hysteresis width (leave left if there is little difference between dot and non-dot, move right for increased stability against pixel noise) - - - 255 - - - 1 - - - 100 - - - Qt::Horizontal + Minimum point diameter - - QSlider::TicksBothSides + + px - - 25 + + 1024 - - + + - Threshold + Max size - threshold_slider + maxdiam_spin - - - - Hysteresis - - - threshold_secondary_slider + + + + Maximum point diameter - - - - - - Min size + + px - - mindiam_spin + + 1024 @@ -1150,9 +1115,6 @@ fps_spin fov threshold_slider - mindiam_spin - threshold_secondary_slider - maxdiam_spin model_tabs clip_tlength_spin clip_theight_spin diff --git a/ftnoir_tracker_pt/ftnoir_tracker_pt_dialog.cpp b/ftnoir_tracker_pt/ftnoir_tracker_pt_dialog.cpp index 86178cb3..e7f1384d 100644 --- a/ftnoir_tracker_pt/ftnoir_tracker_pt_dialog.cpp +++ b/ftnoir_tracker_pt/ftnoir_tracker_pt_dialog.cpp @@ -44,7 +44,6 @@ TrackerDialog_PT::TrackerDialog_PT() tie_setting(s.cam_res_y, ui.res_y_spin); tie_setting(s.cam_fps, ui.fps_spin); - tie_setting(s.threshold_secondary, ui.threshold_secondary_slider); tie_setting(s.threshold, ui.threshold_slider); tie_setting(s.min_point_size, ui.mindiam_spin); diff --git a/ftnoir_tracker_pt/ftnoir_tracker_pt_settings.h b/ftnoir_tracker_pt/ftnoir_tracker_pt_settings.h index 14786013..4e241bc3 100644 --- a/ftnoir_tracker_pt/ftnoir_tracker_pt_settings.h +++ b/ftnoir_tracker_pt/ftnoir_tracker_pt_settings.h @@ -18,7 +18,6 @@ struct settings_pt : opts cam_res_y, cam_fps, threshold, - threshold_secondary, min_point_size, max_point_size; @@ -41,7 +40,6 @@ struct settings_pt : opts cam_res_y(b, "camera-res-height", 480), cam_fps(b, "camera-fps", 30), threshold(b, "threshold-primary", 128), - threshold_secondary(b, "threshold-secondary", 128), min_point_size(b, "min-point-size", 10), max_point_size(b, "max-point-size", 50), m01_x(b, "m_01-x", 0), diff --git a/ftnoir_tracker_pt/point_extractor.cpp b/ftnoir_tracker_pt/point_extractor.cpp index 5f7f6829..dab1d967 100644 --- a/ftnoir_tracker_pt/point_extractor.cpp +++ b/ftnoir_tracker_pt/point_extractor.cpp @@ -25,51 +25,15 @@ std::vector PointExtractor::extract_points(Mat& frame) const int W = frame.cols; const int H = frame.rows; - if (frame_last.cols != W || frame_last.rows != H) - { - frame_last = cv::Mat(); - } - // convert to grayscale Mat frame_gray; cvtColor(frame, frame_gray, cv::COLOR_RGB2GRAY); - int secondary = s.threshold_secondary; - int primary = s.threshold; - // mask for everything that passes the threshold (or: the upper threshold of the hysteresis) Mat frame_bin; - // only used if draw_output - Mat frame_bin_copy; - // mask for everything that passes - Mat frame_bin_low; - // mask for lower-threshold && combined result of last, needs to remain in scope until drawing, but is only used if secondary != 0 - Mat frame_last_and_low; - - if(secondary==0){ - threshold(frame_gray, frame_bin, primary, 255, THRESH_BINARY); - }else{ - // we recombine a number of buffers, this might be slower than a single loop of per-pixel logic - // but it might as well be faster if openCV makes good use of SIMD - float t = primary; - //float hyst = float(threshold_secondary_val)/512.; - //threshold(frame_gray, frame_bin, (t + ((255.-t)*hyst)), 255, THRESH_BINARY); - float hyst = float(primary)/(256.*8.); - threshold(frame_gray, frame_bin, t, 255, THRESH_BINARY); - threshold(frame_gray, frame_bin_low,std::max(float(1), t - (t*hyst)), 255, THRESH_BINARY); - frame_bin.copyTo(frame_bin_copy); - if(frame_last.empty()){ - frame_bin.copyTo(frame_last); - }else{ - // keep pixels from last if they are above lower threshold - bitwise_and(frame_last, frame_bin_low, frame_last_and_low); - // union of pixels >= higher threshold and pixels >= lower threshold - bitwise_or(frame_bin, frame_last_and_low, frame_last); - frame_last.copyTo(frame_bin); - } - } - + threshold(frame_gray, frame_bin, s.threshold, 255, THRESH_BINARY); + int min_size = s.min_point_size; int max_size = s.max_point_size; diff --git a/ftnoir_tracker_pt/point_extractor.h b/ftnoir_tracker_pt/point_extractor.h index 3f6cfb72..b9368ab6 100644 --- a/ftnoir_tracker_pt/point_extractor.h +++ b/ftnoir_tracker_pt/point_extractor.h @@ -28,7 +28,6 @@ public: settings_pt s; private: std::vector points; - cv::Mat frame_last; }; #endif //POINTEXTRACTOR_H -- cgit v1.2.3 From e033465ceb37c727ede335e5832a4b884cf72376 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Fri, 19 Jun 2015 12:38:53 +0200 Subject: pt: extractor algorithm based on OpenCV's SimpleBlobDetector Tunables are probably wrong, we'll get to that later. --- ftnoir_tracker_pt/point_extractor.cpp | 166 +++++++++++++++++++++++++++++----- 1 file changed, 144 insertions(+), 22 deletions(-) diff --git a/ftnoir_tracker_pt/point_extractor.cpp b/ftnoir_tracker_pt/point_extractor.cpp index dab1d967..86454729 100644 --- a/ftnoir_tracker_pt/point_extractor.cpp +++ b/ftnoir_tracker_pt/point_extractor.cpp @@ -28,11 +28,6 @@ std::vector PointExtractor::extract_points(Mat& frame) // convert to grayscale Mat frame_gray; cvtColor(frame, frame_gray, cv::COLOR_RGB2GRAY); - - // mask for everything that passes the threshold (or: the upper threshold of the hysteresis) - Mat frame_bin; - - threshold(frame_gray, frame_bin, s.threshold, 255, THRESH_BINARY); int min_size = s.min_point_size; int max_size = s.max_point_size; @@ -40,30 +35,157 @@ std::vector PointExtractor::extract_points(Mat& frame) 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; - std::vector> contours; - cv::findContours(frame_bin, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE); + // testing indicates threshold difference of 45 from lowest to highest + // that's applicable to poor lighting conditions. + + static constexpr int diff = 20; + static constexpr int steps = 10; + static constexpr int successes = 8; + + int thres = s.threshold; + + struct blob { + double max_radius; + std::vector pos; + std::vector confids; + + cv::Vec2d effective_pos() const + { + double x = 0; + double y = 0; + double norm = 0; + for (unsigned i = 0; i < pos.size(); i++) + { + x += pos[i][0] * confids[i]; + y += pos[i][1] * confids[i]; + norm += confids[i]; + } + cv::Vec2d ret(x, y); + ret *= 1./norm; + //qDebug() << "ret" << ret[0] << ret[1] << "norm" << norm << "count" << pos.size(); + return ret; + } + }; + + struct simple_blob + { + double radius; + cv::Vec2d pos; + double confid; + bool taken; + simple_blob(double radius, const cv::Vec2d& pos, double confid) : radius(radius), pos(pos), confid(confid), taken(false) + { + //qDebug() << "radius" << radius << "pos" << pos[0] << pos[1] << "confid" << confid; + } + bool inside(const simple_blob& other) + { + cv::Vec2d tmp = pos - other.pos; + double p = sqrt(1e-4 + tmp.dot(tmp)); + return p < radius; + } + static std::vector merge(std::vector& blobs) + { + std::vector ret; + for (unsigned i = 0; i < blobs.size(); i++) + { + auto& b = blobs[i]; + if (b.taken) + continue; + b.taken = true; + blob b_; + b_.pos.push_back(b.pos); + b_.confids.push_back(b.confid); + b_.max_radius = b.radius; + + for (unsigned j = i+1; j < blobs.size(); j++) + { + auto& b2 = blobs[j]; + if (b2.taken) + continue; + if (b.inside(b2) || b2.inside(b)) + { + b2.taken = true; + b_.pos.push_back(b2.pos); + b_.confids.push_back(b2.confid); + b_.max_radius = std::max(b_.max_radius, b2.radius); + } + } + if (b_.pos.size() >= successes) + ret.push_back(b_); + } + return ret; + } + }; + + // mask for everything that passes the threshold (or: the upper threshold of the hysteresis) + Mat frame_bin = cv::Mat::zeros(H, W, CV_8U); + + const int min = std::max(0, thres - diff/2); + const int max = std::min(255, thres + diff/2); + const int step = std::max(1, diff / steps); + + std::vector blobs; + + // this code is based on OpenCV SimpleBlobDetector + for (int i = min; i < max; i += step) + { + Mat frame_bin_; + threshold(frame_gray, frame_bin_, i, 255, THRESH_BINARY); + frame_bin.setTo(170, frame_bin_); + + std::vector> contours; + cv::findContours(frame_bin_, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE); + + for (auto& c : contours) + { + auto m = cv::moments(cv::Mat(c)); + const double area = m.m00; + if (area == 0.) + continue; + cv::Vec2d pos(m.m10 / m.m00, m.m01 / m.m00); + if (area < region_size_min || area > region_size_max) + continue; + + double radius = 0; + + for (auto& k : c) + { + cv::Vec2d pos_(k.x, k.y); + cv::Vec2d tmp = pos_ - pos; + radius = std::max(radius, sqrt(1e-2 + tmp.dot(tmp))); + } + double confid = 1; + { + double denominator = std::sqrt(std::pow(2 * m.mu11, 2) + std::pow(m.mu20 - m.mu02, 2)); + const double eps = 1e-2; + if (denominator > eps) + { + double cosmin = (m.mu20 - m.mu02) / denominator; + double sinmin = 2 * m.mu11 / denominator; + double cosmax = -cosmin; + double sinmax = -sinmin; + + double imin = 0.5 * (m.mu20 + m.mu02) - 0.5 * (m.mu20 - m.mu02) * cosmin - m.mu11 * sinmin; + double imax = 0.5 * (m.mu20 + m.mu02) - 0.5 * (m.mu20 - m.mu02) * cosmax - m.mu11 * sinmax; + confid = imin / imax; + } + } + blobs.push_back(simple_blob(radius, pos, confid)); + } + } // clear old points points.clear(); - for (auto& c : contours) + for (auto& b : simple_blob::merge(blobs)) { - auto m = cv::moments(cv::Mat(c)); - const double area = m.m00; - if (area == 0.) - continue; - cv::Vec2f pos(m.m10 / m.m00, m.m01 / m.m00); - if (area < region_size_min || area > region_size_max) - continue; - pos[0] = (pos[0] - W/2)/W; - pos[1] = -(pos[1] - H/2)/W; - - points.push_back(pos); + auto pos = b.effective_pos(); + Vec2f p((pos[0] - W/2)/W, -(pos[1] - H/2)/W); + points.push_back(p); } - - // draw output image + + // draw output image vector 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); -- cgit v1.2.3 From f4693222160f1705107e701bd832e5433cd0d6bb Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Wed, 1 Jul 2015 11:16:28 +0200 Subject: accela: use spline mapper for gain --- CMakeLists.txt | 1 + ftnoir_filter_accela/ftnoir_filter_accela.cpp | 67 ++++++++++++++------------- ftnoir_filter_accela/ftnoir_filter_accela.h | 4 +- 3 files changed, 38 insertions(+), 34 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4413f712..1662c89f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -239,6 +239,7 @@ set_target_properties(opentrack-version PROPERTIES "IN_VERSION_UNIT;OPENTRACK_VERSION=\"${OPENTRACK__COMMIT}\"") opentrack_library(opentrack-filter-accela ftnoir_filter_accela) +target_link_libraries(opentrack-filter-accela opentrack-spline-widget) opentrack_library(opentrack-filter-kalman ftnoir_filter_kalman) opentrack_library(opentrack-filter-ewma ftnoir_filter_ewma2) diff --git a/ftnoir_filter_accela/ftnoir_filter_accela.cpp b/ftnoir_filter_accela/ftnoir_filter_accela.cpp index 77964d32..5a042f81 100644 --- a/ftnoir_filter_accela/ftnoir_filter_accela.cpp +++ b/ftnoir_filter_accela/ftnoir_filter_accela.cpp @@ -12,20 +12,42 @@ #include "opentrack/plugin-api.hpp" using namespace std; -FTNoIR_Filter::FTNoIR_Filter() : first_run(true) -{ -} +static constexpr double rot_gains[][2] = { + { 7, 200 }, + { 6, 100 }, + { 5, 45 }, + { 4, 15 }, + { 3, 5 }, + { 2, 1.4 }, + { 1, .4 }, + { 0, .2 }, + { -1, 0 } +}; +static constexpr double trans_gains[][2] = { + { 5, 180 }, + { 4, 64 }, + { 3, 20 }, + { 2, 5 }, + { 1, .7 }, + { 0, .1 }, + { -1, 0 } +}; -double FTNoIR_Filter::f(double val, const double gains[][2]) +FTNoIR_Filter::FTNoIR_Filter() : first_run(true) { - for (int i = 0; gains[i][0] >= 0; i++) + rot.setMaxInput(rot_gains[0][0]); + trans.setMaxInput(trans_gains[0][0]); + rot.setMaxOutput(rot_gains[0][1]); + trans.setMaxOutput(trans_gains[0][1]); + + for (int i = 0; rot_gains[i][0] >= 0; i++) { - if (val >= gains[i][0]) - { - return gains[i][1] * val; - } + rot.addPoint(QPointF(rot_gains[i][0], rot_gains[i][1])); + } + for (int i = 0; trans_gains[i][0] >= 0; i++) + { + trans.addPoint(QPointF(trans_gains[i][0], trans_gains[i][1])); } - return 0; } void FTNoIR_Filter::filter(const double* input, double *output) @@ -43,25 +65,6 @@ void FTNoIR_Filter::filter(const double* input, double *output) return; } - static const double rot_gains[][2] = { - { 6, 15 }, - { 5, 8 }, - { 4, 4 }, - { 3, 1.6 }, - { 2, .7 }, - { 1, .4 }, - { 0, .2 }, - { -1, 0 } - }; - static const double trans_gains[][2] = { - { 4, 8 }, - { 3, 4 }, - { 2, 2 }, - { 1, .5 }, - { 0, .1 }, - { -1, 0 } - }; - const double rot_t = 10. * (1+s.rot_threshold) / 100.; const double trans_t = 5. * (1+s.trans_threshold) / 100.; @@ -75,6 +78,8 @@ void FTNoIR_Filter::filter(const double* input, double *output) for (int i = 0; i < 6; i++) { + Map& m = i >= 3 ? rot : trans; + smoothed_input[i] = smoothed_input[i] * (1.-alpha) + input[i] * alpha; const double in = smoothed_input[i]; @@ -83,14 +88,12 @@ void FTNoIR_Filter::filter(const double* input, double *output) const double dz = i >= 3 ? rot_dz : trans_dz; const double vec_ = max(0., fabs(vec) - dz); const double thres = i >= 3 ? rot_t : trans_t; - const double val = f(vec_ / thres, i >= 3 ? rot_gains : trans_gains) * thres; + const double val = m.getValue(vec_ / thres) * thres; const double result = last_output[i] + (vec < 0 ? -1 : 1) * dt * val; const bool negp = vec < 0.; const bool done = negp ? result <= in : result >= in; - if (i == 3 && val > 0.1 && done) - qDebug() << "done"; const double ret = done ? in : result; last_output[i] = output[i] = ret; diff --git a/ftnoir_filter_accela/ftnoir_filter_accela.h b/ftnoir_filter_accela/ftnoir_filter_accela.h index aa10e161..e45af03a 100644 --- a/ftnoir_filter_accela/ftnoir_filter_accela.h +++ b/ftnoir_filter_accela/ftnoir_filter_accela.h @@ -1,6 +1,7 @@ #pragma once #include "ui_ftnoir_accela_filtercontrols.h" #include "opentrack/plugin-api.hpp" +#include "qfunctionconfigurator/functionconfig.h" #include #include #include @@ -26,14 +27,13 @@ class FTNoIR_Filter : public IFilter public: FTNoIR_Filter(); void filter(const double* input, double *output); + Map rot, trans; private: settings s; bool first_run; double last_output[6]; double smoothed_input[6]; Timer t; - - double f(double val, const double gains[][2]); }; class FilterControls: public IFilterDialog -- cgit v1.2.3 From 891f5d68a5bc8bdd565f13cd38160948d8a7fb6a Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Wed, 1 Jul 2015 11:16:57 +0200 Subject: qfc: adapt step size to bound --- qfunctionconfigurator/qfunctionconfigurator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qfunctionconfigurator/qfunctionconfigurator.cpp b/qfunctionconfigurator/qfunctionconfigurator.cpp index c1f11ffa..b230cfb1 100644 --- a/qfunctionconfigurator/qfunctionconfigurator.cpp +++ b/qfunctionconfigurator/qfunctionconfigurator.cpp @@ -131,8 +131,8 @@ void QFunctionConfigurator::drawFunction() QPen pen(spline_color, 1.2, Qt::SolidLine); - static constexpr double step = 1.02; const double max = _config->maxInput(); + const double step = std::max(.1, max / 300.); QPointF prev = point_to_pixel(QPointF(0, 0)); for (double i = 0; i < max; i += step) { -- cgit v1.2.3 From ed92ea867bfedef890ce48b26a00bad0bfc79caf Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Wed, 1 Jul 2015 11:17:08 +0200 Subject: qfc: always draw line to last point --- qfunctionconfigurator/qfunctionconfigurator.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/qfunctionconfigurator/qfunctionconfigurator.cpp b/qfunctionconfigurator/qfunctionconfigurator.cpp index b230cfb1..e1c40396 100644 --- a/qfunctionconfigurator/qfunctionconfigurator.cpp +++ b/qfunctionconfigurator/qfunctionconfigurator.cpp @@ -141,6 +141,11 @@ void QFunctionConfigurator::drawFunction() drawLine(&painter, prev, cur, pen); prev = cur; } + if (points.size()) + { + auto last = point_to_pixel(points[points.size()-1]); + drawLine(&painter, prev, last, pen); + } } void QFunctionConfigurator::paintEvent(QPaintEvent *e) -- cgit v1.2.3 From 14a972653d1db7a03de7e2ae9ac19e047d814893 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Wed, 1 Jul 2015 12:11:27 +0200 Subject: cmake: adjust install perms --- CMakeLists.txt | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1662c89f..2ec6dc54 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -178,6 +178,8 @@ endif() # ---- +set(opentrack-perms PERMISSIONS WORLD_READ WORLD_EXECUTE OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE) + if(WIN32) if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_GNUCC) set(CMAKE_RC_COMPILER_INIT i686-w64-mingw32-windres) @@ -470,8 +472,9 @@ endif() install(DIRECTORY ${CMAKE_SOURCE_DIR}/3rdparty-notices DESTINATION .) -install(FILES "${CMAKE_SOURCE_DIR}/bin/freetrackclient.dll" DESTINATION .) -install(FILES "${CMAKE_SOURCE_DIR}/bin/NPClient.dll" "${CMAKE_SOURCE_DIR}/bin/NPClient64.dll" "${CMAKE_SOURCE_DIR}/bin/TrackIR.exe" DESTINATION .) +install(FILES "${CMAKE_SOURCE_DIR}/bin/freetrackclient.dll" DESTINATION . ${opentrack-perms}) +install(FILES "${CMAKE_SOURCE_DIR}/bin/NPClient.dll" "${CMAKE_SOURCE_DIR}/bin/NPClient64.dll" "${CMAKE_SOURCE_DIR}/bin/TrackIR.exe" DESTINATION . + ${opentrack-perms}) install(DIRECTORY "${CMAKE_SOURCE_DIR}/bin/settings" "${CMAKE_SOURCE_DIR}/clientfiles" DESTINATION .) if(NOT WIN32 AND SDK_WINE_PREFIX AND NOT SDK_WINE_NO_WRAPPER) @@ -482,7 +485,7 @@ endif() install(TARGETS opentrack DESTINATION .) if(SDK_VJOY) - install(FILES "${SDK_VJOY}/VJoy.dll" DESTINATION . PERMISSIONS WORLD_READ WORLD_EXECUTE OWNER_WRITE OWNER_READ OWNER_EXECUTE) + install(FILES "${SDK_VJOY}/VJoy.dll" DESTINATION . ${opentrack-perms}) endif() if(WIN32) -- cgit v1.2.3 From 64878fd0941bea05deaa12746ba85b00415b6282 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Wed, 1 Jul 2015 12:12:18 +0200 Subject: freetrack: use volatile --- bin/NPClient.dll | Bin 18944 -> 15872 bytes bin/NPClient64.dll | Bin 20480 -> 19968 bytes csv/csv.cpp | 3 +- freetrackclient/fttypes.h | 52 +++++++------- ftnoir_protocol_ft/ftnoir_protocol_ft.cpp | 78 ++++++++++++--------- .../opentrack-wrapper-wine-main.cxx | 30 ++++---- 6 files changed, 83 insertions(+), 80 deletions(-) diff --git a/bin/NPClient.dll b/bin/NPClient.dll index 47172c22..bf971c03 100755 Binary files a/bin/NPClient.dll and b/bin/NPClient.dll differ diff --git a/bin/NPClient64.dll b/bin/NPClient64.dll index f7b30a90..fd3164e5 100755 Binary files a/bin/NPClient64.dll and b/bin/NPClient64.dll differ diff --git a/csv/csv.cpp b/csv/csv.cpp index 71db8ecb..e55b429c 100644 --- a/csv/csv.cpp +++ b/csv/csv.cpp @@ -97,7 +97,8 @@ void CSV::getGameData( const int id, unsigned char* table, QString& gamename) QString gameID = QString::number(id); /* zero table first, in case unknown game is connecting */ - memset(table, 0, 8); + for (int i = 0; i < 8; i++) + table[i] = 0; QStringList gameLine; qDebug() << "getGameData, ID = " << gameID; diff --git a/freetrackclient/fttypes.h b/freetrackclient/fttypes.h index ad974110..8611017a 100644 --- a/freetrackclient/fttypes.h +++ b/freetrackclient/fttypes.h @@ -31,39 +31,39 @@ typedef __int32 int32_t; /* only 6 headpose floats and the data id are filled -sh */ typedef struct __FTData { - int DataID; - int CamWidth; - int CamHeight; + volatile int DataID; + volatile int CamWidth; + volatile int CamHeight; /* virtual pose */ - float Yaw; /* positive yaw to the left */ - float Pitch; /* positive pitch up */ - float Roll; /* positive roll to the left */ - float X; - float Y; - float Z; + volatile float Yaw; /* positive yaw to the left */ + volatile float Pitch; /* positive pitch up */ + volatile float Roll; /* positive roll to the left */ + volatile float X; + volatile float Y; + volatile float Z; /* raw pose with no smoothing, sensitivity, response curve etc. */ - float RawYaw; - float RawPitch; - float RawRoll; - float RawX; - float RawY; - float RawZ; + volatile float RawYaw; + volatile float RawPitch; + volatile float RawRoll; + volatile float RawX; + volatile float RawY; + volatile float RawZ; /* raw points, sorted by Y, origin top left corner */ - float X1; - float Y1; - float X2; - float Y2; - float X3; - float Y3; - float X4; - float Y4; + volatile float X1; + volatile float Y1; + volatile float X2; + volatile float Y2; + volatile float X3; + volatile float Y3; + volatile float X4; + volatile float Y4; } FTData; /* we add some shit at the end for other legacy proto, sadly */ typedef struct __FTHeap { FTData data; - int32_t GameID; - unsigned char table[8]; - int32_t GameID2; + volatile int32_t GameID; + volatile unsigned char table[8]; + volatile int32_t GameID2; } FTHeap; diff --git a/ftnoir_protocol_ft/ftnoir_protocol_ft.cpp b/ftnoir_protocol_ft/ftnoir_protocol_ft.cpp index 312cf127..56ae061f 100644 --- a/ftnoir_protocol_ft/ftnoir_protocol_ft.cpp +++ b/ftnoir_protocol_ft/ftnoir_protocol_ft.cpp @@ -54,44 +54,51 @@ void FTNoIR_Protocol::pose(const double* headpose) { float tx = headpose[TX] * 10.f; float ty = headpose[TY] * 10.f; float tz = headpose[TZ] * 10.f; - - shm.lock(); - - pMemData->data.RawX = 0; - pMemData->data.RawY = 0; - pMemData->data.RawZ = 0; - pMemData->data.RawPitch = 0; - pMemData->data.RawYaw = 0; - pMemData->data.RawRoll = 0; - - pMemData->data.X = tx; - pMemData->data.Y = ty; - pMemData->data.Z = tz; - pMemData->data.Yaw = yaw; - pMemData->data.Pitch = pitch; - pMemData->data.Roll = roll; - - pMemData->data.X1 = pMemData->data.DataID; - pMemData->data.X2 = 0; - pMemData->data.X3 = 0; - pMemData->data.X4 = 0; - pMemData->data.Y1 = 0; - pMemData->data.Y2 = 0; - pMemData->data.Y3 = 0; - pMemData->data.Y4 = 0; - - if (intGameID != pMemData->GameID) + + FTHeap* ft = pMemData; + FTData* data = &ft->data; + + data->RawX = 0; + data->RawY = 0; + data->RawZ = 0; + data->RawPitch = 0; + data->RawYaw = 0; + data->RawRoll = 0; + + data->X = tx; + data->Y = ty; + data->Z = tz; + data->Yaw = yaw; + data->Pitch = pitch; + data->Roll = roll; + + data->X1 = data->DataID; + data->X2 = 0; + data->X3 = 0; + data->X4 = 0; + data->Y1 = 0; + data->Y2 = 0; + data->Y3 = 0; + data->Y4 = 0; + + int32_t id = ft->GameID; + + if (intGameID != id) { QString gamename; - CSV::getGameData(pMemData->GameID, pMemData->table, gamename); - pMemData->GameID2 = pMemData->GameID; - intGameID = pMemData->GameID; + { + unsigned char table[8]; + for (int i = 0; i < 8; i++) table[i] = pMemData->table[i]; + CSV::getGameData(id, table, gamename); + for (int i = 0; i < 8; i++) pMemData->table[i] = table[i]; + } + ft->GameID2 = id; + intGameID = id; QMutexLocker foo(&this->game_name_mutex); connected_game = gamename; } - - pMemData->data.DataID += 1; - shm.unlock(); + + data->DataID += 1; } void FTNoIR_Protocol::start_tirviews() { @@ -165,9 +172,10 @@ bool FTNoIR_Protocol::correct() pMemData->data.CamWidth = 100; pMemData->data.CamHeight = 250; pMemData->GameID2 = 0; - memset(pMemData->table, 0, 8); + for (int i = 0; i < 8; i++) + pMemData->table[i] = 0; - return true; + return true; } extern "C" OPENTRACK_EXPORT IProtocol* GetConstructor() diff --git a/ftnoir_protocol_wine/opentrack-wrapper-wine-main.cxx b/ftnoir_protocol_wine/opentrack-wrapper-wine-main.cxx index d5d03011..896d8078 100644 --- a/ftnoir_protocol_wine/opentrack-wrapper-wine-main.cxx +++ b/ftnoir_protocol_wine/opentrack-wrapper-wine-main.cxx @@ -40,27 +40,23 @@ private: int main(void) { - ShmPosix lck_posix(WINE_SHM_NAME, WINE_MTX_NAME, sizeof(WineSHM)); + ShmPosix lck_posix(WINE_SHM_NAME, WINE_MTX_NAME, sizeof(WineSHM)); ShmWine lck_wine("FT_SharedMem", "FT_Mutext", sizeof(FTHeap)); if(!lck_posix.success()) { - printf("Can't open posix map: %d\n", errno); - return 1; - } - if(!lck_wine.success()) { - printf("Can't open Wine map\n"); - return 1; - } + printf("Can't open posix map: %d\n", errno); + return 1; + } + if(!lck_wine.success()) { + printf("Can't open Wine map\n"); + return 1; + } WineSHM* shm_posix = (WineSHM*) lck_posix.ptr(); FTHeap* shm_wine = (FTHeap*) lck_wine.ptr(); FTData* data = &shm_wine->data; create_registry_key(); - while (1) { - lck_posix.lock(); - if (shm_posix->stop) { - lck_posix.unlock(); - break; - } - lck_wine.lock(); + while (1) { + if (shm_posix->stop) + break; data->Yaw = -shm_posix->data[Yaw]; data->Pitch = -shm_posix->data[Pitch]; data->Roll = shm_posix->data[Roll]; @@ -74,8 +70,6 @@ int main(void) shm_posix->gameid = shm_wine->GameID; for (int i = 0; i < 8; i++) shm_wine->table[i] = shm_posix->table[i]; - lck_wine.unlock(); - lck_posix.unlock(); (void) Sleep(4); - } + } } -- cgit v1.2.3 From 66bcf1db948ca409b7474a4efc9d447f61353060 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Wed, 1 Jul 2015 13:16:48 +0200 Subject: pt: use iterative contour detector --- ftnoir_tracker_pt/point_extractor.cpp | 54 ++++++++++++++++++++++++++++------- 1 file changed, 43 insertions(+), 11 deletions(-) diff --git a/ftnoir_tracker_pt/point_extractor.cpp b/ftnoir_tracker_pt/point_extractor.cpp index 86454729..71023a38 100644 --- a/ftnoir_tracker_pt/point_extractor.cpp +++ b/ftnoir_tracker_pt/point_extractor.cpp @@ -8,6 +8,9 @@ #include "point_extractor.h" #include +#ifdef DEBUG_EXTRACTION +# include "opentrack/timer.hpp" +#endif using namespace cv; using namespace std; @@ -39,15 +42,15 @@ std::vector PointExtractor::extract_points(Mat& frame) // that's applicable to poor lighting conditions. static constexpr int diff = 20; - static constexpr int steps = 10; - static constexpr int successes = 8; + static constexpr int steps = 5; + static constexpr int successes = 5; int thres = s.threshold; struct blob { - double max_radius; std::vector pos; std::vector confids; + std::vector areas; cv::Vec2d effective_pos() const { @@ -56,13 +59,13 @@ std::vector PointExtractor::extract_points(Mat& frame) double norm = 0; for (unsigned i = 0; i < pos.size(); i++) { - x += pos[i][0] * confids[i]; - y += pos[i][1] * confids[i]; - norm += confids[i]; + const double w = confids[i] * areas[i]; + x += pos[i][0] * w; + y += pos[i][1] * w; + norm += w; } cv::Vec2d ret(x, y); ret *= 1./norm; - //qDebug() << "ret" << ret[0] << ret[1] << "norm" << norm << "count" << pos.size(); return ret; } }; @@ -73,7 +76,8 @@ std::vector PointExtractor::extract_points(Mat& frame) cv::Vec2d pos; double confid; bool taken; - simple_blob(double radius, const cv::Vec2d& pos, double confid) : radius(radius), pos(pos), confid(confid), taken(false) + double area; + simple_blob(double radius, const cv::Vec2d& pos, double confid, double area) : radius(radius), pos(pos), confid(confid), taken(false), area(area) { //qDebug() << "radius" << radius << "pos" << pos[0] << pos[1] << "confid" << confid; } @@ -85,6 +89,12 @@ std::vector PointExtractor::extract_points(Mat& frame) } static std::vector merge(std::vector& blobs) { +#ifdef DEBUG_EXTRACTION + static Timer t; + bool debug = t.elapsed_ms() > 100; + if (debug) t.start(); +#endif + std::vector ret; for (unsigned i = 0; i < blobs.size(); i++) { @@ -95,7 +105,7 @@ std::vector PointExtractor::extract_points(Mat& frame) blob b_; b_.pos.push_back(b.pos); b_.confids.push_back(b.confid); - b_.max_radius = b.radius; + b_.areas.push_back(b.area); for (unsigned j = i+1; j < blobs.size(); j++) { @@ -107,12 +117,29 @@ std::vector PointExtractor::extract_points(Mat& frame) b2.taken = true; b_.pos.push_back(b2.pos); b_.confids.push_back(b2.confid); - b_.max_radius = std::max(b_.max_radius, b2.radius); + b_.areas.push_back(b2.area); } } if (b_.pos.size() >= successes) ret.push_back(b_); } +#ifdef DEBUG_EXTRACTION + if (debug) + { + double diff = 0; + for (unsigned j = 0; j < ret.size(); j++) + { + auto& b = ret[j]; + cv::Vec2d pos = b.effective_pos(); + for (unsigned i = 0; i < b.pos.size(); i++) + { + auto tmp = pos - b.pos[i]; + diff += std::abs(tmp.dot(tmp)); + } + } + qDebug() << "diff" << diff; + } +#endif return ret; } }; @@ -136,8 +163,13 @@ std::vector PointExtractor::extract_points(Mat& frame) std::vector> contours; cv::findContours(frame_bin_, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE); + int cnt = 0; + for (auto& c : contours) { + if (cnt++ > 30) + break; + auto m = cv::moments(cv::Mat(c)); const double area = m.m00; if (area == 0.) @@ -170,7 +202,7 @@ std::vector PointExtractor::extract_points(Mat& frame) confid = imin / imax; } } - blobs.push_back(simple_blob(radius, pos, confid)); + blobs.push_back(simple_blob(radius, pos, confid, area)); } } -- cgit v1.2.3 From 8c5a34f9002f45bdda2f3e7240faf63766bc729a Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Wed, 1 Jul 2015 13:35:10 +0200 Subject: pt: fix sqrt eps --- ftnoir_tracker_pt/point_extractor.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/ftnoir_tracker_pt/point_extractor.cpp b/ftnoir_tracker_pt/point_extractor.cpp index 71023a38..dd75852c 100644 --- a/ftnoir_tracker_pt/point_extractor.cpp +++ b/ftnoir_tracker_pt/point_extractor.cpp @@ -72,20 +72,19 @@ std::vector PointExtractor::extract_points(Mat& frame) struct simple_blob { - double radius; + double radius_2; cv::Vec2d pos; double confid; bool taken; double area; - simple_blob(double radius, const cv::Vec2d& pos, double confid, double area) : radius(radius), pos(pos), confid(confid), taken(false), area(area) + simple_blob(double radius, const cv::Vec2d& pos, double confid, double area) : radius_2(radius*radius), pos(pos), confid(confid), taken(false), area(area) { //qDebug() << "radius" << radius << "pos" << pos[0] << pos[1] << "confid" << confid; } bool inside(const simple_blob& other) { cv::Vec2d tmp = pos - other.pos; - double p = sqrt(1e-4 + tmp.dot(tmp)); - return p < radius; + return tmp.dot(tmp) < radius_2; } static std::vector merge(std::vector& blobs) { -- cgit v1.2.3 From e94be88e28b41610bab983a1cbf8f31133a4ced8 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Wed, 1 Jul 2015 14:25:34 +0200 Subject: pt: show color frame in widget --- ftnoir_tracker_pt/point_extractor.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/ftnoir_tracker_pt/point_extractor.cpp b/ftnoir_tracker_pt/point_extractor.cpp index dd75852c..e81e3aa0 100644 --- a/ftnoir_tracker_pt/point_extractor.cpp +++ b/ftnoir_tracker_pt/point_extractor.cpp @@ -215,11 +215,14 @@ std::vector PointExtractor::extract_points(Mat& frame) points.push_back(p); } + vector channels_; + cv::split(frame, channels_); // draw output image + Mat frame_bin_ = frame_bin * .5; vector channels; - channels.push_back(frame_gray + frame_bin); - channels.push_back(frame_gray - frame_bin); - channels.push_back(frame_gray - frame_bin); + channels.push_back(channels_[0] + frame_bin_); + channels.push_back(channels_[1] - frame_bin_); + channels.push_back(channels_[2] - frame_bin_); merge(channels, frame); return points; -- cgit v1.2.3