diff options
| author | Stanislaw Halik <sthalik@misaki.pl> | 2019-02-11 20:07:41 +0100 | 
|---|---|---|
| committer | Stanislaw Halik <sthalik@misaki.pl> | 2019-02-11 20:21:36 +0100 | 
| commit | 85fc6ac25d350950be56ba47b06c247216f2e22a (patch) | |
| tree | 6a4b4a65e9084c9595c28c4045824376a8c577d3 | |
| parent | 5d6cccb406e4aa4fe3e8430690296e5f59474e48 (diff) | |
video/widget: externalize opencv code
| -rw-r--r-- | cv/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | cv/video-widget.cpp | 78 | ||||
| -rw-r--r-- | cv/video-widget.hpp | 20 | ||||
| -rw-r--r-- | tracker-aruco/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | tracker-aruco/ftnoir_tracker_aruco.h | 2 | ||||
| -rw-r--r-- | tracker-kinect-face/kinect_face_tracker.cpp | 2 | ||||
| -rw-r--r-- | tracker-kinect-face/kinect_face_tracker.h | 2 | ||||
| -rw-r--r-- | tracker-pt/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | tracker-pt/ftnoir_tracker_pt.cpp | 8 | ||||
| -rw-r--r-- | tracker-pt/ftnoir_tracker_pt.h | 4 | ||||
| -rw-r--r-- | video/CMakeLists.txt | 8 | ||||
| -rw-r--r-- | video/export.hpp | 11 | ||||
| -rw-r--r-- | video/video-widget.cpp | 96 | ||||
| -rw-r--r-- | video/video-widget.hpp | 23 | 
14 files changed, 139 insertions, 121 deletions
| diff --git a/cv/CMakeLists.txt b/cv/CMakeLists.txt index 60350a99..dfc983aa 100644 --- a/cv/CMakeLists.txt +++ b/cv/CMakeLists.txt @@ -1,6 +1,6 @@  find_package(OpenCV QUIET)  if(OpenCV_FOUND)      otr_module(cv STATIC) -    target_link_libraries(${self} opencv_videoio opencv_core) +    target_link_libraries(${self} opencv_videoio opencv_core opentrack-video)      target_include_directories(${self} SYSTEM PRIVATE ${OpenCV_INCLUDE_DIRS})  endif() diff --git a/cv/video-widget.cpp b/cv/video-widget.cpp new file mode 100644 index 00000000..7cc6ca2d --- /dev/null +++ b/cv/video-widget.cpp @@ -0,0 +1,78 @@ +#include "video-widget.hpp" + +#include <opencv2/imgproc.hpp> + +void cv_video_widget::update_image(const cv::Mat& frame) +{ +    QMutexLocker l(&mtx); + +    if (freshp) +        return; + +    if (W < 1 || H < 1 || frame.rows < 1 || frame.cols < 1) +        return; + +    cv::Mat const* __restrict frame_scaled = nullptr; + +    if (frame3.cols != W || frame3.rows != H) +    { +        frame3 = cv::Mat(H, W, frame.type()); +        frame2 = cv::Mat(H, W, CV_8UC4); + +        if (!frame2.isContinuous() || !frame3.isContinuous()) +            std::abort(); +    } + +    if (frame.cols != W || frame.rows != H) +    { +        cv::resize(frame, frame3, { W, H }, 0, 0, cv::INTER_NEAREST); +        frame_scaled = &frame3; +    } +    else if (!frame.isContinuous()) +    { +        frame.copyTo(frame3); +        frame_scaled = &frame3; +    } +    else +        frame_scaled = &frame; + +    freshp = true; + +    int color_cvt = 0; +    constexpr int nchannels = 4; + +    switch (frame_scaled->channels()) +    { +    case 1: +        color_cvt = cv::COLOR_GRAY2BGRA; +        break; +    case 3: +        color_cvt = cv::COLOR_BGR2BGRA; +        break; +    case nchannels: +        break; +    default: +        unreachable(); +        break; +    } + +    cv::Mat const* frame_color; + +    if (color_cvt != cv::COLOR_COLORCVT_MAX) +    { +        cv::cvtColor(*frame_scaled, frame2, color_cvt); +        frame_color = &frame2; +    } +    else +        frame_color = frame_scaled; + +    int stride = frame_color->step.p[0], rows = frame_color->rows; +    int nbytes = rows * stride; +    vec.resize(nbytes); vec.shrink_to_fit(); +    std::memcpy(vec.data(), frame_color->data, nbytes); + +    texture = QImage((const unsigned char*) vec.data(), W, H, stride, QImage::Format_ARGB32); +    texture.setDevicePixelRatio(devicePixelRatioF()); +} + +cv_video_widget::cv_video_widget(QWidget* parent) : video_widget(parent) {} diff --git a/cv/video-widget.hpp b/cv/video-widget.hpp new file mode 100644 index 00000000..9d62f19e --- /dev/null +++ b/cv/video-widget.hpp @@ -0,0 +1,20 @@ +/* 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 + * copyright notice and this permission notice appear in all copies. + */ + +#pragma once + +#include "video/video-widget.hpp" +#include <opencv2/core.hpp> + +struct cv_video_widget final : video_widget +{ +    cv_video_widget(QWidget* parent = nullptr); +    void update_image(const cv::Mat& frame); + +private: +    cv::Mat frame2, frame3; +}; diff --git a/tracker-aruco/CMakeLists.txt b/tracker-aruco/CMakeLists.txt index f34b7420..bfa7a348 100644 --- a/tracker-aruco/CMakeLists.txt +++ b/tracker-aruco/CMakeLists.txt @@ -39,6 +39,6 @@ if(OpenCV_FOUND)          otr_module(tracker-aruco)          target_include_directories(${self} SYSTEM PUBLIC ${OpenCV_INCLUDE_DIRS} "${dir}") -        target_link_libraries(${self} opentrack-cv opentrack-video ${modules}) +        target_link_libraries(${self} opentrack-cv ${modules})      endif()  endif() diff --git a/tracker-aruco/ftnoir_tracker_aruco.h b/tracker-aruco/ftnoir_tracker_aruco.h index 0477c4da..1d6fd107 100644 --- a/tracker-aruco/ftnoir_tracker_aruco.h +++ b/tracker-aruco/ftnoir_tracker_aruco.h @@ -11,7 +11,7 @@  #include "options/options.hpp"  #include "cv/translation-calibrator.hpp"  #include "api/plugin-api.hpp" -#include "video/video-widget.hpp" +#include "cv/video-widget.hpp"  #include "compat/timer.hpp"  #include "aruco/markerdetector.h" diff --git a/tracker-kinect-face/kinect_face_tracker.cpp b/tracker-kinect-face/kinect_face_tracker.cpp index e826f8b0..d4cf89e3 100644 --- a/tracker-kinect-face/kinect_face_tracker.cpp +++ b/tracker-kinect-face/kinect_face_tracker.cpp @@ -127,7 +127,7 @@ module_status KinectFaceTracker::start_tracker(QFrame* aFrame)  	if (SUCCEEDED(InitializeDefaultSensor()))  	{  		// Setup our video preview widget -		iVideoWidget = std::make_unique<cv_video_widget>(aFrame); +		iVideoWidget = std::make_unique<video_widget>(aFrame);  		iLayout = std::make_unique<QHBoxLayout>(aFrame);  		iLayout->setContentsMargins(0, 0, 0, 0);  		iLayout->addWidget(iVideoWidget.get()); diff --git a/tracker-kinect-face/kinect_face_tracker.h b/tracker-kinect-face/kinect_face_tracker.h index 672047b1..3ed28bea 100644 --- a/tracker-kinect-face/kinect_face_tracker.h +++ b/tracker-kinect-face/kinect_face_tracker.h @@ -109,7 +109,7 @@ private:  	CameraSpacePoint iFaceRotation = { 0 };  	CameraSpacePoint iFaceRotationCenter = { 0 };  	// -	std::unique_ptr<cv_video_widget> iVideoWidget; +	std::unique_ptr<video_widget> iVideoWidget;  	std::unique_ptr<QLayout> iLayout;  	// Id of the body currently being tracked diff --git a/tracker-pt/CMakeLists.txt b/tracker-pt/CMakeLists.txt index 94e0a9d5..f12f530b 100644 --- a/tracker-pt/CMakeLists.txt +++ b/tracker-pt/CMakeLists.txt @@ -2,7 +2,7 @@ find_package(OpenCV QUIET)  if(OpenCV_FOUND)      otr_module(tracker-pt-base STATIC)      target_include_directories(${self} SYSTEM PUBLIC ${OpenCV_INCLUDE_DIRS}) -    target_link_libraries(${self} opencv_imgproc opentrack-cv opentrack-video opencv_core) +    target_link_libraries(${self} opencv_imgproc opentrack-cv opencv_core)      set_property(TARGET ${self} PROPERTY OUTPUT_NAME "pt-base")  endif()  add_subdirectory(module) diff --git a/tracker-pt/ftnoir_tracker_pt.cpp b/tracker-pt/ftnoir_tracker_pt.cpp index ed29906f..b717e4a1 100644 --- a/tracker-pt/ftnoir_tracker_pt.cpp +++ b/tracker-pt/ftnoir_tracker_pt.cpp @@ -94,11 +94,11 @@ void Tracker_PT::run()              vec3 p = X_GH.t; // head (center?) position in global space              preview_frame->draw_head_center((p[0] * fx) / p[2], (p[1] * fx) / p[2]); -            video_widget->update_image(preview_frame->get_bitmap()); +            widget->update_image(preview_frame->get_bitmap());              {                  int w = -1, h = -1; -                video_widget->get_preview_size(w, h); +                widget->get_preview_size(w, h);                  if (w != preview_width || h != preview_height)                  {                      preview_width = w; preview_height = h; @@ -127,10 +127,10 @@ module_status Tracker_PT::start_tracker(QFrame* video_frame)  {      //video_frame->setAttribute(Qt::WA_NativeWindow); -    video_widget = std::make_unique<cv_video_widget>(video_frame); +    widget = std::make_unique<video_widget>(video_frame);      layout = std::make_unique<QHBoxLayout>(video_frame);      layout->setContentsMargins(0, 0, 0, 0); -    layout->addWidget(video_widget.get()); +    layout->addWidget(widget.get());      video_frame->setLayout(layout.get());      //video_widget->resize(video_frame->width(), video_frame->height());      video_frame->show(); diff --git a/tracker-pt/ftnoir_tracker_pt.h b/tracker-pt/ftnoir_tracker_pt.h index 0226fd87..77835602 100644 --- a/tracker-pt/ftnoir_tracker_pt.h +++ b/tracker-pt/ftnoir_tracker_pt.h @@ -24,7 +24,7 @@  #include <QLayout>  class TrackerDialog_PT; -class cv_video_widget; +class video_widget;  namespace pt_module { @@ -69,7 +69,7 @@ private:      pointer<pt_point_extractor> point_extractor;      pointer<pt_camera> camera; -    pointer<cv_video_widget> video_widget; +    pointer<video_widget> widget;      pointer<pt_frame> frame;      pointer<pt_preview> preview_frame; diff --git a/video/CMakeLists.txt b/video/CMakeLists.txt index 3bf04d75..0a9dfd24 100644 --- a/video/CMakeLists.txt +++ b/video/CMakeLists.txt @@ -1,7 +1 @@ -find_package(OpenCV QUIET) -otr_module(video STATIC) -if(OpenCV_FOUND) -    target_compile_definitions(${self} PUBLIC -DOTR_VIDEO_HAS_OPENCV) -    target_link_libraries(${self} opencv_videoio opencv_core) -endif() - +otr_module(video BIN) diff --git a/video/export.hpp b/video/export.hpp new file mode 100644 index 00000000..fc850193 --- /dev/null +++ b/video/export.hpp @@ -0,0 +1,11 @@ +// generates export.hpp for each module from compat/linkage.hpp + +#pragma once + +#include "compat/linkage-macros.hpp" + +#ifdef BUILD_VIDEO +#   define OTR_VIDEO_EXPORT OTR_GENERIC_EXPORT +#else +#   define OTR_VIDEO_EXPORT OTR_GENERIC_IMPORT +#endif diff --git a/video/video-widget.cpp b/video/video-widget.cpp index 90975f0c..3e6d9038 100644 --- a/video/video-widget.cpp +++ b/video/video-widget.cpp @@ -6,103 +6,24 @@  #include <cstddef>  #include <cstring> -#ifdef OTR_VIDEO_HAS_OPENCV -#   include <opencv2/imgproc.hpp> -#endif -  #include <QPainter> -void cv_video_widget::init_image_nolock() +void video_widget::init_image_nolock()  {      texture = QImage(W, H, QImage::Format_ARGB32);      texture.setDevicePixelRatio(devicePixelRatioF());  } -cv_video_widget::cv_video_widget(QWidget* parent) : QWidget(parent) +video_widget::video_widget(QWidget* parent) : QWidget(parent)  {      W = width(); H = height();      init_image_nolock(); texture.fill(Qt::gray); -    connect(&timer, &QTimer::timeout, this, &cv_video_widget::update_and_repaint, Qt::DirectConnection); +    connect(&timer, &QTimer::timeout, this, &video_widget::update_and_repaint, Qt::DirectConnection);      timer.start(65);  } -#ifdef OTR_VIDEO_HAS_OPENCV -void cv_video_widget::update_image(const cv::Mat& frame) -{ -    QMutexLocker l(&mtx); - -    if (freshp) -        return; - -    if (W < 1 || H < 1 || frame.rows < 1 || frame.cols < 1) -        return; - -    cv::Mat const* __restrict frame_scaled = nullptr; - -    if (frame3.cols != W || frame3.rows != H) -    { -        frame3 = cv::Mat(H, W, frame.type()); -        frame2 = cv::Mat(H, W, CV_8UC4); - -        if (!frame2.isContinuous() || !frame3.isContinuous()) -            std::abort(); -    } - -    if (frame.cols != W || frame.rows != H) -    { -        cv::resize(frame, frame3, { W, H }, 0, 0, cv::INTER_NEAREST); -        frame_scaled = &frame3; -    } -    else if (!frame.isContinuous()) -    { -        frame.copyTo(frame3); -        frame_scaled = &frame3; -    } -    else -        frame_scaled = &frame; - -    freshp = true; - -    int color_cvt = 0; -    constexpr int nchannels = 4; - -    switch (frame_scaled->channels()) -    { -    case 1: -        color_cvt = cv::COLOR_GRAY2BGRA; -        break; -    case 3: -        color_cvt = cv::COLOR_BGR2BGRA; -        break; -    case nchannels: -        break; -    default: -        unreachable(); -        break; -    } - -    cv::Mat const* frame_color; - -    if (color_cvt != cv::COLOR_COLORCVT_MAX) -    { -        cv::cvtColor(*frame_scaled, frame2, color_cvt); -        frame_color = &frame2; -    } -    else -        frame_color = frame_scaled; - -    int stride = frame_color->step.p[0], rows = frame_color->rows; -    int nbytes = rows * stride; -    vec.resize(nbytes); vec.shrink_to_fit(); -    std::memcpy(vec.data(), frame_color->data, nbytes); - -    texture = QImage((const unsigned char*) vec.data(), W, H, stride, QImage::Format_ARGB32); -    texture.setDevicePixelRatio(devicePixelRatioF()); -} -#endif - -void cv_video_widget::update_image(const QImage& img) +void video_widget::update_image(const QImage& img)  {      QMutexLocker l(&mtx); @@ -118,7 +39,7 @@ void cv_video_widget::update_image(const QImage& img)      texture.setDevicePixelRatio(devicePixelRatioF());  } -void cv_video_widget::paintEvent(QPaintEvent*) +void video_widget::paintEvent(QPaintEvent*)  {      QMutexLocker foo(&mtx); @@ -132,7 +53,7 @@ void cv_video_widget::paintEvent(QPaintEvent*)      painter.drawImage(rect(), texture);  } -void cv_video_widget::update_and_repaint() +void video_widget::update_and_repaint()  {      if (!check_is_visible())          return; @@ -146,7 +67,7 @@ void cv_video_widget::update_and_repaint()      }  } -void cv_video_widget::resizeEvent(QResizeEvent*) +void video_widget::resizeEvent(QResizeEvent*)  {      QMutexLocker l(&mtx);      double dpr = devicePixelRatioF(); @@ -155,8 +76,9 @@ void cv_video_widget::resizeEvent(QResizeEvent*)      init_image_nolock();  } -void cv_video_widget::get_preview_size(int& w, int& h) +void video_widget::get_preview_size(int& w, int& h)  {      QMutexLocker l(&mtx);      w = W; h = H;  } + diff --git a/video/video-widget.hpp b/video/video-widget.hpp index b610557d..563f468c 100644 --- a/video/video-widget.hpp +++ b/video/video-widget.hpp @@ -8,45 +8,38 @@  #pragma once  #include "compat/math.hpp" +#include "export.hpp"  #include <vector> -#ifdef OTR_VIDEO_HAS_OPENCV -#   include <opencv2/core.hpp> -#endif -  #include <QWidget>  #include <QTimer>  #include <QMutex> -class cv_video_widget final : public QWidget +class OTR_VIDEO_EXPORT video_widget : public QWidget  {      Q_OBJECT  public: -    cv_video_widget(QWidget *parent); +    video_widget(QWidget* parent = nullptr); -#ifdef OTR_VIDEO_HAS_OPENCV -    void update_image(const cv::Mat& frame); -#endif      void update_image(const QImage& image);      void get_preview_size(int& w, int& h);      void resizeEvent(QResizeEvent*) override; -private slots: +protected slots:      void paintEvent(QPaintEvent*) override;      void update_and_repaint();  private: +    QTimer timer; + +protected:      QMutex mtx { QMutex::Recursive };      QImage texture;      std::vector<unsigned char> vec; -    QTimer timer; -#ifdef OTR_VIDEO_HAS_OPENCV -    cv::Mat frame2, frame3; -#endif      bool freshp = false; -    int W  = iround(QWidget::width() * devicePixelRatioF()); +    int W = iround(QWidget::width() * devicePixelRatioF());      int H = iround(QWidget::height() * devicePixelRatioF());      void init_image_nolock(); | 
