[英]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_one
内DrawScanPoints
它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.