summaryrefslogtreecommitdiffhomepage
path: root/tracker-pt/module
diff options
context:
space:
mode:
Diffstat (limited to 'tracker-pt/module')
-rw-r--r--tracker-pt/module/camera.cpp31
-rw-r--r--tracker-pt/module/camera.h8
-rw-r--r--tracker-pt/module/frame.cpp6
-rw-r--r--tracker-pt/module/frame.hpp14
-rw-r--r--tracker-pt/module/module.cpp16
-rw-r--r--tracker-pt/module/module.hpp4
-rw-r--r--tracker-pt/module/point_extractor.cpp156
-rw-r--r--tracker-pt/module/point_extractor.h9
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 &current_center, f filter_width)
+static vec2 MeanShiftIteration(const cv::Mat1b &frame_gray, const vec2 &current_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);