QT-从UI捕获后,用鼠标绘制opencv -imshow,不工作
我有一个QT项目,可以在其中使用OpenCV MouseCallbacks捕获网络摄像头的图像,然后在IMShow上执行图形,而不是QgraphicsView)。 我可以捕获图像并使用我的按钮显示,但是我无法绘制任何内容(甚至在我单击图像后它甚至会崩溃)。
代码:
mainwindow.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
mainwindow.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()
{
}
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
mainwindow.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>
I have this Qt Project where I can capture an Image from WebCam and afterwards draw on it using OpenCV MouseCallbacks (I perform the drawing on the imshow, not the QGraphicsView).
I can capture the Image and display it using my pushbutton, but I can't draw anything (it even crashes after I click on the Image).
Codes:
mainwindow.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
mainwindow.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()
{
}
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
mainwindow.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>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我无法在本地复制此此内容(我缺少一些源文件,例如Main和UI),但是您可能应该在
setmousecallback
中传递this
作为最后一个参数。参见我应该如何通过opencv中的指针到会员功能到setMouseCallback?进行了问题后更新了:
remove
cv :: destrionallwindows
来自on_pbt_capture_clicked
;替换CV :: Waitkey(0);
带有cv :: waitkey(30);
:原因:您从未更新“捕获”窗口:
waitkey(0)
永远键输入) - 因此,只有在按下键盘上的任何键后,您的窗口才会更新。因此,如果您更改为Waitkey(30)
更新将自动每30 [ms]发生一次(此后Waitkey
退出)。每次删除
destroyallwindows
时,无需破坏和重新创建窗口。如果您想知道何时更新on_pbt_capture_clicked
中的窗口,请使用条件变量。在中等待它,而(1)
和notify_one
它从drawscanpoints
中。I'm not able to reproduce this locally (I'm missing some of the source files, e.g. main and the UI) but probably you should pass
this
insetMouseCallback
as the last parameter. See How should I pass a pointer-to-member-function to setMouseCallback in OpenCV?Edit after question was updated:
Remove
cv::destroyAllWindows
fromon_pbt_Capture_clicked
; replacecv::waitKey(0);
withcv::waitKey(30);
:Reason: you've never updated the "capture" window:
waitKey(0)
waits forever (for any key input) - so your window will be updated with circles only after you press any key on the keyboard. So if you change towaitKey(30)
the updates will be happening every 30 [ms] automatically (timeout after whichwaitKey
exits).No need to destroy and recreate window every time hence removing
destroyAllWindows
. If you want to be smart about when to update the window inon_pbt_Capture_clicked
, use conditional variable. WAit for it insidewhile(1)
andnotify_one
it from insideDrawScanPoints
.