如何将QImage转换为opencv Mat

时间:2012-08-09 14:51:56

标签: c++ qt opencv

我在互联网上搜索过,但找不到将QImage(或QPixmap)转换为OpenCV Mat的方法。我该怎么做?。

感谢任何帮助。

5 个答案:

答案 0 :(得分:10)

在您发出此问题一年后,互联网上的答案很棒:

但是我看到它的方式,如果您同时使用Qt和OpenCV,那么键入QImage可能仅用于显示,这种情况您可能需要使用QPixmap,因为它已针对显示进行了优化。所以这就是我的工作:

  1. 将图片加载为cv::Mat,如果您想要显示图片,请使用第二篇文章中介绍的非复制方法转换为QPixmap
  2. cv::Mat
  3. 中进行图像处理
  4. 在工作流程中的任何时候,您都可以调用类似Mat2QPixmap()的内容来获得实时结果。
  5. 永远不要将QPixmap转换为cv::Mat,考虑到每种类型的目的,没有任何意义。

答案 1 :(得分:9)

如果QImage仍然存在并且您只需要对其执行快速操作,那么您可以使用QImage内存构建cv :: Mat

cv::Mat mat(image.rows(),image.cols(),CV_8UC3,image.scanline()); 这假设Qimage是3通道,即RGB888

如果Qimage消失,那么您需要复制数据,请参阅Qimage to cv::Mat convertion strange behaviour

如果QImage是Format_ARGB32_Premultiplied(优先格式),那么您需要将每个像素转换为openCV的BGR布局。 cv :: cvtcolor()函数可以在最新版本中将ARGB转换为RGB 或者,您可以在复制数据之前使用QImage::convertToformat()转换为RGB

答案 2 :(得分:1)

我尝试使用OpenCV 3.1+样式代码:

void qimage_to_mat(const QImage& image, cv::OutputArray out) {

    switch(image.format()) {
        case QImage::Format_Invalid:
        {
            Mat empty;
            empty.copyTo(out);
            break;
        }
        case QImage::Format_RGB32:
        {
            Mat view(image.height(),image.width(),CV_8UC4,(void *)image.constBits(),image.bytesPerLine());
            view.copyTo(out);
            break;
        }
        case QImage::Format_RGB888:
        {
            Mat view(image.height(),image.width(),CV_8UC3,(void *)image.constBits(),image.bytesPerLine());
            cvtColor(view, out, COLOR_RGB2BGR);
            break;
        }
        default:
        {
            QImage conv = image.convertToFormat(QImage::Format_ARGB32);
            Mat view(conv.height(),conv.width(),CV_8UC4,(void *)conv.constBits(),conv.bytesPerLine());
            view.copyTo(out);
            break;
        }
    }
}

void mat_to_qimage(cv::InputArray image, QImage& out)
{
    switch(image.type())
    {
        case CV_8UC4:
        {
            Mat view(image.getMat());
            QImage view2(view.data, view.cols, view.rows, view.step[0], QImage::Format_ARGB32);
            out = view2.copy();
            break;
        }
        case CV_8UC3:
        {
            Mat mat;
            cvtColor(image, mat, COLOR_BGR2BGRA); //COLOR_BGR2RGB doesn't behave so use RGBA
            QImage view(mat.data, mat.cols, mat.rows, mat.step[0], QImage::Format_ARGB32);
            out = view.copy();
            break;
        }
        case CV_8UC1:
        {
            Mat mat;
            cvtColor(image, mat, COLOR_GRAY2BGRA);
            QImage view(mat.data, mat.cols, mat.rows, mat.step[0], QImage::Format_ARGB32);
            out = view.copy();
            break;
        }
        default:
        {
            throw invalid_argument("Image format not supported");
            break;
        }
    }
}

答案 3 :(得分:0)

Qt 5.11(可能还有一些早期版本)的答案:

    cv::Mat mat(image.height(), image.width(),CV_8UC3, image.bits());  
    // image.scanline() does not exist, 
    //and height/width is interchanged for a matrix

同样假设QImage为RGB888(即QImage :: Format_RGB888)

答案 4 :(得分:-2)

我将图像保存到磁盘并从cv中重新打开;)

@ ^我尝试过以前的解决方案。它似乎不适合我。虽然我得到了一些图像,但它看起来像一些条形码信息类图像。我猜参数有些不匹配。