繁体   English   中英

Qt - 从 UI 捕获后用鼠标在 opencv-imshow 上绘图不起作用

[英]Qt - Draw on opencv-imshow with mouse after capture from UI doesn't work

我有这个 Qt 项目,我可以在其中从 WebCam 捕获图像,然后使用 OpenCV MouseCallbacks 在其上绘制(我在 imshow 上执行绘图,而不是 QGraphicsView)。 我可以捕获图像并使用我的按钮显示它,但我无法绘制任何东西(它甚至在我单击图像后崩溃)。

代码:

主窗口.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QPixmap>
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QFile>
#include <QFileDialog>
#include <QMessageBox>
#include <QTimer>

#include <opencv2/imgproc.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/core.hpp>

#include <vector>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

     static void DrawScanPoints(int event, int x, int y, int flag, void* param);
     void DrawScanPoints(int event, int x, int y);

private slots:
    void on_pbt_Capture_clicked();

    void on_pbt_Scan_clicked();

public slots:
    void UpdateFrame();

private:
    Ui::MainWindow *ui;
    cv::VideoCapture videoCap;
     cv::Mat liveImage, inputImage;
    bool camRun = true;
};
#endif // MAINWINDOW_H

主窗口.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    videoCap.open(0);

    QTimer* timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), this, SLOT(UpdateFrame()));
    timer->start(20);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::UpdateFrame()
{
    if(camRun)
    {
        videoCap.read(liveImage);

        QImage image = QImage(liveImage.data, liveImage.cols, liveImage.rows, QImage::Format_RGB888).rgbSwapped();
        QGraphicsScene* scene = new QGraphicsScene(this);
        scene->addPixmap(QPixmap::fromImage(image));

        ui->graphicsView->setScene(scene);
        ui->graphicsView->show();
    }
}

void MainWindow::DrawScanPoints(int event, int x, int y, int flag, void* param)
{
    MainWindow* mw = reinterpret_cast<MainWindow*>(param);
    mw->DrawScanPoints(event, x, y);
}

void MainWindow::DrawScanPoints(int event, int x, int y)
{
    if(event & cv::EVENT_LBUTTONDOWN)
    {
        cv::Point pt = cv::Point(x, y);
        cv::circle(inputImage, pt, 10, cv::Scalar(0, 255, 0), 1, cv::LINE_AA);
    }
}

void MainWindow::on_pbt_Capture_clicked()
{
    camRun = false;
    inputImage = liveImage;

    cv::namedWindow("Capture");
    cv::setMouseCallback("Capture", DrawScanPoints, this);

    while(1)
    {
        cv::imshow("Capture", inputImage);
        cv::waitKey(0);
        cv::destroyAllWindows();
    }
}

void MainWindow::on_pbt_Scan_clicked()
{

}


主文件

#include "mainwindow.h"

#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();
}

主窗口.ui

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>608</width>
    <height>440</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <widget class="QGraphicsView" name="graphicsView">
    <property name="geometry">
     <rect>
      <x>10</x>
      <y>10</y>
      <width>501</width>
      <height>391</height>
     </rect>
    </property>
   </widget>
   <widget class="QPushButton" name="pbt_Capture">
    <property name="geometry">
     <rect>
      <x>520</x>
      <y>10</y>
      <width>81</width>
      <height>20</height>
     </rect>
    </property>
    <property name="text">
     <string>Capture</string>
    </property>
   </widget>
   <widget class="QPushButton" name="pbt_Scan">
    <property name="geometry">
     <rect>
      <x>520</x>
      <y>40</y>
      <width>80</width>
      <height>18</height>
     </rect>
    </property>
    <property name="text">
     <string>Scan</string>
    </property>
   </widget>
  </widget>
  <widget class="QMenuBar" name="menubar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>608</width>
     <height>17</height>
    </rect>
   </property>
  </widget>
  <widget class="QStatusBar" name="statusbar"/>
 </widget>
 <resources/>
 <connections/>
</ui>

我无法在本地重现此内容(我缺少一些源文件,例如 main 和 UI),但您可能应该在setMouseCallback this作为最后一个参数传递。 请参阅如何在 OpenCV 中将指向成员函数的指针传递给 setMouseCallback?

问题更新后编辑:

on_pbt_Capture_clicked删除cv::destroyAllWindows 替换cv::waitKey(0); cv::waitKey(30);

void MainWindow::on_pbt_Capture_clicked()
{
    camRun = false;
    inputImage = liveImage;

    cv::namedWindow("Capture");
    cv::setMouseCallback("Capture", DrawScanPoints, this);

    while(1)
    {
        cv::imshow("Capture", inputImage);
        cv::waitKey(30);
    }
}

原因:您从未更新过“捕获”窗口: waitKey(0)将永远等待(对于任何键输入) - 因此只有在您按下键盘上的任何键后,您的窗口才会更新为圆圈。 因此,如果您更改为waitKey(30) ,更新将每 30 [ms] 自动发生一次(超时后waitKey退出)。

无需每次都销毁和重新创建窗口,因此删除了destroyAllWindows 如果您想知道何时更新on_pbt_Capture_clicked中的窗口,请使用条件变量。 while(1)内等待它,并从notify_oneDrawScanPoints它。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM