【问题标题】:How to convert a cv::Mat to QImage or QPixmap?如何将 cv::Mat 转换为 QImage 或 QPixmap?
【发布时间】:2014-04-04 20:05:49
【问题描述】:

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

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

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

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

然后我创建了一个按钮并将这个函数链接到它

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;
}

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

【问题讨论】:

  • repaint() 完全没有必要。您不需要将该像素图存储为成员,它可以是临时的。你从哪里得到Mat2QImage?为什么你无缘无故地使用在堆上分配的QImage?哦,两个 sn-ps 之间的区别很明显:在第一个中,您设置 temp=cv::Scalar(0,0,255),在第二个中设置 temp=cv::Scalar(0,255,0)。当你测试这些东西时,你必须完全相同做同样的事情。
  • 感谢您的回答。关于配置。这只是解决问题的众多尝试之一。当我不使用 repaint() 时,什么都没有发生。而且我猜像素图可能是临时的,但这是有人在其他主题中找到的解决方案。
  • 我撤回关于重绘的评论。同样的事情发生了,所以我想你是对的,因为它是不必要的。
  • "帽子是有人在其他主题中找到的解决方案。"在使用之前,您需要准确了解假定的修复工作的原因。否则你只是让自己相信童话、传说和传说。那些属于社会文化,而不是解决问题。
  • 您的Mat2QImage 函数返回一个引用悬空指针的QImage。

标签: qt opencv qimage qpixmap


【解决方案1】:

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

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

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

#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"

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-06-28
    • 1970-01-01
    • 2012-06-16
    • 1970-01-01
    • 1970-01-01
    • 2013-05-01
    • 2023-03-09
    • 1970-01-01
    相关资源
    最近更新 更多