我想将现有的openCV应用程序包含到使用Qt创建的GUI中。我在stackoverflow上发现了一些类似的问题
QT How to embed an application into QT widget
Run another executable in my Qt app
问题是,我不想像QProcess那样简单地启动openCV应用程序。 OpenCV应用程序有一个" MouseListener",所以如果我点击窗口,它仍然应该调用openCV应用程序的功能。我还想在Qt GUI的标签中显示检测到的坐标。因此,它必须是某种互动。
我已经阅读了关于createwindowContainer函数(http://blog.qt.io/blog/2013/02/19/introducing-qwidgetcreatewindowcontainer/)但由于我对Qt不是很熟悉,我不确定这是否是正确的选择以及如何使用它。
我使用的是Linux Mint 17.2,opencv 3.1.0和Qt version 4.8.6
感谢您的意见
答案 0 :(得分:0)
我还没有真正解决过我想要的问题。但现在它正在发挥作用。如果有人遇到同样的问题,也许我的解决方案可以提供一些想法。如果你想用qt显示视频或者你有OpenCV库的问题,也许我可以提供帮助。
以下是一些代码片段。他们的评论不是很多,但我希望这个概念很明确:
首先,我有一个带有标签的MainWindow,我将其提升为CustomLabel的类型。 CustomLabel是我的容器,用于显示视频并对我的鼠标输入作出反应。
CustomLabel::CustomLabel(QWidget* parent) : QLabel(parent), currentImage(NULL),
tickrate_ms(33), vid_fps(0), video_width(0), video_height(0), myTimer(NULL), cap(NULL)
{
// init variables
showPoints = true;
calculatedCenter = cv::Point(0,0);
oldCenter = cv::Point(0,0);
currentState = STATE_NO_STREAM;
NOF_corners = 30; //default init value
termcrit = cv::TermCriteria(cv::TermCriteria::COUNT | cv::TermCriteria::EPS, 30,0.01);
// enable mouse Tracking
this->setMouseTracking(true);
// connect signals with slots
QObject::connect(getMainWindow(), SIGNAL(sendFileOpen()), this, SLOT(onOpenClick()));
QObject::connect(getMainWindow(), SIGNAL(sendWebcamOpen()), this, SLOT(onWebcamBtnOpen()));
QObject::connect(getMainWindow(), SIGNAL(closeVideoStreamSignal()), this, SLOT(onCloseVideoStream()));
}
你必须覆盖paintEvent-Method:
void CustomLabel::paintEvent(QPaintEvent *e){
QPainter painter(this);
// When no image is loaded, paint the window black
if (!currentImage){
painter.fillRect(QRectF(QPoint(0, 0), QSize(width(), height())), Qt::black);
QWidget::paintEvent(e);
return;
}
// Draw a frame from the video
drawVideoFrame(painter);
QWidget::paintEvent(e);
}
在paintEvent中调用的方法:
void CustomLabel::drawVideoFrame(QPainter &painter){
painter.drawImage(QRectF(QPoint(0, 0), QSize(width(), height())), *currentImage,
QRectF(QPoint(0, 0), currentImage->size()));
}
在我的计时器的每个刻度线上,我都会打电话给onTick()
void CustomLabel::onTick() {
/* This method is called every couple of milliseconds.
* It reads from the OpenCV's capture interface and saves a frame as QImage
* the state machine is implemented here. every tick is handled
*/
if(cap->isOpened()){
switch(currentState) {
case STATE_IDLE:
if (!cap->read(currentFrame)){
qDebug() << "cvWindow::_tick !!! Failed to read frame from the capture interface in STATE_IDLE";
}
break;
case STATE_DRAWING:
if (!cap->read(currentFrame)){
qDebug() << "cvWindow::_tick !!! Failed to read frame from the capture interface in STATE_DRAWING";
}
currentFrame.copyTo(currentCopy);
cv::circle(currentCopy, cv::Point(focusPt.x*xScale, focusPt.y*yScale),
sqrt((focusPt.x - currentMousePos.x())*(focusPt.x - currentMousePos.x())*xScale*xScale+(focusPt.y - currentMousePos.y())*
(focusPt.y - currentMousePos.y())*yScale*yScale), cv::Scalar(0, 0, 255), 2, 8, 0);
//qDebug() << "focus pt x " << focusPt.x << "y " << focusPt.y;
break;
case STATE_TRACKING:
if (!cap->read(currentFrame)){
qDebug() << "cvWindow::_tick !!! Failed to read frame from the capture interface in STATE_TRACKING";
}
cv::cvtColor(currentFrame, currentFrame, CV_BGR2GRAY, 0);
if(initGrayFrame){
currentGrayFrame.copyTo(previousGrayFrame);
initGrayFrame = false;
return;
}
cv::calcOpticalFlowPyrLK(previousGrayFrame, currentFrame, previousPts, currentPts, featuresFound, err, cv::Size(21, 21),
3, termcrit, 0, 1e-4);
AcquireNewPoints();
currentCopy = CalculateCenter(currentFrame, currentPts);
if(showPoints){
DrawPoints(currentCopy, currentPts);
}
break;
case STATE_LOST_POLE:
currentState = STATE_IDLE;
initGrayFrame = true;
cv::cvtColor(currentFrame, currentFrame, CV_GRAY2BGR);
break;
default:
break;
}
// if not tracking, draw currentFrame
// OpenCV uses BGR order, convert it to RGB
if(currentState == STATE_IDLE) {
cv::cvtColor(currentFrame, currentFrame, CV_BGR2RGB);
memcpy(currentImage->scanLine(0), (unsigned char*)currentFrame.data, currentImage->width() * currentImage->height() * currentFrame.channels());
} else {
cv::cvtColor(currentCopy, currentCopy, CV_BGR2RGB);
memcpy(currentImage->scanLine(0), (unsigned char*)currentCopy.data, currentImage->width() * currentImage->height() * currentCopy.channels());
previousGrayFrame = currentFrame;
previousPts = currentPts;
}
}
// Trigger paint event to redraw the window
update();
}
不要介意yScale和xScale因素,它们仅适用于opencv绘图函数,因为customLabel大小与视频分辨率不同
答案 1 :(得分:0)
OpenCV仅用于图像处理。如果您知道将cv :: Mat转换为任何其他所需格式,则可以将OpenCV与任何GUI开发工具包一起使用。对于Qt,您可以将cv :: Mat转换为QImage,然后在Qt SDK中的任何位置使用它。此示例显示了OpenCV和Qt集成,包括线程和网络摄像头访问。使用OpenCV访问网络摄像头,并将接收到的cv :: Mat转换为QImage并渲染到QLabel上。 https://github.com/nickdademo/qt-opencv-multithreaded 该代码包含MatToQImage()函数,该函数显示从cv :: Mat到QImage的转换。集成非常简单,因为一切都在C ++中。