diff options
Diffstat (limited to 'cv')
| -rw-r--r-- | cv/CMakeLists.txt | 15 | ||||
| -rw-r--r-- | cv/affine.cpp | 35 | ||||
| -rw-r--r-- | cv/affine.hpp | 34 | ||||
| -rw-r--r-- | cv/init.cpp | 24 | ||||
| -rw-r--r-- | cv/init.hpp | 2 | ||||
| -rw-r--r-- | cv/lang/de_DE.ts | 4 | ||||
| -rw-r--r-- | cv/lang/zh_CN.ts | 4 | ||||
| -rw-r--r-- | cv/numeric.hpp | 21 | ||||
| -rw-r--r-- | cv/ocv-check.cxx | 7 | ||||
| -rw-r--r-- | cv/translation-calibrator.cpp | 86 | ||||
| -rw-r--r-- | cv/translation-calibrator.hpp | 44 | ||||
| -rw-r--r-- | cv/video-property-page.cpp | 182 | ||||
| -rw-r--r-- | cv/video-property-page.hpp | 23 | ||||
| -rw-r--r-- | cv/video-widget.cpp | 108 | ||||
| -rw-r--r-- | cv/video-widget.hpp | 35 |
15 files changed, 267 insertions, 357 deletions
diff --git a/cv/CMakeLists.txt b/cv/CMakeLists.txt index 67a27ee9..3a8798cc 100644 --- a/cv/CMakeLists.txt +++ b/cv/CMakeLists.txt @@ -1,6 +1,15 @@ -find_package(OpenCV 3.0 QUIET COMPONENTS ${opencv-modules}) +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_link_libraries(opentrack-cv ${OpenCV_LIBS}) - target_include_directories(opentrack-cv SYSTEM PUBLIC ${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 new file mode 100644 index 00000000..66e21aa6 --- /dev/null +++ b/cv/affine.cpp @@ -0,0 +1,35 @@ +/* Copyright (c) 2012 Patrick Ruoff + * + * 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 "affine.hpp" + +namespace affine_impl { + +Affine::Affine() = default; +Affine::Affine(const mat33& R, const vec3& t) : R(R), t(t) {} + +Affine operator*(const Affine& X, const Affine& Y) +{ + return { X.R*Y.R, X.R*Y.t + X.t }; +} + +Affine operator*(const mat33& X, const Affine& Y) +{ + return { X*Y.R, X*Y.t }; +} + +Affine operator*(const Affine& X, const mat33& Y) +{ + return { X.R*Y, X.t }; +} + +vec3 operator*(const Affine& X, const vec3& v) +{ + return X.R*v + X.t; +} + +} // ns affine_impl diff --git a/cv/affine.hpp b/cv/affine.hpp new file mode 100644 index 00000000..4640e24e --- /dev/null +++ b/cv/affine.hpp @@ -0,0 +1,34 @@ +/* Copyright (c) 2012 Patrick Ruoff + * + * 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 "numeric.hpp" + +namespace affine_impl { + +using namespace numeric_types; + +class Affine final +{ +public: + Affine(); + Affine(const mat33& R, const vec3& t); + + mat33 R { mat33::eye() }; + vec3 t { 0, 0, 0 }; +}; + +Affine operator*(const Affine& X, const Affine& Y); +Affine operator*(const mat33& X, const Affine& Y); +Affine operator*(const Affine& X, const mat33& Y); +vec3 operator*(const Affine& X, const vec3& v); + +} // ns affine_impl + +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 new file mode 100644 index 00000000..e5ca8aa9 --- /dev/null +++ b/cv/lang/zh_CN.ts @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE TS> +<TS version="2.1" language="zh_CN"> +</TS> diff --git a/cv/numeric.hpp b/cv/numeric.hpp new file mode 100644 index 00000000..2050e8e4 --- /dev/null +++ b/cv/numeric.hpp @@ -0,0 +1,21 @@ +#pragma once + +#include <type_traits> +#include <opencv2/core/matx.hpp> + +namespace numeric_types { + using f = float; + + 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>; + using vec3 = vec<3>; + + template<int y, int x> using mat = cv::Matx<f, y, x>; + using mat33 = mat<3, 3>; + using mat22 = mat<2, 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 cdd573bc..6fb3e638 100644 --- a/cv/translation-calibrator.cpp +++ b/cv/translation-calibrator.cpp @@ -7,16 +7,16 @@ #include "translation-calibrator.hpp" #include "compat/euler.hpp" -#include "compat/util.hpp" +#include "compat/math.hpp" +#include "compat/macros.h" +#include <opencv2/core.hpp> #include <tuple> -constexpr double TranslationCalibrator::pitch_spacing_in_degrees; -constexpr double TranslationCalibrator::yaw_spacing_in_degrees; -constexpr double TranslationCalibrator::roll_spacing_in_degrees; +#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(); } @@ -24,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; } @@ -54,65 +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, unsigned> 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; - qDebug() << "calibrator:" << nsamples << "samples total"; - - 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" - << "yaw" << values[0] - << "pitch" << values[1] - << "roll" << values[2]; + qDebug() << "samples total" << nsamples + << "yaw" << nsamples[0] + << "pitch" << nsamples[1]; - return std::make_tuple(cv::Vec3f(-x[0], -x[1], -x[2]), nsamples); + 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; - static 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; - 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); + auto array_index = [](double val, double spacing) { + return (unsigned)iround((val + 180)/spacing); + }; - if (yaw_k < used_yaw_poses.size() && - pitch_k < used_pitch_poses.size() && - roll_k < used_roll_poses.size()) + 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()) { 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 40ba19e9..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,34 +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, unsigned> get_estimate(); - -private: - bool check_bucket(const cv::Matx33d& R_CM_k); - static int get_index(int yaw, int pitch, int roll); + // we're bringing in 3DOF samples but the calibrator only + // checks yaw and pitch - cv::Matx66f P; // normalized precision matrix = inverse covariance - cv::Vec6f y; // P*(-t_MH, t_CH) + static constexpr unsigned num_cal_axis = 3; + static constexpr unsigned num_nsample_axis = 2; - using vec = std::vector<unsigned>; + 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>; - vec used_yaw_poses; - vec used_pitch_poses; - vec used_roll_poses; + // get the current estimate for t_MH + tt get_estimate(); - static constexpr double yaw_spacing_in_degrees = 2.5; + static constexpr double yaw_spacing_in_degrees = 2; static constexpr double pitch_spacing_in_degrees = 1.5; - static constexpr double roll_spacing_in_degrees = 3.5; - - unsigned yaw_rdof, pitch_rdof, roll_rdof, nsamples; }; diff --git a/cv/video-property-page.cpp b/cv/video-property-page.cpp deleted file mode 100644 index b542a9c4..00000000 --- a/cv/video-property-page.cpp +++ /dev/null @@ -1,182 +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 <cstring> -#include <QRegularExpression> -#include <QDebug> - -#define CHECK(expr) if (FAILED(hr = (expr))) { qDebug() << QStringLiteral(#expr) << hr; goto done; } -#define CHECK2(expr) if (!(expr)) { qDebug() << QStringLiteral(#expr); goto done; } - -bool video_property_page::show_from_capture(cv::VideoCapture& cap, int) -{ - cap.set(cv::CAP_PROP_SETTINGS, 0); - return true; -} - -bool video_property_page::should_show_dialog(const QString& camera_name) -{ - using re = QRegularExpression; - static const re regexen[] = - { - re("^PS3Eye Camera$"), - re("^A4 TECH "), - }; - bool avail = true; - for (const re& r : regexen) - { - avail &= !r.match(camera_name).hasMatch(); - if (!avail) - break; - } - return avail; -} - -bool video_property_page::show(int id) -{ - IBaseFilter* filter = NULL; - bool ret = false; - - CHECK2(filter = get_device(id)); - - ret = SUCCEEDED(ShowFilterPropertyPages(filter)); - -done: - if (filter) - filter->Release(); - - return ret; -} - -HRESULT video_property_page::ShowFilterPropertyPages(IBaseFilter* filter) -{ - ISpecifyPropertyPages* pProp = NULL; - IUnknown* unk = NULL; - CAUUID caGUID = { 0, NULL }; - FILTER_INFO FilterInfo = { {0}, NULL }; - HRESULT hr; - - CHECK(filter->QueryInterface(IID_ISpecifyPropertyPages, (void**)&pProp)); - CHECK(pProp->GetPages(&caGUID)); - CHECK(filter->QueryFilterInfo(&FilterInfo)); - - filter->QueryInterface(IID_IUnknown, (void**)&unk); - - // OleInitialize, CoCreateInstance et al. don't help with ps3 eye. - - // cl-eye uses this - // perhaps more than IBaseFilter* -> IUnknown* needs be passed to lplpUnk - // and the OleCreatePropertyFrame equiv -#if 0 - OCPFIPARAMS params; - params.cbStructSize = sizeof(params); - params.hWndOwner = GetActiveWindow(); - params.x = 0; - params.y = 0; - params.lpszCaption = L"camera props"; - params.cObjects = 1; - params.lplpUnk = &unk; - params.cPages = 1; - //OleCreatePropertyFrameIndirect() -#endif - - OleCreatePropertyFrame( - NULL, // Parent window - 0, 0, // Reserved - FilterInfo.achName, // Caption for the dialog box - 1, // Number of objects (just the filter) - &unk, // Array of object pointers. - caGUID.cElems, // Number of property pages - caGUID.pElems, // Array of property page CLSIDs - 0, // Locale identifier - 0, NULL // Reserved - ); - -done: - if (FilterInfo.pGraph) - FilterInfo.pGraph->Release(); - - if (caGUID.pElems) - CoTaskMemFree(caGUID.pElems); - - if (pProp) - pProp->Release(); - - if (unk) - unk->Release(); - - return hr; -} - -IBaseFilter* video_property_page::get_device(int id) -{ - ICreateDevEnum* pSysDevEnum = NULL; - IEnumMoniker* pEnumCat = NULL; - IMoniker* pMoniker = NULL; - IBaseFilter* filter = NULL; - HRESULT hr; - - CHECK(CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (void**)&pSysDevEnum)); - CHECK(pSysDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnumCat, 0)); - - for (int i = 0; !filter && SUCCEEDED(pEnumCat->Next(1, &pMoniker, NULL)); pMoniker->Release(), i++) - { - if (i == id) - { - CHECK(pMoniker->BindToObject(NULL, NULL, IID_IBaseFilter, (void**)&filter)); - break; - } - } - -done: - if (pMoniker) - pMoniker->Release(); - - if (pEnumCat) - pEnumCat->Release(); - - if (pSysDevEnum) - pSysDevEnum->Release(); - - return filter; -} - -#elif defined(__linux) -# include <QProcess> -# include "compat/camera-names.hpp" - -bool video_property_page::should_show_dialog(const QString&) -{ - return true; -} - -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; } -bool video_property_page::should_show_dialog(const QString& camera_name) -{ - return false; -} -#endif diff --git a/cv/video-property-page.hpp b/cv/video-property-page.hpp deleted file mode 100644 index 4e53e2ab..00000000 --- a/cv/video-property-page.hpp +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -#include <QString> - -#ifdef _WIN32 -# include <windows.h> -# include <dshow.h> -#endif - -#include "opencv2/videoio.hpp" - -struct video_property_page final -{ - video_property_page() = delete; - static bool show(int id); - static bool show_from_capture(cv::VideoCapture& cap, int idx); - static bool should_show_dialog(const QString& camera_name); -private: -#ifdef _WIN32 - static HRESULT ShowFilterPropertyPages(IBaseFilter* filter); - static IBaseFilter* get_device(int id); -#endif -}; diff --git a/cv/video-widget.cpp b/cv/video-widget.cpp index acaf06a6..7accd275 100644 --- a/cv/video-widget.cpp +++ b/cv/video-widget.cpp @@ -1,78 +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/macros.h" #include <opencv2/imgproc.hpp> -cv_video_widget::cv_video_widget(QWidget* parent) : - QWidget(parent), freshp(false) -{ - connect(&timer, SIGNAL(timeout()), this, SLOT(update_and_repaint())); - timer.start(65); -} - void cv_video_widget::update_image(const cv::Mat& frame) { - QMutexLocker l(&mtx); - - if (!freshp) - { - const int w = preview_size.width(), h = preview_size.height(); - - if (w < 1 || h < 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_8UC3); - - if (_frame3.cols != w || _frame3.rows != h) - _frame3 = cv::Mat(h, w, CV_8UC3); - - cv::cvtColor(_frame, _frame2, cv::COLOR_RGB2BGR); - - const cv::Mat* img_; + if (fresh()) + return; - if (_frame.cols != w || _frame.rows != h) - { - cv::resize(_frame2, _frame3, cv::Size(w, h), 0, 0, cv::INTER_NEAREST); + auto [ W, H ] = preview_size(); - img_ = &_frame3; - } - else - img_ = &_frame2; + if (W < 1 || H < 1 || frame.rows < 1 || frame.cols < 1) + return; - const cv::Mat& img = *img_; + cv::Mat const* __restrict scaled = nullptr; + frame3.create(H, W, frame.type()); + frame2.create(H, W, CV_8UC4); - texture = QImage((const unsigned char*) img.data, w, h, QImage::Format_RGB888); + if (frame.cols != W || frame.rows != H) + { + cv::resize(frame, frame3, { W, H }, 0, 0, cv::INTER_NEAREST); + scaled = &frame3; } -} + else if (!frame.isContinuous()) + { + frame.copyTo(frame3); + scaled = &frame3; + } + else + scaled = &frame; -void cv_video_widget::paintEvent(QPaintEvent*) -{ - QMutexLocker foo(&mtx); - QPainter painter(this); - painter.drawImage(rect(), texture); -} + int color_cvt = cv::COLOR_COLORCVT_MAX; -void cv_video_widget::update_and_repaint() -{ - QMutexLocker l(&mtx); + 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; + } - preview_size = size(); + cv::Mat const* color; - if (freshp) + if (color_cvt != cv::COLOR_COLORCVT_MAX) { - freshp = false; - update(); + cv::cvtColor(*scaled, frame2, color_cvt); + color = &frame2; } + else + color = scaled; + + int width = color->cols, height = color->rows; + unsigned stride = color->step.p[0]; + set_image(color->data, width, height, stride, QImage::Format_ARGB32); + + set_fresh(true); } diff --git a/cv/video-widget.hpp b/cv/video-widget.hpp index 3b29ffc6..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,32 +7,14 @@ #pragma once -#include <opencv2/core/core.hpp> -#include <memory> -#include <QObject> -#include <QWidget> -#include <QPainter> -#include <QPaintEvent> -#include <QTimer> -#include <QMutex> -#include <QMutexLocker> -#include <QSize> -#include <QDebug> +#include "video/video-widget.hpp" +#include <opencv2/core/mat.hpp> -class cv_video_widget final : public QWidget +struct cv_video_widget final : video_widget { - Q_OBJECT -public: - cv_video_widget(QWidget *parent); - void update_image(const cv::Mat &frame); -protected slots: - void paintEvent(QPaintEvent*) override; - void update_and_repaint(); + using video_widget::video_widget; + void update_image(const cv::Mat& frame); + private: - QMutex mtx; - QImage texture; - QTimer timer; - QSize preview_size; - cv::Mat _frame, _frame2, _frame3; - bool freshp; + cv::Mat frame2, frame3; }; |
