diff options
Diffstat (limited to 'tracker-pt/module')
| -rw-r--r-- | tracker-pt/module/camera.cpp | 31 | ||||
| -rw-r--r-- | tracker-pt/module/camera.h | 8 | ||||
| -rw-r--r-- | tracker-pt/module/frame.cpp | 6 | ||||
| -rw-r--r-- | tracker-pt/module/frame.hpp | 14 | ||||
| -rw-r--r-- | tracker-pt/module/module.cpp | 16 | ||||
| -rw-r--r-- | tracker-pt/module/module.hpp | 4 | ||||
| -rw-r--r-- | tracker-pt/module/point_extractor.cpp | 156 | ||||
| -rw-r--r-- | tracker-pt/module/point_extractor.h | 9 | 
8 files changed, 136 insertions, 108 deletions
| diff --git a/tracker-pt/module/camera.cpp b/tracker-pt/module/camera.cpp index e2edfcb6..1afecc92 100644 --- a/tracker-pt/module/camera.cpp +++ b/tracker-pt/module/camera.cpp @@ -18,7 +18,7 @@  #include <cstdlib> -using namespace pt_module; +namespace pt_module {  Camera::Camera(const QString& module_name) : s { module_name }  { @@ -56,16 +56,16 @@ Camera::result Camera::get_frame(pt_frame& frame_)  {      cv::Mat& frame = frame_.as<Frame>()->mat; -    const bool new_frame = _get_frame(frame); +    const bool new_frame = get_frame_(frame);      if (new_frame)      { -        const double dt = t.elapsed_seconds(); +        const f dt = (f)t.elapsed_seconds();          t.start();          // measure fps of valid frames -        constexpr double RC = .1; // seconds -        const double alpha = dt/(dt + RC); +        constexpr f RC = f{1}/10; // seconds +        const f alpha = dt/(dt + RC);          if (dt_mean < dt_eps)              dt_mean = dt; @@ -88,7 +88,7 @@ bool Camera::start(int idx, int fps, int res_x, int res_y)      if (idx >= 0 && fps >= 0 && res_x >= 0 && res_y >= 0)      {          if (cam_desired.idx != idx || -            cam_desired.fps != fps || +            (int)cam_desired.fps != fps ||              cam_desired.res_x != res_x ||              cam_desired.res_y != res_y ||              !cap || !cap->isOpened() || !cap->grab()) @@ -104,10 +104,12 @@ bool Camera::start(int idx, int fps, int res_x, int res_y)              cap = camera_ptr(new cv::VideoCapture(idx)); -            if (cam_desired.res_x) +            if (cam_desired.res_x > 0 && cam_desired.res_y > 0) +            {                  cap->set(cv::CAP_PROP_FRAME_WIDTH,  res_x); -            if (cam_desired.res_y)                  cap->set(cv::CAP_PROP_FRAME_HEIGHT, res_y); +            } +              if (fps > 0)                  cap->set(cv::CAP_PROP_FPS, fps); @@ -120,7 +122,7 @@ bool Camera::start(int idx, int fps, int res_x, int res_y)                  cv::Mat tmp; -                if (_get_frame(tmp)) +                if (get_frame_(tmp))                  {                      t.start();                      return true; @@ -141,13 +143,13 @@ bool Camera::start(int idx, int fps, int res_x, int res_y)  void Camera::stop()  {      cap = nullptr; -    desired_name = QString(); -    active_name = QString(); -    cam_info = pt_camera_info(); -    cam_desired = pt_camera_info(); +    desired_name = QString{}; +    active_name = QString{}; +    cam_info = {}; +    cam_desired = {};  } -bool Camera::_get_frame(cv::Mat& frame) +bool Camera::get_frame_(cv::Mat& frame)  {      if (cap && cap->isOpened())      { @@ -171,3 +173,4 @@ void Camera::camera_deleter::operator()(cv::VideoCapture* cap)      }  } +} // ns pt_module diff --git a/tracker-pt/module/camera.h b/tracker-pt/module/camera.h index f8f140de..2ea633d0 100644 --- a/tracker-pt/module/camera.h +++ b/tracker-pt/module/camera.h @@ -33,13 +33,13 @@ struct Camera final : pt_camera      QString get_desired_name() const override;      QString get_active_name() const override; -    void set_fov(double value) override { fov = value; } +    void set_fov(f value) override { fov = value; }      void show_camera_settings() override;  private: -    [[nodiscard]] bool _get_frame(cv::Mat& Frame); +    [[nodiscard]] bool get_frame_(cv::Mat& frame); -    double dt_mean = 0, fov = 30; +    f dt_mean = 0, fov = 30;      Timer t;      pt_camera_info cam_info;      pt_camera_info cam_desired; @@ -56,7 +56,7 @@ private:      pt_settings s; -    static constexpr inline double dt_eps = 1./256; +    static constexpr f dt_eps = f{1}/256;  };  } // ns pt_module diff --git a/tracker-pt/module/frame.cpp b/tracker-pt/module/frame.cpp index 6734edf6..c88099f1 100644 --- a/tracker-pt/module/frame.cpp +++ b/tracker-pt/module/frame.cpp @@ -4,7 +4,7 @@  #include <opencv2/imgproc.hpp> -using namespace pt_module; +namespace pt_module {  Preview& Preview::operator=(const pt_frame& frame_)  { @@ -52,7 +52,7 @@ QImage Preview::get_bitmap()                    QImage::Format_ARGB32);  } -void Preview::draw_head_center(double x, double y) +void Preview::draw_head_center(f x, f y)  {      auto [px_, py_] = to_pixel_pos(x, y, frame_copy.cols, frame_copy.rows); @@ -76,3 +76,5 @@ void Preview::ensure_size(cv::Mat& frame, int w, int h, int type)      if (frame.cols != w || frame.rows != h)          frame = cv::Mat(h, w, type);  } + +} // ns pt_module diff --git a/tracker-pt/module/frame.hpp b/tracker-pt/module/frame.hpp index 49dde49e..89334599 100644 --- a/tracker-pt/module/frame.hpp +++ b/tracker-pt/module/frame.hpp @@ -5,6 +5,11 @@  #include <opencv2/core.hpp>  #include <QImage> +#ifdef __clang__ +#   pragma clang diagnostic push +#   pragma clang diagnostic ignored "-Wweak-vtables" +#endif +  namespace pt_module {  struct Frame final : pt_frame @@ -21,7 +26,7 @@ struct Preview final : pt_preview      Preview& operator=(const pt_frame& frame) override;      QImage get_bitmap() override; -    void draw_head_center(double x, double y) override; +    void draw_head_center(f x, f y) override;      operator cv::Mat&() { return frame_copy; }      operator cv::Mat const&() const { return frame_copy; } @@ -29,8 +34,11 @@ struct Preview final : pt_preview  private:      static void ensure_size(cv::Mat& frame, int w, int h, int type); -    bool fresh = true; -    cv::Mat frame_copy, frame_color, frame_out, frame_out2; +    cv::Mat frame_copy, frame_out;  };  } // ns pt_module + +#ifdef __clang__ +#   pragma clang diagnostic pop +#endif diff --git a/tracker-pt/module/module.cpp b/tracker-pt/module/module.cpp index 4731175a..f665face 100644 --- a/tracker-pt/module/module.cpp +++ b/tracker-pt/module/module.cpp @@ -12,7 +12,11 @@  static const QString module_name = "tracker-pt"; -using namespace pt_module; +#ifdef __clang__ +#   pragma clang diagnostic ignored "-Wweak-vtables" +#endif + +namespace pt_module {  struct pt_module_traits final : pt_runtime_traits  { @@ -54,13 +58,15 @@ struct dialog_pt : TrackerDialog_PT      dialog_pt();  }; -// ns pt_module - -using namespace pt_module; -  dialog_pt::dialog_pt() : TrackerDialog_PT(module_name) {}  QString metadata_pt::name() { return tr("PointTracker 1.1"); }  QIcon metadata_pt::icon() { return QIcon(":/Resources/Logo_IR.png"); } +} + +// ns pt_module + +using namespace pt_module; +  OPENTRACK_DECLARE_TRACKER(tracker_pt, dialog_pt, metadata_pt) diff --git a/tracker-pt/module/module.hpp b/tracker-pt/module/module.hpp index 3afe8bc9..0b3f12cf 100644 --- a/tracker-pt/module/module.hpp +++ b/tracker-pt/module/module.hpp @@ -13,8 +13,8 @@ class OTR_GENERIC_EXPORT metadata_pt : public Metadata  {      Q_OBJECT -    QString name(); -    QIcon icon(); +    QString name() override; +    QIcon icon() override;  };  } // ns pt_module diff --git a/tracker-pt/module/point_extractor.cpp b/tracker-pt/module/point_extractor.cpp index a634768c..596b3d93 100644 --- a/tracker-pt/module/point_extractor.cpp +++ b/tracker-pt/module/point_extractor.cpp @@ -29,8 +29,7 @@  #include <QDebug> -using namespace types; -using namespace pt_module; +using namespace numeric_types;  // meanshift code written by Michael Welter @@ -50,10 +49,10 @@ corresponding location is a good candidate for the extracted point.  The idea similar to the window scaling suggested in  Berglund et al. "Fast, bias-free   algorithm for tracking single particles with variable size and shape." (2008).  */ -static cv::Vec2d MeanShiftIteration(const cv::Mat &frame_gray, const vec2 ¤t_center, f filter_width) +static vec2 MeanShiftIteration(const cv::Mat1b &frame_gray, const vec2 ¤t_center, f filter_width)  {      // Most amazingly this function runs faster with doubles than with floats. -    const f s = 1.0 / filter_width; +    const f s = 1 / filter_width;      f m = 0;      vec2 com { 0, 0  }; @@ -63,12 +62,12 @@ static cv::Vec2d MeanShiftIteration(const cv::Mat &frame_gray, const vec2 &curre          for (int j = 0; j < frame_gray.cols; j++)          {              f val = frame_ptr[j]; -            val = val * val; // taking the square wights brighter parts of the image stronger. +            val = val * val; // taking the square weighs brighter parts of the image stronger.              {                  f dx = (j - current_center[0])*s;                  f dy = (i - current_center[1])*s; -                f f = std::fmax(0, 1 - dx*dx - dy*dy); -                val *= f; +                f max = std::fmax(f{0}, 1 - dx*dx - dy*dy); +                val *= max;              }              m += val;              com[0] += j * val; @@ -77,13 +76,15 @@ static cv::Vec2d MeanShiftIteration(const cv::Mat &frame_gray, const vec2 &curre      }      if (m > f(.1))      { -        com *= f(1) / m; +        com *= 1 / m;          return com;      }      else          return current_center;  } +namespace pt_module { +  PointExtractor::PointExtractor(const QString& module_name) : s(module_name)  {      blobs.reserve(max_blobs); @@ -92,7 +93,7 @@ PointExtractor::PointExtractor(const QString& module_name) : s(module_name)  void PointExtractor::ensure_channel_buffers(const cv::Mat& orig_frame)  {      if (ch[0].rows != orig_frame.rows || ch[0].cols != orig_frame.cols) -        for (unsigned k = 0; k < 3; k++) +        for (unsigned k = 0; k < 3; k++) // NOLINT(modernize-loop-convert)              ch[k] = cv::Mat1b(orig_frame.rows, orig_frame.cols);  } @@ -108,7 +109,7 @@ void PointExtractor::ensure_buffers(const cv::Mat& frame)      }  } -void PointExtractor::extract_single_channel(const cv::Mat& orig_frame, int idx, cv::Mat& dest) +void PointExtractor::extract_single_channel(const cv::Mat& orig_frame, int idx, cv::Mat1b& dest)  {      ensure_channel_buffers(orig_frame); @@ -119,13 +120,6 @@ void PointExtractor::extract_single_channel(const cv::Mat& orig_frame, int idx,      cv::mixChannels(&orig_frame, 1, &dest, 1, from_to, 1);  } -void PointExtractor::extract_channels(const cv::Mat& orig_frame, const int* order, int order_npairs) -{ -    ensure_channel_buffers(orig_frame); - -    cv::mixChannels(&orig_frame, 1, (cv::Mat*) ch, order_npairs, order, order_npairs); -} -  void PointExtractor::color_to_grayscale(const cv::Mat& frame, cv::Mat1b& output)  {      switch (s.blob_color) @@ -147,15 +141,15 @@ void PointExtractor::color_to_grayscale(const cv::Mat& frame, cv::Mat1b& output)      }      case pt_color_average:      { -        const int W = frame.cols, H = frame.rows; -        const cv::Mat tmp = frame.reshape(1, W * H); -        cv::Mat output_ = output.reshape(1, W * H); -        cv::reduce(tmp, output_, 1, cv::REDUCE_AVG); +        const int W = frame.cols, H = frame.rows, sz = W*H; +        cv::reduce(frame.reshape(1, sz), +                   output.reshape(1, sz), +                   1, cv::REDUCE_AVG);          break;      }      default:          eval_once(qDebug() << "wrong pt_color_type enum value" << int(s.blob_color)); -        /*FALLTHROUGH*/ +    [[fallthrough]];      case pt_color_natural:          cv::cvtColor(frame, output, cv::COLOR_BGR2GRAY);          break; @@ -182,31 +176,80 @@ void PointExtractor::threshold_image(const cv::Mat& frame_gray, cv::Mat1b& outpu                       cv::noArray(),                       hist,                       1, -                     (int const*) &hist_size, +                     &hist_size,                       &ranges);          const f radius = (f) threshold_radius_value(frame_gray.cols, frame_gray.rows, threshold_slider_value);          float const* const __restrict ptr = hist.ptr<float>(0); -        const unsigned area = uround(3 * M_PI * radius*radius); +        const unsigned area = uround(3 * pi * radius*radius);          const unsigned sz = unsigned(hist.cols * hist.rows); -        unsigned thres = 32; +        constexpr unsigned min_thres = 64; +        unsigned thres = min_thres;          for (unsigned i = sz-1, cnt = 0; i > 32; i--)          { -            cnt += ptr[i]; +            cnt += (unsigned)ptr[i];              if (cnt >= area)                  break;              thres = i;          } +        if (thres > min_thres) +            thres = uround(thres * .8); +          cv::threshold(frame_gray, output, thres, 255, cv::THRESH_BINARY);      }  } +static void draw_blobs(cv::Mat& preview_frame, const blob* blobs, unsigned nblobs, cv::Size size) +{ +    for (unsigned k = 0; k < nblobs; k++) +    { +        const blob& b = blobs[k]; + +        if (b.radius < 0) +            continue; + +        const f dpi = preview_frame.cols / f(320); +        const f offx = 10 * dpi, offy = f{7.5} * dpi; + +        const f cx = preview_frame.cols / f(size.width), +            cy = preview_frame.rows / f(size.height), +            c_ = (cx+cy)/2; + +        static constexpr unsigned fract_bits = 16; +        static constexpr double c_fract(1 << fract_bits); + +        cv::Point p(iround(b.pos[0] * cx * c_fract), iround(b.pos[1] * cy * c_fract)); + +        auto circle_color = k >= PointModel::N_POINTS +                            ? cv::Scalar(192, 192, 192) +                            : cv::Scalar(255, 255, 0); + +        const f overlay_size = dpi > 1.5 ? 2 : 1; + +        cv::circle(preview_frame, p, iround((b.radius + 3.3) * c_ * c_fract), +                   circle_color, (int)overlay_size, +                   cv::LINE_AA, fract_bits); + +        char buf[16]; +        buf[sizeof(buf)-1] = '\0'; +        std::snprintf(buf, sizeof(buf) - 1, "%.2fpx", b.radius); + +        auto text_color = k >= PointModel::N_POINTS +                          ? cv::Scalar(160, 160, 160) +                          : cv::Scalar(0, 0, 255); + +        cv::Point pos(iround(b.pos[0]*cx+offx), iround(b.pos[1]*cy+offy)); +        cv::putText(preview_frame, buf, pos, +                    cv::FONT_HERSHEY_PLAIN, overlay_size, text_color, +                    1); +    } +} +  void PointExtractor::extract_points(const pt_frame& frame_, pt_preview& preview_frame_, std::vector<vec2>& points)  {      const cv::Mat& frame = frame_.as_const<Frame>()->mat; -    cv::Mat& preview_frame = *preview_frame_.as<Preview>();      ensure_buffers(frame);      color_to_grayscale(frame, frame_gray_unmasked); @@ -219,8 +262,8 @@ void PointExtractor::extract_points(const pt_frame& frame_, pt_preview& preview_      threshold_image(frame_gray_unmasked, frame_bin);      frame_gray_unmasked.copyTo(frame_gray, frame_bin); -    const f region_size_min = s.min_point_size; -    const f region_size_max = s.max_point_size; +    const f region_size_min = (f)s.min_point_size; +    const f region_size_max = (f)s.max_point_size;      unsigned idx = 0; @@ -265,12 +308,12 @@ void PointExtractor::extract_points(const pt_frame& frame_, pt_preview& preview_                  }              } -            const double radius = std::sqrt(cnt / M_PI); +            const double radius = std::sqrt(cnt / pi);              if (radius > region_size_max || radius < region_size_min)                  continue;              blobs.emplace_back(radius, -                               vec2(rect.width/2., rect.height/2.), +                               vec2(rect.width/f(2), rect.height/f(2)),                                 std::pow(f(norm), f(1.1))/cnt,                                 rect); @@ -280,9 +323,7 @@ void PointExtractor::extract_points(const pt_frame& frame_, pt_preview& preview_              // XXX we could go to the next scanline unless the points are really small.              // i'd expect each point being present on at least one unique scanline              // but it turns out some people are using 2px points -sh 20180110 -#if BROKEN && 0 -            break; -#endif +            //break;          }      }  end: @@ -296,7 +337,7 @@ end:      for (idx = 0; idx < sz; ++idx)      { -        blob &b = blobs[idx]; +        blob& b = blobs[idx];          cv::Rect rect = b.rect;          rect.x -= rect.width / 2; @@ -311,14 +352,14 @@ end:          static constexpr f radius_c = f(1.75);          const f kernel_radius = b.radius * radius_c; -        vec2 pos(rect.width/2., rect.height/2.); // position relative to ROI. +        vec2 pos(rect.width/f{2}, rect.height/f{2}); // position relative to ROI.          for (int iter = 0; iter < 10; ++iter)          {              vec2 com_new = MeanShiftIteration(frame_roi, pos, kernel_radius);              vec2 delta = com_new - pos;              pos = com_new; -            if (delta.dot(delta) < 1e-2) +            if (delta.dot(delta) < f(1e-3))                  break;          } @@ -326,43 +367,10 @@ end:          b.pos[1] = pos[1] + rect.y;      } -    for (unsigned k = 0; k < blobs.size(); k++) -    { -        blob& b = blobs[k]; - -        const f dpi = preview_frame.cols / f(320); -        const f offx = 10 * dpi, offy = 7.5 * dpi; - -        const f cx = preview_frame.cols / f(frame.cols), -                cy = preview_frame.rows / f(frame.rows), -                c_ = (cx+cy)/2; - -        static constexpr unsigned fract_bits = 16; -        static constexpr double c_fract(1 << fract_bits); - -        cv::Point p(iround(b.pos[0] * cx * c_fract), iround(b.pos[1] * cy * c_fract)); - -        auto circle_color = k >= PointModel::N_POINTS -                            ? cv::Scalar(192, 192, 192) -                            : cv::Scalar(255, 255, 0); - -        const f overlay_size = dpi > 1.5 ? 2 : 1; - -        cv::circle(preview_frame, p, iround((b.radius + 3.3) * c_ * c_fract), circle_color, overlay_size, cv::LINE_AA, fract_bits); - -        char buf[16]; -        buf[sizeof(buf)-1] = '\0'; -        std::snprintf(buf, sizeof(buf) - 1, "%.2fpx", b.radius); - -        auto text_color = k >= PointModel::N_POINTS -                          ? cv::Scalar(160, 160, 160) -                          : cv::Scalar(0, 0, 255); +    draw_blobs(preview_frame_.as<Frame>()->mat, +               blobs.data(), blobs.size(), +               frame_gray.size()); -        cv::Point pos(iround(b.pos[0]*cx+offx), iround(b.pos[1]*cy+offy)); -        cv::putText(preview_frame, buf, pos, -                    cv::FONT_HERSHEY_PLAIN, overlay_size, text_color, -                    1); -    }      // End of mean shift code. At this point, blob positions are updated with hopefully less noisy less biased values.      points.reserve(max_blobs); @@ -383,3 +391,5 @@ blob::blob(f radius, const vec2& pos, f brightness, const cv::Rect& rect) :  {      //qDebug() << "radius" << radius << "pos" << pos[0] << pos[1];  } + +} // ns pt_module diff --git a/tracker-pt/module/point_extractor.h b/tracker-pt/module/point_extractor.h index 2288f1a1..a6103667 100644 --- a/tracker-pt/module/point_extractor.h +++ b/tracker-pt/module/point_extractor.h @@ -17,9 +17,9 @@  namespace pt_module { -using namespace types; +using namespace numeric_types; -struct blob +struct blob final  {      f radius, brightness;      vec2 pos; @@ -36,7 +36,7 @@ public:      void extract_points(const pt_frame& frame, pt_preview& preview_frame, std::vector<vec2>& points) override;      PointExtractor(const QString& module_name);  private: -    static constexpr inline int max_blobs = 16; +    static constexpr int max_blobs = 16;      pt_settings s; @@ -48,8 +48,7 @@ private:      void ensure_channel_buffers(const cv::Mat& orig_frame);      void ensure_buffers(const cv::Mat& frame); -    void extract_single_channel(const cv::Mat& orig_frame, int idx, cv::Mat& dest); -    void extract_channels(const cv::Mat& orig_frame, const int* order, int order_npairs); +    void extract_single_channel(const cv::Mat& orig_frame, int idx, cv::Mat1b& dest);      void color_to_grayscale(const cv::Mat& frame, cv::Mat1b& output);      void threshold_image(const cv::Mat& frame_gray, cv::Mat1b& output); | 
