summaryrefslogtreecommitdiffhomepage
path: root/cv
diff options
context:
space:
mode:
Diffstat (limited to 'cv')
-rw-r--r--cv/CMakeLists.txt14
-rw-r--r--cv/affine.cpp11
-rw-r--r--cv/affine.hpp11
-rw-r--r--cv/init.cpp24
-rw-r--r--cv/init.hpp2
-rw-r--r--cv/lang/de_DE.ts4
-rw-r--r--cv/lang/zh_CN.ts2
-rw-r--r--cv/numeric.hpp14
-rw-r--r--cv/ocv-check.cxx7
-rw-r--r--cv/translation-calibrator.cpp76
-rw-r--r--cv/translation-calibrator.hpp45
-rw-r--r--cv/video-property-page.cpp169
-rw-r--r--cv/video-property-page.hpp19
-rw-r--r--cv/video-widget.cpp150
-rw-r--r--cv/video-widget.hpp40
15 files changed, 185 insertions, 403 deletions
diff --git a/cv/CMakeLists.txt b/cv/CMakeLists.txt
index a3f05162..3a8798cc 100644
--- a/cv/CMakeLists.txt
+++ b/cv/CMakeLists.txt
@@ -1,5 +1,15 @@
-find_package(OpenCV 3.0 QUIET)
+include(opentrack-opencv)
+find_package(OpenCV QUIET)
if(OpenCV_FOUND)
+ try_compile(cv_use-ipp "${CMAKE_CURRENT_BINARY_DIR}"
+ SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/ocv-check.cxx"
+ CMAKE_FLAGS "-DINCLUDE_DIRECTORIES=${OpenCV_INCLUDE_DIRS}"
+ "-DCXX_STANDARD=20" "-DCXX_STANDARD_REQUIRED=1"
+ OUTPUT_VARIABLE krap)
otr_module(cv STATIC)
- target_include_directories(opentrack-cv SYSTEM PRIVATE ${OpenCV_INCLUDE_DIRS})
+ target_link_libraries(${self} opencv_core opentrack-video)
+ target_include_directories(${self} SYSTEM PRIVATE ${OpenCV_INCLUDE_DIRS})
+ if(cv_use-ipp)
+ target_compile_definitions(${self} PUBLIC -DOTR_HAS_CV_IPP)
+ endif()
endif()
diff --git a/cv/affine.cpp b/cv/affine.cpp
index 1b37305c..66e21aa6 100644
--- a/cv/affine.cpp
+++ b/cv/affine.cpp
@@ -9,23 +9,22 @@
namespace affine_impl {
-Affine::Affine() : R(mat33::eye()), t(0,0,0) {}
-
-Affine::Affine(const mat33& R, const vec3& t) : R(R),t(t) {}
+Affine::Affine() = default;
+Affine::Affine(const mat33& R, const vec3& t) : R(R), t(t) {}
Affine operator*(const Affine& X, const Affine& Y)
{
- return Affine(X.R*Y.R, X.R*Y.t + X.t);
+ return { X.R*Y.R, X.R*Y.t + X.t };
}
Affine operator*(const mat33& X, const Affine& Y)
{
- return Affine(X*Y.R, X*Y.t);
+ return { X*Y.R, X*Y.t };
}
Affine operator*(const Affine& X, const mat33& Y)
{
- return Affine(X.R*Y, X.t);
+ return { X.R*Y, X.t };
}
vec3 operator*(const Affine& X, const vec3& v)
diff --git a/cv/affine.hpp b/cv/affine.hpp
index 3bc85c95..4640e24e 100644
--- a/cv/affine.hpp
+++ b/cv/affine.hpp
@@ -7,12 +7,11 @@
#pragma once
-#include <opencv2/core.hpp>
#include "numeric.hpp"
namespace affine_impl {
-using namespace types;
+using namespace numeric_types;
class Affine final
{
@@ -20,8 +19,8 @@ public:
Affine();
Affine(const mat33& R, const vec3& t);
- mat33 R;
- vec3 t;
+ mat33 R { mat33::eye() };
+ vec3 t { 0, 0, 0 };
};
Affine operator*(const Affine& X, const Affine& Y);
@@ -31,5 +30,5 @@ vec3 operator*(const Affine& X, const vec3& v);
} // ns affine_impl
-using affine_impl::Affine;
-using affine_impl::operator *;
+using Affine = affine_impl::Affine;
+//using affine_impl::operator *;
diff --git a/cv/init.cpp b/cv/init.cpp
new file mode 100644
index 00000000..d883365b
--- /dev/null
+++ b/cv/init.cpp
@@ -0,0 +1,24 @@
+#include "init.hpp"
+#include <type_traits>
+#include <opencv2/core/base.hpp>
+#include <opencv2/core/utility.hpp>
+
+[[noreturn]]
+static
+int error_handler(int, const char* fn, const char* msg, const char* filename, int line, void*)
+{
+ fprintf(stderr, "[%s:%d] opencv: %s at %s\n", filename, line, msg, fn);
+ fflush(stderr);
+ std::abort();
+}
+
+void opencv_init()
+{
+ cv::redirectError(error_handler);
+ cv::setBreakOnError(false);
+ cv::setNumThreads(1);
+#ifdef OTR_HAS_CV_IPP
+ cv::ipp::setUseIPP(true);
+ cv::ipp::setUseIPP_NotExact(true);
+#endif
+}
diff --git a/cv/init.hpp b/cv/init.hpp
new file mode 100644
index 00000000..4c529549
--- /dev/null
+++ b/cv/init.hpp
@@ -0,0 +1,2 @@
+#pragma once
+void opencv_init();
diff --git a/cv/lang/de_DE.ts b/cv/lang/de_DE.ts
new file mode 100644
index 00000000..1552582e
--- /dev/null
+++ b/cv/lang/de_DE.ts
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="de_DE">
+</TS>
diff --git a/cv/lang/zh_CN.ts b/cv/lang/zh_CN.ts
index 6401616d..e5ca8aa9 100644
--- a/cv/lang/zh_CN.ts
+++ b/cv/lang/zh_CN.ts
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
-<TS version="2.1">
+<TS version="2.1" language="zh_CN">
</TS>
diff --git a/cv/numeric.hpp b/cv/numeric.hpp
index 0edb7f58..2050e8e4 100644
--- a/cv/numeric.hpp
+++ b/cv/numeric.hpp
@@ -1,13 +1,15 @@
#pragma once
-#include <opencv2/core.hpp>
+#include <type_traits>
+#include <opencv2/core/matx.hpp>
-namespace types {
- using f = double;
+namespace numeric_types {
+ using f = float;
- namespace constants {
- static constexpr inline f eps = f(1e-8);
- }
+ static_assert(std::is_floating_point_v<f>);
+
+ static constexpr f eps = f(1e-8);
+ static constexpr f pi = f(M_PI);
template<int n> using vec = cv::Vec<f, n>;
using vec2 = vec<2>;
diff --git a/cv/ocv-check.cxx b/cv/ocv-check.cxx
new file mode 100644
index 00000000..9efe3610
--- /dev/null
+++ b/cv/ocv-check.cxx
@@ -0,0 +1,7 @@
+#include <opencv2/core.hpp>
+
+void check1()
+{
+ cv::ipp::setUseIPP(true);
+ cv::ipp::setUseIPP_NotExact(true);
+}
diff --git a/cv/translation-calibrator.cpp b/cv/translation-calibrator.cpp
index 1eb9d1fa..6fb3e638 100644
--- a/cv/translation-calibrator.cpp
+++ b/cv/translation-calibrator.cpp
@@ -8,13 +8,15 @@
#include "translation-calibrator.hpp"
#include "compat/euler.hpp"
#include "compat/math.hpp"
+#include "compat/macros.h"
+#include <opencv2/core.hpp>
#include <tuple>
#include <QDebug>
-TranslationCalibrator::TranslationCalibrator(unsigned yaw_rdof, unsigned pitch_rdof, unsigned roll_rdof) :
- yaw_rdof(yaw_rdof), pitch_rdof(pitch_rdof), roll_rdof(roll_rdof)
+TranslationCalibrator::TranslationCalibrator(unsigned yaw_rdof, unsigned pitch_rdof) :
+ yaw_rdof(yaw_rdof), pitch_rdof(pitch_rdof)
{
reset();
}
@@ -22,11 +24,10 @@ TranslationCalibrator::TranslationCalibrator(unsigned yaw_rdof, unsigned pitch_r
void TranslationCalibrator::reset()
{
P = cv::Matx66f::zeros();
- y = cv::Vec6f(0,0,0, 0,0,0);
+ y = { 0,0,0, 0,0,0 };
- used_yaw_poses = vec(1 + iround(360 / yaw_spacing_in_degrees), 0);
- used_pitch_poses = vec(1 + iround(360 / pitch_spacing_in_degrees), 0);
- used_roll_poses = vec(1 + iround(360 / roll_spacing_in_degrees), 0);
+ used_yaw_poses = vec_i(1 + iround(360 / yaw_spacing_in_degrees), 0);
+ used_pitch_poses = vec_i(1 + iround(360 / pitch_spacing_in_degrees), 0);
nsamples = 0;
}
@@ -52,63 +53,70 @@ void TranslationCalibrator::update(const cv::Matx33d& R_CM_k, const cv::Vec3d& t
y += H_k_T * t_CM_k;
}
-std::tuple<cv::Vec3f, cv::Vec3i> TranslationCalibrator::get_estimate()
+using cv_out_vec = TranslationCalibrator::cv_nsample_vec;
+using cv_in_vec = TranslationCalibrator::cv_cal_vec;
+using tt = TranslationCalibrator::tt;
+
+tt TranslationCalibrator::get_estimate()
{
cv::Vec6f x = P.inv() * y;
- unsigned values[3] {};
- vec* in[] { &used_yaw_poses, &used_pitch_poses, &used_roll_poses };
+ vec_i const* in[num_nsample_axis] = { &used_yaw_poses, &used_pitch_poses, };
+ unsigned nsamples[num_cal_axis] {};
- for (unsigned k = 0; k < 3; k++)
+ for (unsigned k = 0; k < num_nsample_axis; k++)
{
- const vec& data = *in[k];
- for (unsigned i = 0; i < data.size(); i++)
- if (data[i])
- values[k]++;
+ vec_i const& data = *in[k];
+ for (unsigned i : data)
+ if (i)
+ nsamples[k]++;
}
qDebug() << "samples total" << nsamples
- << "yaw" << values[0]
- << "pitch" << values[1]
- << "roll" << values[2];
+ << "yaw" << nsamples[0]
+ << "pitch" << nsamples[1];
- return std::make_tuple(cv::Vec3f(-x[0], -x[1], -x[2]),
- cv::Vec3i(values[0], values[1], values[2]));
+ return {
+ { -x[0], -x[1], -x[2] },
+ { nsamples[0], nsamples[1] },
+ };
}
+static constexpr double r2d = 180/M_PI;
+
bool TranslationCalibrator::check_bucket(const cv::Matx33d& R_CM_k)
{
using namespace euler;
- constexpr double r2d = 180/M_PI;
rmat r;
for (unsigned j = 0; j < 3; j++)
for (unsigned i = 0; i < 3; i++)
r(j, i) = R_CM_k(j, i);
- const euler_t ypr = rmat_to_euler(r) * r2d;
+ const Pose_ ypr = rmat_to_euler(r) * r2d;
+
+ auto array_index = [](double val, double spacing) {
+ return (unsigned)iround((val + 180)/spacing);
+ };
- const unsigned yaw_k = iround((ypr(yaw_rdof) + 180)/yaw_spacing_in_degrees);
- const unsigned pitch_k = iround((ypr(pitch_rdof) + 180)/pitch_spacing_in_degrees);
- const unsigned roll_k = iround((ypr(roll_rdof) + 180)/roll_spacing_in_degrees);
+ const unsigned yaw_k = array_index(ypr(yaw_rdof), yaw_spacing_in_degrees);
+ const unsigned pitch_k = array_index(ypr(pitch_rdof), pitch_spacing_in_degrees);
if (yaw_k < used_yaw_poses.size() &&
- pitch_k < used_pitch_poses.size() &&
- roll_k < used_roll_poses.size())
+ pitch_k < used_pitch_poses.size())
{
used_yaw_poses[yaw_k]++;
used_pitch_poses[pitch_k]++;
- used_roll_poses[roll_k]++;
return used_yaw_poses[yaw_k] == 1 ||
- used_pitch_poses[pitch_k] == 1 ||
- used_roll_poses[roll_k] == 1;
+ used_pitch_poses[pitch_k] == 1;
}
else
- qDebug() << "calibrator: index out of range"
- << "yaw" << yaw_k
- << "pitch" << pitch_k
- << "roll" << roll_k;
+ {
+ eval_once(qDebug() << "calibrator: index out of range"
+ << "yaw" << yaw_k
+ << "pitch" << pitch_k);
- return false;
+ return false;
+ }
}
diff --git a/cv/translation-calibrator.hpp b/cv/translation-calibrator.hpp
index c1f6d2ec..3912c938 100644
--- a/cv/translation-calibrator.hpp
+++ b/cv/translation-calibrator.hpp
@@ -7,7 +7,7 @@
#pragma once
-#include <opencv2/core.hpp>
+#include <opencv2/core/matx.hpp>
#include <vector>
//-----------------------------------------------------------------------------
@@ -19,33 +19,38 @@
class TranslationCalibrator
{
-public:
- TranslationCalibrator(unsigned yaw_rdof, unsigned pitch_rdof, unsigned roll_rdof);
+ bool check_bucket(const cv::Matx33d& R_CM_k);
+
+ cv::Matx66f P; // normalized precision matrix = inverse covariance
+ cv::Vec6f y; // P*(-t_MH, t_CH)
+
+ using vec_i = std::vector<unsigned>;
+
+ vec_i used_yaw_poses {};
+ vec_i used_pitch_poses {};
+
+ unsigned yaw_rdof, pitch_rdof, nsamples = 0;
- // reset the calibration process
+public:
+ TranslationCalibrator(unsigned yaw_rdof, unsigned pitch_rdof);
void reset();
// update the current estimate
void update(const cv::Matx33d& R_CM_k, const cv::Vec3d& t_CM_k);
- // get the current estimate for t_MH
- std::tuple<cv::Vec3f, cv::Vec3i> get_estimate();
-
-private:
- bool check_bucket(const cv::Matx33d& R_CM_k);
-
- cv::Matx66f P; // normalized precision matrix = inverse covariance
- cv::Vec6f y; // P*(-t_MH, t_CH)
+ // we're bringing in 3DOF samples but the calibrator only
+ // checks yaw and pitch
- using vec = std::vector<unsigned>;
+ static constexpr unsigned num_cal_axis = 3;
+ static constexpr unsigned num_nsample_axis = 2;
- vec used_yaw_poses;
- vec used_pitch_poses;
- vec used_roll_poses;
+ using cv_cal_vec = cv::Vec<float, num_cal_axis>;
+ using cv_nsample_vec = cv::Vec<unsigned, num_nsample_axis>;
+ using tt = std::tuple<cv_cal_vec, cv_nsample_vec>;
- static constexpr inline double yaw_spacing_in_degrees = 2.5;
- static constexpr inline double pitch_spacing_in_degrees = 1.5;
- static constexpr inline double roll_spacing_in_degrees = 3.5;
+ // get the current estimate for t_MH
+ tt get_estimate();
- unsigned yaw_rdof, pitch_rdof, roll_rdof, nsamples;
+ static constexpr double yaw_spacing_in_degrees = 2;
+ static constexpr double pitch_spacing_in_degrees = 1.5;
};
diff --git a/cv/video-property-page.cpp b/cv/video-property-page.cpp
deleted file mode 100644
index a711e6af..00000000
--- a/cv/video-property-page.cpp
+++ /dev/null
@@ -1,169 +0,0 @@
-/* Copyright (c) 2016 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.
- */
-
-#include "video-property-page.hpp"
-
-#ifdef _WIN32
-
-#include "compat/camera-names.hpp"
-#include "compat/sleep.hpp"
-#include "compat/run-in-thread.hpp"
-#include "compat/library-path.hpp"
-
-#include <cstring>
-
-#include <opencv2/videoio.hpp>
-
-#include <QApplication>
-#include <QProcess>
-#include <QThread>
-#include <QMessageBox>
-
-#include <QDebug>
-
-#include <dshow.h>
-
-#define CHECK(expr) if (FAILED(hr = (expr))) { qDebug() << QLatin1String(#expr) << hr; goto done; }
-#define CHECK2(expr) if (!(expr)) { qDebug() << QLatin1String(#expr); goto done; }
-
-bool video_property_page::show_from_capture(cv::VideoCapture& cap, int /*index */)
-{
- return cap.set(cv::CAP_PROP_SETTINGS, 0);
-}
-
-struct prop_settings_worker final : QThread
-{
- prop_settings_worker(int idx);
- ~prop_settings_worker() override;
- void _open_prop_page();
- void run() override;
-
- cv::VideoCapture cap;
- int _idx = -1;
-};
-
-prop_settings_worker::prop_settings_worker(int idx)
-{
- int ret = cap.get(cv::CAP_PROP_SETTINGS);
-
- if (ret != 0)
- run_in_thread_async(qApp, []() {
- QMessageBox::warning(nullptr,
- "Camera properties",
- "Camera dialog already opened",
- QMessageBox::Cancel,
- QMessageBox::NoButton);
- });
- else
- {
- _idx = idx;
- // DON'T MOVE IT
- // ps3 eye will reset to default settings if done from another thread
- _open_prop_page();
- }
-}
-
-void prop_settings_worker::_open_prop_page()
-{
- cap.open(_idx);
-
- if (cap.isOpened())
- {
- cv::Mat tmp;
-
- for (unsigned k = 0; k < 2000/50; k++)
- {
- if (cap.read(tmp))
- {
- qDebug() << "got frame" << tmp.rows << tmp.cols;
- goto ok;
- }
- portable::sleep(50);
- }
- }
-
- qDebug() << "property-page: can't open camera";
- _idx = -1;
-
- return;
-
-ok:
- portable::sleep(100);
-
- qDebug() << "property-page: opening for" << _idx;
-
- if (!cap.set(cv::CAP_PROP_SETTINGS, 0))
- {
- run_in_thread_async(qApp, []() {
- QMessageBox::warning(nullptr,
- "Camera properties",
- "Can't open camera dialog",
- QMessageBox::Cancel,
- QMessageBox::NoButton);
- });
- }
-}
-
-prop_settings_worker::~prop_settings_worker()
-{
- if (_idx != -1)
- {
- // ax filter is race condition-prone
- portable::sleep(250);
- cap.release();
- // idem
- portable::sleep(250);
-
- qDebug() << "property-page: closed" << _idx;
- }
-}
-
-void prop_settings_worker::run()
-{
- if (_idx != -1)
- {
- while (cap.get(cv::CAP_PROP_SETTINGS) > 0)
- portable::sleep(1000);
- }
-}
-
-bool video_property_page::show(int idx)
-{
- auto thread = new prop_settings_worker(idx);
-
- // XXX is this a race condition?
- thread->moveToThread(qApp->thread());
- QObject::connect(thread, &QThread::finished, qApp, [thread]() { thread->deleteLater(); }, Qt::DirectConnection);
-
- thread->start();
-
- return true;
-}
-
-#elif defined(__linux)
-# include <QProcess>
-# include "compat/camera-names.hpp"
-
-bool video_property_page::show(int idx)
-{
- const QList<QString> camera_names(get_camera_names());
-
- if (idx >= 0 && idx < camera_names.size())
- return QProcess::startDetached("qv4l2", QStringList() << "-d" << camera_names[idx]);
- else
- return false;
-}
-
-bool video_property_page::show_from_capture(cv::VideoCapture&, int idx)
-{
- return show(idx);
-}
-#else
-bool video_property_page::show(int) { return false; }
-bool video_property_page::show_from_capture(cv::VideoCapture&, int) { return false; }
-#endif
-
diff --git a/cv/video-property-page.hpp b/cv/video-property-page.hpp
deleted file mode 100644
index 4f356b2c..00000000
--- a/cv/video-property-page.hpp
+++ /dev/null
@@ -1,19 +0,0 @@
-#pragma once
-
-#include <QString>
-
-#ifdef _WIN32
-# include <windows.h>
-#endif
-
-#include <opencv2/videoio.hpp>
-
-struct IBaseFilter;
-
-struct video_property_page final
-{
- video_property_page() = delete;
- static bool show(int id);
- static bool show_from_capture(cv::VideoCapture& cap, int index);
-private:
-};
diff --git a/cv/video-widget.cpp b/cv/video-widget.cpp
index fd4fe350..7accd275 100644
--- a/cv/video-widget.cpp
+++ b/cv/video-widget.cpp
@@ -1,128 +1,64 @@
-/* Copyright (c) 2012 Patrick Ruoff
- * Copyright (c) 2014-2016 Stanislaw Halik <sthalik@misaki.pl>
- *
- * 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.
- */
-
#include "video-widget.hpp"
-#include "compat/check-visible.hpp"
-
-#include <cstring>
-
+#include "compat/macros.h"
#include <opencv2/imgproc.hpp>
-cv_video_widget::cv_video_widget(QWidget* parent) : QWidget(parent)
-{
- connect(&timer, SIGNAL(timeout()), this, SLOT(update_and_repaint()), Qt::DirectConnection);
- timer.start(65);
-}
-
void cv_video_widget::update_image(const cv::Mat& frame)
{
- QMutexLocker l(&mtx);
-
- if (!freshp)
- {
- if (width < 1 || height < 1)
- return;
-
- if (_frame.cols != frame.cols || _frame.rows != frame.rows)
- _frame = cv::Mat(frame.rows, frame.cols, CV_8UC3);
- frame.copyTo(_frame);
- freshp = true;
-
- if (_frame2.cols != _frame.cols || _frame2.rows != _frame.rows)
- _frame2 = cv::Mat(_frame.rows, _frame.cols, CV_8UC4);
-
- if (_frame3.cols != width || _frame3.rows != height)
- _frame3 = cv::Mat(height, width, CV_8UC4);
-
- cv::cvtColor(_frame, _frame2, cv::COLOR_BGR2BGRA);
-
- const cv::Mat* img;
-
- if (_frame.cols != width || _frame.rows != height)
- {
- cv::resize(_frame2, _frame3, cv::Size(width, height), 0, 0, cv::INTER_NEAREST);
-
- img = &_frame3;
- }
- else
- img = &_frame2;
-
- const unsigned nbytes = 4 * img->rows * img->cols;
-
- vec.resize(nbytes);
-
- std::memcpy(vec.data(), img->data, nbytes);
-
- texture = QImage((const unsigned char*) vec.data(), width, height, QImage::Format_ARGB32);
- }
-}
-
-void cv_video_widget::update_image(const QImage& img)
-{
- QMutexLocker l(&mtx);
-
- if (freshp)
+ if (fresh())
return;
- const unsigned nbytes = img.bytesPerLine() * img.height();
-
- vec.resize(nbytes);
-
- std::memcpy(vec.data(), img.constBits(), nbytes);
-
- texture = QImage((const unsigned char*) vec.data(), img.width(), img.height(), img.format());
-
- freshp = true;
-}
-
-void cv_video_widget::paintEvent(QPaintEvent*)
-{
- QMutexLocker foo(&mtx);
-
- QPainter painter(this);
-
- double dpr = devicePixelRatioF();
+ auto [ W, H ] = preview_size();
- int W = int(QWidget::width() * dpr);
- int H = int(QWidget::height() * dpr);
+ if (W < 1 || H < 1 || frame.rows < 1 || frame.cols < 1)
+ return;
- painter.drawImage(rect(), texture);
+ cv::Mat const* __restrict scaled = nullptr;
+ frame3.create(H, W, frame.type());
+ frame2.create(H, W, CV_8UC4);
- if (texture.width() != W || texture.height() != H)
+ if (frame.cols != W || frame.rows != H)
+ {
+ cv::resize(frame, frame3, { W, H }, 0, 0, cv::INTER_NEAREST);
+ scaled = &frame3;
+ }
+ else if (!frame.isContinuous())
{
- texture = QImage(W, H, QImage::Format_ARGB32);
- texture.setDevicePixelRatio(dpr);
+ frame.copyTo(frame3);
+ scaled = &frame3;
+ }
+ else
+ scaled = &frame;
- width = W, height = H;
+ int color_cvt = cv::COLOR_COLORCVT_MAX;
- _frame = cv::Mat();
- _frame2 = cv::Mat();
- _frame3 = cv::Mat();
+ switch (scaled->channels())
+ {
+ case 1:
+ color_cvt = cv::COLOR_GRAY2BGRA;
+ break;
+ case 3:
+ color_cvt = cv::COLOR_BGR2BGRA;
+ break;
+ case 4:
+ break;
+ default:
+ unreachable();
+ break;
}
-}
-void cv_video_widget::update_and_repaint()
-{
- if (!check_is_visible())
- return;
-
- QMutexLocker l(&mtx);
+ cv::Mat const* color;
- if (freshp)
+ if (color_cvt != cv::COLOR_COLORCVT_MAX)
{
- freshp = false;
- repaint();
+ cv::cvtColor(*scaled, frame2, color_cvt);
+ color = &frame2;
}
-}
+ else
+ color = scaled;
-void cv_video_widget::get_preview_size(int& w, int& h)
-{
- QMutexLocker l(&mtx);
+ int width = color->cols, height = color->rows;
+ unsigned stride = color->step.p[0];
+ set_image(color->data, width, height, stride, QImage::Format_ARGB32);
- w = width, h = height;
+ set_fresh(true);
}
diff --git a/cv/video-widget.hpp b/cv/video-widget.hpp
index 15430e2f..24f8d7f3 100644
--- a/cv/video-widget.hpp
+++ b/cv/video-widget.hpp
@@ -1,5 +1,4 @@
-/* Copyright (c) 2012 Patrick Ruoff
- * Copyright (c) 2014-2016 Stanislaw Halik <sthalik@misaki.pl>
+/* Copyright (c) 2019 Stanislaw Halik <sthalik@misaki.pl>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -8,39 +7,14 @@
#pragma once
-#include <memory>
-#include <vector>
+#include "video/video-widget.hpp"
+#include <opencv2/core/mat.hpp>
-#include <opencv2/core.hpp>
-
-#include <QObject>
-#include <QWidget>
-#include <QPainter>
-#include <QPaintEvent>
-#include <QTimer>
-#include <QMutex>
-#include <QMutexLocker>
-#include <QSize>
-#include <QDebug>
-
-class cv_video_widget final : public QWidget
+struct cv_video_widget final : video_widget
{
- Q_OBJECT
-
-public:
- cv_video_widget(QWidget *parent);
+ using video_widget::video_widget;
void update_image(const cv::Mat& frame);
- void update_image(const QImage& image);
- void get_preview_size(int& w, int& h);
-private slots:
- void paintEvent(QPaintEvent*) override;
- void update_and_repaint();
+
private:
- QMutex mtx { QMutex::Recursive };
- QImage texture;
- std::vector<unsigned char> vec;
- QTimer timer;
- cv::Mat _frame, _frame2, _frame3;
- int width = 320, height = 240;
- bool freshp = false;
+ cv::Mat frame2, frame3;
};