如何在 Qt GUI 应用程序中工作循环并显示 qimage

Posted

技术标签:

【中文标题】如何在 Qt GUI 应用程序中工作循环并显示 qimage【英文标题】:how to work the loop in Qt GUI application and display the qimage 【发布时间】:2014-08-24 05:44:10 【问题描述】:

我是 Qt 和 OpenCV 的新手,需要帮助解决以下问题。

我正在开发一个代码来计算进入公园的车辆数量。预先获得的输入视频用于开发算法。为此,我选择了一个带有 OpenCV 的 Qt 小部件应用程序。目前在编译时,会跳过下面的循环。

for( ; contour != 0; contour = contour->h_next ) 

                
                    bndRect = cvBoundingRect(contour, 0);

                    ui->txtXYnew->appendPlainText("one contour");
                    pt1.x = bndRect.x;
                    pt1.y = bndRect.y;
                    pt2.x = bndRect.x + bndRect.width;
                    pt2.y = bndRect.y + bndRect.height;

                    printf("--------------------\n");
                 cvRectangle(newImage, pt1, pt2, CV_RGB(255,0,0), 1); 
                 

然后编译移至下一部分。为什么会这样,我是不是用错了定时器功能? (我在控制台应用程序中对此进行了测试,它在 Qt 和 Visual Studio 中都运行良好)。

我使用了两个标签,一个用于显示输入帧,第二个用于处理后的帧。当前在已处理的帧中显示黑色帧。但它应该显示处理后的框架,并在轮廓周围绘制矩形。

有什么方法可以纠正这个代码吗?下面是完整的代码。

#include "dialog.h"
#include "ui_dialog.h"
#include  <QtCore>
#include  <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv/cv.h>
using namespace cv;

using namespace std;

Dialog::Dialog(QWidget *parent) :QDialog(parent), ui(new Ui::Dialog)

ui->setupUi(this);

inputMovie = cvCaptureFromAVI("E:\\pk.avi");
if (!inputMovie)
   ui->txtXYnew->appendPlainText("error video");
   return;



tmrTimer=new QTimer(this);
connect(tmrTimer,SIGNAL(timeout()),this,SLOT(processedframesandudateGUI()));
tmrTimer->start(25);



//////////////////////////////////////////////////////////////////////////////////
Dialog::~Dialog()

delete ui;


/////////////////////////////////////////////////////////////////////////////////
void Dialog::processedframesandudateGUI()

    CvRect bndRect = cvRect(0,0,0,0);

    CvPoint pt1, pt2;


    CvSize imgSize;
    imgSize.width = 540;
    imgSize.height = 432;
greyImage = cvCreateImage( imgSize, IPL_DEPTH_8U, 1);
movingAverage = cvCreateImage( imgSize, IPL_DEPTH_32F, 3);
colourImage = cvQueryFrame(inputMovie);


bool first = true;


        if(!colourImage)
            ui->txtXYnew->appendPlainText("no frames");
            return;

        if(first)
                
                        difference = cvCloneImage(colourImage);
                        temp = cvCloneImage(colourImage);
                        cvConvertScale(colourImage, movingAverage, 1.0, 0.0);

                    first = false;
                

        cvConvertScale(movingAverage, temp, 1.0, 0.0);
        cvAbsDiff(colourImage,temp,difference);


        cvCvtColor(difference, greyImage, CV_RGB2GRAY);

        cvThreshold(greyImage,greyImage, 70, 255, CV_THRESH_BINARY);


        newImage = cvCloneImage(colourImage);

        cvDilate(greyImage, greyImage, 0, 18);
        cvErode(greyImage, greyImage, 0, 10);

       CvMemStorage* storage = cvCreateMemStorage(0);
       CvSeq* contour = 0;

         ui->txtXYnew->appendPlainText("contour");
         printf("******\n");

  cvFindContours( greyImage, storage, &contour, sizeof(CvContour), CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);


              for( ; contour != 0; contour = contour->h_next )

                
                    bndRect = cvBoundingRect(contour, 0);

                    ui->txtXYnew->appendPlainText("one contour");
                    pt1.x = bndRect.x;
                    pt1.y = bndRect.y;
                    pt2.x = bndRect.x + bndRect.width;
                    pt2.y = bndRect.y + bndRect.height;

                    printf("--------------------\n");
                 cvRectangle(newImage, pt1, pt2, CV_RGB(255,0,0), 1);


                

     printf("here\n");

    cvCvtColor(colourImage, colourImage, CV_BGR2RGB);
    QImage qimgOriginal((uchar*)colourImage->imageData,colourImage->width, colourImage->height, colourImage->widthStep, QImage::Format_RGB888);
    QImage qimgProcessed((uchar*)newImage->imageData,newImage->width, newImage->height, newImage->widthStep, QImage::Format_RGB888);

    ui->label->setPixmap(QPixmap::fromImage(qimgOriginal));
    ui->label->resize(ui->label->pixmap()->size());
    ui->txtXYnew->appendPlainText("one frame");

    ui->label_2->setPixmap(QPixmap::fromImage(qimgProcessed));
    ui->label_2->resize(ui->label_2->pixmap()->size());

    cvReleaseImage(&temp);
    cvReleaseImage(&difference);
    cvReleaseImage(&greyImage);
    cvReleaseImage(&movingAverage);





///////////////////////////////////////////////////////////////////////////////////////
void Dialog::on_pushButton_clicked()


