如何将 cv::Mat 转换为 QImage 或 QPixmap? [英] How to convert a cv::Mat to QImage or QPixmap?

查看:163
本文介绍了如何将 cv::Mat 转换为 QImage 或 QPixmap?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试环顾四周,尝试了我找到的所有方法,但还没有找到解决此问题的方法.

I've tried to look around and tried everything I've found, but haven't found a solution for this problem.

我正在尝试通过单击按钮来更新 QT 应用程序中的图像.

I'm trying to update an image in a QT application by button click.

在构造函数中,我设法显示了一个图像:

In the constructor I've managed to show a image:

    cv::Mat temp = cv::Mat(*this->cv_size,CV_8UC3);
    temp = cv::Scalar(0,255,155);
    ui->image->setPixmap(QPixmap::fromImage( Mat2QImage(temp)));

然后我创建了一个按钮并将此功能链接到它

And then I've created a button and linked this function to it

void UIQT::refreshImage(){
    cv::Mat temp = cv::Mat(*this->cv_size,CV_8UC3);
    temp = cv::Scalar(0,255,0);
    ui->image->setPixmap(QPixmap::fromImage( Mat2QImage(temp)));
    std::cout << "refreshed" << std::endl;
}

功能如下:

QImage UIQT::Mat2QImage(cv::Mat const& src) {
    cv::Mat temp(src.cols,src.rows,src.type());
    cvtColor(src, temp,CV_BGR2RGB);
    QImage dest= QImage((uchar*) temp.data, temp.cols, temp.rows, temp.step, QImage::Format_RGB888);

    return dest;
}

但是当我按下按钮时,整个图像变成白色.有人有想法吗?

But when I hit the button the whole image turns white. Anyone got an idea?

推荐答案

您的代码似乎非常复杂,而且您做了很多不必要的事情.没有理由让 cv_size 一个指针.您应该只使用 cv::Size 的实例.您的 Mat2QImage 返回一个带有指向其数据的悬空指针的 QImage.

Your code seems to be hopelessly convoluted and you do a lot of unnecessary things. There's no reason to have cv_size a pointer. You should just use an instance of cv::Size. Your Mat2QImage returns a QImage with a dangling pointer to its data.

下面的代码是一个完整的、经过测试的示例.它维护了其他不必要的 Ui 命名空间等,只是为了使其类似于您现有的代码库.

The code below is a complete, tested example. It maintains the otherwise unnecessary Ui namespace etc. just to make it similar to your existing code base.

一些公开的 Mat2QImage 样式方法被破坏,因为它们返回一个 QImage 使用垫子的数据而不保留对它的引用.如果源 mat 不复存在,图像会引用一个悬空指针,任何事情都可能发生.那是你的问题.下面的版本在这方面是正确的.

Some publicized Mat2QImage-style methods are broken as they return a QImage that uses the mat's data without retaining a reference to it. If the source mat ceases to exist, the image references a dangling pointer, and anything can happen. That was your problem. The version below is correct in this respect.

#include <QApplication>
#include <QBasicTimer>
#include <QImage>
#include <QPixmap>
#include <QGridLayout>
#include <QLabel>
#include <opencv2/opencv.hpp>

namespace Ui { struct UIQT {
  QLabel * image;
  void setupUi(QWidget * w) {
    QGridLayout * layout = new QGridLayout(w);
    layout->addWidget((image = new QLabel));
  }
}; }

class UIQT : public QWidget {
  Q_OBJECT
  Ui::UIQT ui;
  QBasicTimer m_timer;
  cv::Size m_size;
  void timerEvent(QTimerEvent *);
public:
  UIQT(QWidget * parent = 0);
  ~UIQT();
  Q_SLOT void refreshImage();
};

void matDeleter(void* mat) { delete static_cast<cv::Mat*>(mat); }

static QImage imageFromMat(cv::Mat const& src) {
  Q_ASSERT(src.type() == CV_8UC3);
  cv::Mat * mat = new cv::Mat(src.cols,src.rows,src.type());
  cvtColor(src, *mat, CV_BGR2RGB);
  return QImage((uchar*)mat->data, mat->cols, mat->rows, mat->step,
                QImage::Format_RGB888, &matDeleter, mat);
}

static cv::Scalar randomScalar() {
  static cv::RNG rng(12345);
  return cv::Scalar(rng.uniform(0,255), rng.uniform(0, 255), rng.uniform(0, 255));
}

static QPixmap pixmapFromMat(const cv::Mat & src) {
  QImage image(imageFromMat(src));
  return QPixmap::fromImage(image);
}

UIQT::UIQT(QWidget * parent) :
  QWidget(parent),
  m_size(100, 100)
{
  ui.setupUi(this);
  m_timer.start(500, this);
  refreshImage();
}

UIQT::~UIQT() {}

void UIQT::timerEvent(QTimerEvent * ev) {
  if (ev->timerId() != m_timer.timerId()) return;
  refreshImage();
}

void UIQT::refreshImage() {
  cv::Mat mat(m_size, CV_8UC3, randomScalar());
  ui.image->setPixmap(pixmapFromMat(mat));
}

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

#include "main.moc"

这篇关于如何将 cv::Mat 转换为 QImage 或 QPixmap?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