opencv mat недоступен функцией gtkmm DrawingArea on_draw - PullRequest
0 голосов
/ 08 мая 2019

Я пытаюсь сделать снимок экрана и отобразить содержимое в области рисования в системе Linux с помощью c ++.

Я комбинирую код из разных сообщений.Когда снимок экрана сделан, мат хорош, и содержимое может быть отображено с помощью imshow, но однажды внутри функции on_draw размеры, строки и столбцы верны, но данные плохие.

Обновление:Проблема была решена путем удаления экрана из обратного вызова on_draw.Почему предотвращается чтение мата из колбэка?

источники: снимок экрана , с использованием opencv с gtkmm

HelloWorld.h

#include <gtkmm.h>
#include "ScreenDisplay.h"

class HelloWorld : public Gtk::Window
{

public:
  HelloWorld();
  virtual ~HelloWorld();

protected:
  Gtk::Box m_box;
  Gtk::Notebook m_notebook;
  void on_button_clicked();
private:
  ScreenDisplay m_screenDisplay;
  Gtk::ScrolledWindow m_scrolledWindow;

  Gtk::Button m_button;
};

HelloWorld.cpp

#include "HelloWorld.h"

HelloWorld::HelloWorld()
{
    m_scrolledWindow.set_min_content_width(1000);
    m_scrolledWindow.set_min_content_height(1000);
    m_scrolledWindow.add(m_screenDisplay);

    m_button.signal_clicked().connect(sigc::mem_fun(*this, &HelloWorld::on_button_clicked));
    m_button.set_label("screenshot");

    m_box.set_orientation(Gtk::ORIENTATION_VERTICAL);
    m_box.pack_start(m_scrolledWindow, TRUE, TRUE);
    m_box.pack_start(m_button, FALSE, FALSE);

    add(m_box);
    show_all();
}

HelloWorld::~HelloWorld()
{
}

void HelloWorld::on_button_clicked()
{
    m_screenDisplay.TakeScreenshot();
}

ScreenDisplay.h

#include <gtkmm.h>
#include "opencv2/core/core.hpp"

class ScreenDisplay : public Gtk::DrawingArea
{
public:
    ScreenDisplay();
    virtual ~ScreenDisplay();
    void TakeScreenshot();

protected:
    bool on_draw(const Cairo::RefPtr<Cairo::Context>& cr) override;
private:
    cv::Mat m_screenShot;
};

ScreenDisplay.cpp

#include "ScreenDisplay.h"
#include <X11/Xlib.h>
#include <X11/Xutil.h>

#include "opencv2/imgproc/imgproc.hpp"
#include <gdkmm/pixbuf.h>
#include <cairomm/context.h>
#include <gdkmm/general.h>
using namespace cv;

struct ScreenShot
{
    ScreenShot(int x, int y, int width, int height):
        x(x),
        y(y),
        width(width),
        height(height)
    {
        display = XOpenDisplay(nullptr);
        root = DefaultRootWindow(display);

        init = true;
    }

    void operator() (cv::Mat& cvImg)
    {
        if(init == true)
            init = false;
        else
            XDestroyImage(img);

        img = XGetImage(display, root, x, y, width, height, AllPlanes, ZPixmap);

        cvImg = cv::Mat(height, width, CV_8UC4, img->data);
    }

    ~ScreenShot()
    {
        if(init == false)
            XDestroyImage(img);

        XCloseDisplay(display);
    }

    Display* display;
    Window root;
    int x,y,width,height;
    XImage* img;

    bool init;
};


ScreenDisplay::ScreenDisplay() 
{ 
}

ScreenDisplay::~ScreenDisplay() { }

void ScreenDisplay::TakeScreenshot()
{
   ScreenShot screen(0, 0, 1920, 1080);
   screen(m_screenShot);
   Glib::RefPtr<Gdk::Window> win = get_window();
   Gdk::Rectangle r(0, 0, get_allocation().get_width(), get_allocation().get_height());
   win->invalidate_rect(r, false);
}

bool ScreenDisplay::on_draw(const Cairo::RefPtr<Cairo::Context>& cr)
{
    if (!m_screenShot.empty())
    {
       cv::Mat cv_frame1;
       cv::cvtColor (m_screenShot, cv_frame1, CV_BGR2RGB);
       Gdk::Cairo::set_source_pixbuf (cr, Gdk::Pixbuf::create_from_data(cv_frame1.data, Gdk::COLORSPACE_RGB, false, 8, cv_frame1.cols, cv_frame1.rows, cv_frame1.step));
       cr->paint();
    }

   return true;
}
...