if(tmrTimer->isActive()==true)

    tmrTimer->stop();
    ui->pushButton->setText("resume");

else

    tmrTimer->start(25);
    ui->pushButton->setText("pause");




下面显示了 dialog.h(头文件)代码。

#ifndef DIALOG_H
#define DIALOG_H
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace std;
using namespace cv;

//////////////////////////////////////////////////////////////
#include <QDialog>

namespace Ui 
class Dialog;

/////////////////////////////////////////////////////////////////////////
class Dialog : public QDialog

Q_OBJECT


public:
explicit Dialog(QWidget *parent = 0);
~Dialog();


public slots:
void processedframesandudateGUI();

private slots:

void on_pushButton_clicked();

private:
Ui::Dialog *ui;

QImage qimgOriginal;
QImage qimgProcessed;

IplImage* greyImage ;
IplImage* colourImage;
IplImage* newImage;
IplImage* movingAverage ;
IplImage* difference;
IplImage* temp;
CvCapture* inputMovie;
QTimer *tmrTimer;



;

#endif // DIALOG_H

编辑:

我仍然没有找到任何运气。我放松了切尔诺贝利描述的方法,它也跳过了循环。任何人都可以解决这个问题。我正在使用带有 MinGW 的 Windows 32 位 Qt 5.3.1,此代码在控制台应用程序上完美编译。任何支持人员。仍在等待答案。

【问题讨论】:

在 qimgProcessed 中将 QImage::Format_RGB888 更改为 QImage::Format_Indexed8。有效吗? 不,先生,它没有……我已经试过了。在这里,我必须在移动的车辆周围绘制一个红色矩形来显示彩色图像。所以我想我必须使用 RGB888。我想这对你有帮助。关于为什么跳过那个循环的任何建议。我对qt界面不太熟悉。感谢您对我的问题感兴趣.. 我也在 Qt+ opencv 中工作,但我使用另一个 opencv 元素来做类似的事情,我可以给你一个我的代码 sn-p,它可以在我的计算机上完美运行,但在我的代码中我没有使用 CvMemStorage、CvSeq(我的 OpenCV 版本 - 2.4.9)等。你想要这个吗? 那会很棒先生。如果你有一个工作的请提供它。我没有在我的代码上开发此代码。所以我总是可以改变这个。我熟悉opencv中的c和c++ api。 (小 c++)。唯一的问题是我是 qt 界面的新手。再次感谢您的兴趣。(我使用 opencv 2.4.8 版)。先生,您可以在此处发布或这是我的电子邮件。 dazzirulz@gmail.com 【参考方案1】:

在您的代码中,您初始化“轮廓”

CvSeq* 轮廓 = 0;

归零。接下来是条件为'contour != 0;'的循环

for( ; 轮廓 != 0; 轮廓 = 轮廓->h_next )

这样,编译器识别出执行循环体的条件永远不会满足并跳过循环体。

【讨论】:

先生,我已经在 qt 和 Visual Studio 控制台应用程序中编译了我的代码,它提供了所需的输出。那么如何跳过这个条件。感谢您的建议和兴趣。你能建议一种方法来克服这个问题吗?【参考方案2】:

我认为所有其他代码都正常并且运行良好,所以我展示了我的循环,我尝试让我的代码适应你的,但我不太确定。

//this is our containers
        std::vector<std::vector<cv::Point> > contours; // Vector for storing contour
        std::vector<cv::Vec4i> hierarchy;
        cv::Rect rect;

//now we try to find contours on the grayscale image
        findContours( greyImage, contours, hierarchy,CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE );

        for( int i = 0; i< contours.size(); i++ ) // iterate through each contour.
         
          double a = contourArea( contours[i],false);  //  Find the area of contour

          if(a > 30)//you can delete this lines if you don't want search big contours
          
          rect = boundingRect(contours[i]); // Find the bounding rectangle 
          cv::Point2f centerCircle;
          float rad;
          cv::minEnclosingCircle(contours[i],centerCircle,rad);//search circle
          cv::rectangle(newImage, rect,  cv::Scalar(255,0,0),1, 8,0);//draw rect
          cv::circle(newImage, centerCircle,rad,  cv::Scalar(255,0,0),1, 8,0);//draw circle

         
         

设置图片但是这个用处不大

cv::cvtColor(frame,frame,CV_BGR2RGB);
cv::resize(frame,frame,cv::Size2i(ui->label->geometry().width(),ui->label->geometry().height()));
QImage image1((uchar*)frame.data,frame.cols,frame.rows,frame.step,QImage::Format_RGB888);
QPixmap px1(QPixmap::fromImage(image1));
ui->label_2->setPixmap(px1);

【讨论】:

先生感谢您的快速回复。我编译了您的代码并添加了两条 printf 行,一条在 for 循环中,一条在 if 条件中。可悲的是,代码没有进入 for 循环,它跳过该部分并移动到下一部分打印“here”。

以上是关于如何在 Qt GUI 应用程序中工作循环并显示 qimage的主要内容,如果未能解决你的问题,请参考以下文章

如何通过 Qt gui 应用程序显示视频的帧?

XCTest 中的 IOS -NSRunLoop:如何让运行循环在单元测试中工作?

Qt 崩溃中工作线程的删除和清理

QThread 和 GUI 线程说明

如何让 Richfaces 组件在按需加载的弹出窗口中工作?

Qt如何在循环中更新GUI